Skip to main content

SDK Guide

Galadriel provides official SDKs for Python and TypeScript/JavaScript. These SDKs offer type-safe, idiomatic interfaces for interacting with the GPU marketplace.

Installation

pip install galadriel

Python SDK

Quick Start

from galadriel import Client

# Initialize client
client = Client(api_token="your_token_here")

# Create market order
order = client.orders.create(
    side="buy",
    type="market",
    gpu_type="h100",
    gpu_count=16,
    duration_hours=24,
    zone="us-west-1"
)

print(f"Order ID: {order.order_id}")
print(f"Status: {order.status}")
print(f"Lease ID: {order.lease_id}")

# Get kubeconfig
if order.lease_id:
    lease = client.leases.get(order.lease_id)
    lease.save_kubeconfig("~/.kube/galadriel.conf")

Configuration

from galadriel import Client

# From environment variable
import os
client = Client(api_token=os.getenv("GALADRIEL_TOKEN"))

# With custom base URL
client = Client(
    api_token="your_token",
    base_url="https://api.galadriel.com/v1"
)

# With timeout
client = Client(
    api_token="your_token",
    timeout=30  # seconds
)

Marketplace Operations

Create Orders

# Market order (instant)
market_order = client.orders.create(
    side="buy",
    type="market",
    gpu_type="h100",
    gpu_count=16,
    duration_hours=24,
    zone="us-west-1"
)

# Limit order (wait for price)
limit_order = client.orders.create(
    side="buy",
    type="limit",
    gpu_type="h100",
    gpu_count=16,
    duration_hours=24,
    limit_price=3.20,
    zone="us-west-1",
    start_time="2025-11-11T14:00:00Z"
)

# Flexible order (best price)
flex_order = client.orders.create(
    side="buy",
    type="flexible",
    gpu_type="h200",
    gpu_count=16,
    duration_hours=24,
    limit_price=5.00,
    zone="us-west-1",
    start_time="2025-11-11T14:00:00Z",
    flex_window_hours=48
)

List and Get Orders

# List all orders
orders = client.orders.list()
for order in orders:
    print(f"{order.order_id}: {order.status}")

# Filter by status
pending_orders = client.orders.list(status="pending")
filled_orders = client.orders.list(status="filled")

# Get specific order
order = client.orders.get("ord_abc123")
print(f"Filled: {order.filled_gpus}/{order.gpu_count} GPUs")

Cancel Orders

# Cancel order
client.orders.cancel("ord_abc123")

# With order object
order = client.orders.get("ord_abc123")
order.cancel()

View Orderbook

# Get orderbook
orderbook = client.orderbook.get(
    instance_type="8xh100",
    zone="us-west-1"
)

print(f"Best Bid: ${orderbook.market_depth.best_bid}")
print(f"Best Ask: ${orderbook.market_depth.best_ask}")
print(f"Spread: ${orderbook.market_depth.spread}")

# Get bids and asks
for bid in orderbook.bids:
    print(f"  ${bid.price}/hr: {bid.gpus} GPUs")

for ask in orderbook.asks:
    print(f"  ${ask.price}/hr: {ask.gpus} GPUs")

Price Estimates

# Get price estimate
estimate = client.prices.estimate(
    instance_type="8xh100",
    gpu_count=16,
    zone="us-west-1"
)

print(f"Estimated price: ${estimate.estimated_price}/hr")
print(f"Sufficient liquidity: {estimate.sufficient_liquidity}")

# Historical prices
prices = client.prices.history(
    instance_type="8xh100",
    zone="us-west-1",
    start="2025-11-01T00:00:00Z",
    end="2025-11-07T23:59:59Z",
    interval="1h"
)

for price in prices:
    print(f"{price.timestamp}: ${price.close}/hr (volume: {price.volume})")

Lease Management

# List leases
leases = client.leases.list(status="active")
for lease in leases:
    print(f"{lease.lease_id}: {lease.gpu_count} GPUs, expires {lease.end_time}")

# Get lease details
lease = client.leases.get("lse_xyz123")
print(f"Nodes: {lease.nodes}")
print(f"Namespace: {lease.namespace}")
print(f"SSH: {lease.ssh_endpoints}")

# Get kubeconfig
kubeconfig = lease.get_kubeconfig()
# or
lease.save_kubeconfig("~/.kube/galadriel.conf")

# Terminate lease
lease.terminate()

Reselling

# Resell unused time
resell_order = client.leases.resell(
    lease_id="lse_xyz123",
    limit_price=3.00,
    available_from="2025-11-12T18:00:00Z"
)

print(f"Resell order ID: {resell_order.order_id}")
print(f"Potential recovery: ${resell_order.potential_recovery}")
print(f"Net recovery: ${resell_order.net_recovery} (after 15% fee)")

# Or use lease object
lease = client.leases.get("lse_xyz123")
resell_order = lease.resell(
    limit_price=3.00,
    available_from="2025-11-12T18:00:00Z"
)

Error Handling

from galadriel import GaladrielError, InsufficientLiquidityError, RateLimitError

try:
    order = client.orders.create(
        side="buy",
        type="market",
        gpu_type="h100",
        gpu_count=16,
        duration_hours=24,
        zone="us-west-1"
    )
except InsufficientLiquidityError:
    print("No liquidity available. Try a limit order.")
except RateLimitError:
    print("Rate limit exceeded. Wait before retrying.")
except GaladrielError as e:
    print(f"API error: {e.message}")

Async Support

from galadriel import AsyncClient
import asyncio

async def main():
    client = AsyncClient(api_token="your_token")

    # Async operations
    order = await client.orders.create(
        side="buy",
        type="market",
        gpu_type="h100",
        gpu_count=16,
        duration_hours=24,
        zone="us-west-1"
    )

    print(f"Order ID: {order.order_id}")

    await client.close()

asyncio.run(main())

Type Hints

The Python SDK is fully typed:
from galadriel import Client, Order, Lease, Orderbook
from typing import List

client: Client = Client(api_token="your_token")

# Type-safe operations
order: Order = client.orders.create(...)
orders: List[Order] = client.orders.list()
lease: Lease = client.leases.get("lse_xyz123")
orderbook: Orderbook = client.orderbook.get(...)

TypeScript SDK

Quick Start

import { GaladrielClient } from '@galadriel/sdk';

// Initialize client
const client = new GaladrielClient({
  apiToken: process.env.GALADRIEL_TOKEN
});

// Create market order
const order = await client.orders.create({
  side: 'buy',
  type: 'market',
  gpuType: 'h100',
  gpuCount: 16,
  durationHours: 24,
  zone: 'us-west-1'
});

console.log(`Order ID: ${order.orderId}`);
console.log(`Status: ${order.status}`);
console.log(`Lease ID: ${order.leaseId}`);

// Get kubeconfig
if (order.leaseId) {
  const lease = await client.leases.get(order.leaseId);
  console.log(lease.kubeconfig);
}

Configuration

import { GaladrielClient } from '@galadriel/sdk';

// Basic configuration
const client = new GaladrielClient({
  apiToken: process.env.GALADRIEL_TOKEN
});

// Custom configuration
const client = new GaladrielClient({
  apiToken: 'your_token',
  baseUrl: 'https://api.galadriel.com/v1',
  timeout: 30000  // milliseconds
});

Marketplace Operations

Create Orders

// Market order (instant)
const marketOrder = await client.orders.create({
  side: 'buy',
  type: 'market',
  gpuType: 'h100',
  gpuCount: 16,
  durationHours: 24,
  zone: 'us-west-1'
});

// Limit order (wait for price)
const limitOrder = await client.orders.create({
  side: 'buy',
  type: 'limit',
  gpuType: 'h100',
  gpuCount: 16,
  durationHours: 24,
  limitPrice: 3.20,
  zone: 'us-west-1',
  startTime: '2025-11-11T14:00:00Z'
});

// Flexible order (best price)
const flexOrder = await client.orders.create({
  side: 'buy',
  type: 'flexible',
  gpuType: 'h200',
  gpuCount: 16,
  durationHours: 24,
  limitPrice: 5.00,
  zone: 'us-west-1',
  startTime: '2025-11-11T14:00:00Z',
  flexWindowHours: 48
});

List and Get Orders

// List all orders
const orders = await client.orders.list();
orders.forEach(order => {
  console.log(`${order.orderId}: ${order.status}`);
});

// Filter by status
const pendingOrders = await client.orders.list({ status: 'pending' });
const filledOrders = await client.orders.list({ status: 'filled' });

// Get specific order
const order = await client.orders.get('ord_abc123');
console.log(`Filled: ${order.filledGpus}/${order.gpuCount} GPUs`);

Cancel Orders

// Cancel order
await client.orders.cancel('ord_abc123');

View Orderbook

// Get orderbook
const orderbook = await client.orderbook.get({
  instanceType: '8xh100',
  zone: 'us-west-1'
});

console.log(`Best Bid: $${orderbook.marketDepth.bestBid}`);
console.log(`Best Ask: $${orderbook.marketDepth.bestAsk}`);
console.log(`Spread: $${orderbook.marketDepth.spread}`);

// Get bids and asks
orderbook.bids.forEach(bid => {
  console.log(`  $${bid.price}/hr: ${bid.gpus} GPUs`);
});

orderbook.asks.forEach(ask => {
  console.log(`  $${ask.price}/hr: ${ask.gpus} GPUs`);
});

Price Estimates

// Get price estimate
const estimate = await client.prices.estimate({
  instanceType: '8xh100',
  gpuCount: 16,
  zone: 'us-west-1'
});

console.log(`Estimated price: $${estimate.estimatedPrice}/hr`);
console.log(`Sufficient liquidity: ${estimate.sufficientLiquidity}`);

// Historical prices
const prices = await client.prices.history({
  instanceType: '8xh100',
  zone: 'us-west-1',
  start: '2025-11-01T00:00:00Z',
  end: '2025-11-07T23:59:59Z',
  interval: '1h'
});

prices.forEach(price => {
  console.log(`${price.timestamp}: $${price.close}/hr (volume: ${price.volume})`);
});

Lease Management

// List leases
const leases = await client.leases.list({ status: 'active' });
leases.forEach(lease => {
  console.log(`${lease.leaseId}: ${lease.gpuCount} GPUs`);
});

// Get lease details
const lease = await client.leases.get('lse_xyz123');
console.log(`Nodes: ${lease.nodes.join(', ')}`);
console.log(`Namespace: ${lease.namespace}`);

// Terminate lease
await lease.terminate();

Reselling

// Resell unused time
const resellOrder = await client.leases.resell('lse_xyz123', {
  limitPrice: 3.00,
  availableFrom: '2025-11-12T18:00:00Z'
});

console.log(`Resell order ID: ${resellOrder.orderId}`);
console.log(`Potential recovery: $${resellOrder.potentialRecovery}`);
console.log(`Net recovery: $${resellOrder.netRecovery} (after 15% fee)`);

Error Handling

import { GaladrielError, InsufficientLiquidityError, RateLimitError } from '@galadriel/sdk';

try {
  const order = await client.orders.create({
    side: 'buy',
    type: 'market',
    gpuType: 'h100',
    gpuCount: 16,
    durationHours: 24,
    zone: 'us-west-1'
  });
} catch (error) {
  if (error instanceof InsufficientLiquidityError) {
    console.log('No liquidity available. Try a limit order.');
  } else if (error instanceof RateLimitError) {
    console.log('Rate limit exceeded. Wait before retrying.');
  } else if (error instanceof GaladrielError) {
    console.log(`API error: ${error.message}`);
  } else {
    throw error;
  }
}

TypeScript Types

The SDK is fully typed with TypeScript:
import type {
  Order,
  Lease,
  Orderbook,
  PriceEstimate,
  CreateOrderParams
} from '@galadriel/sdk';

// Type-safe operations
const params: CreateOrderParams = {
  side: 'buy',
  type: 'market',
  gpuType: 'h100',
  gpuCount: 16,
  durationHours: 24,
  zone: 'us-west-1'
};

const order: Order = await client.orders.create(params);
const lease: Lease = await client.leases.get('lse_xyz123');
const orderbook: Orderbook = await client.orderbook.get({
  instanceType: '8xh100',
  zone: 'us-west-1'
});

Advanced Examples

Python: Automated Trading Bot

from galadriel import Client
import time

client = Client(api_token="your_token")

def trade_bot():
    while True:
        # Get orderbook
        orderbook = client.orderbook.get(
            instance_type="8xh100",
            zone="us-west-1"
        )

        # If spread is wide, place limit order in the middle
        if orderbook.market_depth.spread > 0.50:
            mid_price = orderbook.market_depth.mid_price

            order = client.orders.create(
                side="buy",
                type="limit",
                gpu_type="h100",
                gpu_count=8,
                duration_hours=24,
                limit_price=mid_price,
                zone="us-west-1"
            )

            print(f"Placed order at ${mid_price}/hr")

        time.sleep(60)  # Check every minute

trade_bot()

TypeScript: Batch Processing

import { GaladrielClient } from '@galadriel/sdk';

const client = new GaladrielClient({
  apiToken: process.env.GALADRIEL_TOKEN
});

async function processBatch() {
  // Create multiple orders concurrently
  const orders = await Promise.all([
    client.orders.create({
      side: 'buy',
      type: 'limit',
      gpuType: 'h100',
      gpuCount: 8,
      durationHours: 24,
      limitPrice: 3.20,
      zone: 'us-west-1'
    }),
    client.orders.create({
      side: 'buy',
      type: 'limit',
      gpuType: 'h100',
      gpuCount: 8,
      durationHours: 24,
      limitPrice: 3.30,
      zone: 'us-west-1'
    }),
    client.orders.create({
      side: 'buy',
      type: 'limit',
      gpuType: 'h100',
      gpuCount: 8,
      durationHours: 24,
      limitPrice: 3.40,
      zone: 'us-west-1'
    })
  ]);

  console.log(`Created ${orders.length} orders`);

  // Wait for fills
  for (const order of orders) {
    const status = await client.orders.get(order.orderId);
    console.log(`${order.orderId}: ${status.status}`);
  }
}

processBatch();

Python: Cost Tracking

from galadriel import Client
from datetime import datetime, timedelta

client = Client(api_token="your_token")

def track_costs(days=30):
    leases = client.leases.list(status="all")

    total_cost = 0
    total_hours = 0

    for lease in leases:
        duration = (lease.end_time - lease.start_time).total_seconds() / 3600
        cost = duration * lease.gpu_count * lease.price_per_gpu

        total_cost += cost
        total_hours += duration * lease.gpu_count

        print(f"{lease.lease_id}: ${cost:.2f} ({duration}h × {lease.gpu_count} GPUs)")

    print(f"\nTotal cost: ${total_cost:.2f}")
    print(f"Total GPU-hours: {total_hours}")
    print(f"Average rate: ${total_cost / total_hours:.2f}/GPU/hr")

track_costs()

Next Steps