OstiumBuilder Service
Guides

Delegated Trading Guide

Complete guide to setting up and using delegated (gasless) trading.

Alpha Version

The Ostium Builder Service is in Alpha. API endpoints, specifications, and builder URLs may change without notice. Use with caution in production environments.

Overview

Delegated trading allows your application to execute trades on behalf of users without requiring them to pay gas fees or sign each transaction. This is ideal for:

  • High-frequency trading applications
  • Mobile apps with simplified UX
  • Automated trading strategies
  • Gasless user experiences

How It Works

  1. Delegate Wallet Creation: Create a smart account (delegate wallet) linked to a trader
  2. On-chain Approval: Trader approves the delegate wallet
  3. API Key Generation: Receive an API key for delegated actions
  4. Delegated Execution: Use the API key to execute trades

Step-by-Step Setup

1. Create a Delegate Wallet

curl -X POST https://builder.ostiscan.xyz/v1/auth/create \
  -H "Content-Type: application/json" \
  -H "X-Trader-Address: 0xYourWallet" \
  -d '{}'

Response:

{
  "smartAccountAddress": "0x...",
  "apiKey": "bsvc_...",
  "delegateApprovalTx": {
    "to": "0x...",
    "data": "0x...",
    "value": "0"
  },
  "usdcApprovalRequired": true,
  "usdcApprovalTx": {
    "to": "0x...",
    "data": "0x...",
    "value": "0"
  },
  "chainId": 42161
}

2. Execute Approval Transactions

The trader must sign and submit both transactions:

// Using ethers.js
const signer = await provider.getSigner();

// Approve delegate
const delegateTx = await signer.sendTransaction(response.delegateApprovalTx);
await delegateTx.wait();

// Approve USDC spending (if required)
if (response.usdcApprovalRequired) {
  const usdcTx = await signer.sendTransaction(response.usdcApprovalTx);
  await usdcTx.wait();
}

3. Verify the Delegate Wallet

curl -X POST https://builder.ostiscan.xyz/v1/auth/verify-auth \
  -H "X-Trader-Address: 0xYourWallet" \
  -H "X-API-Key: bsvc_..."

Response:

{
  "verified": true,
  "smartAccountAddress": "0x...",
  "allowance": "1000000"
}

4. Execute Delegated Trades

Now use the API key for gasless trading:

curl -X POST https://builder.ostiscan.xyz/v1/exchange/open \
  -H "Content-Type: application/json" \
  -H "X-Trader-Address: 0xYourWallet" \
  -H "X-API-Key: bsvc_..." \
  -d '{
    "open": {
      "a": 0,
      "b": true,
      "p": "42500",
      "s": "100",
      "l": "10",
      "t": "market"
    }
  }'

Delegated response:

{
  "txHash": "0x...",
  "smartAccountAddress": "0x..."
}

Important Considerations

Single Action Limitation

In delegated mode, only one action per request is supported. This means:

  • One open object per request
  • One position close per request
  • Cannot batch multiple operations

Security Best Practices

  1. Store API keys securely - Never expose in client-side code
  2. Use HTTPS only - Never send API keys over unsecured connections
  3. Implement rate limiting - Protect against abuse
  4. Monitor usage - Track all delegated transactions

Revoking Access

To revoke delegated access:

curl -X POST https://builder.ostiscan.xyz/v1/auth/revoke \
  -H "X-Trader-Address: 0xYourWallet"

This returns a transaction to remove delegation plus a message to sign. After removing delegation and revoking USDC allowance on-chain, call:

curl -X POST https://builder.ostiscan.xyz/v1/auth/verify-revoke \
  -H "Content-Type: application/json" \
  -H "X-Trader-Address: 0xYourWallet" \
  -d '{"message":"<message>","signature":"0x..."}'

Error Handling

Common delegated mode errors:

  • 401 UNAUTHORIZED: API key is invalid or delegate wallet not verified
  • 400 INVALID_REQUEST: Multiple actions in delegated mode
  • 500 INTERNAL_ERROR: Transaction failed on-chain

Example Integration

class DelegatedTrader {
  constructor(apiKey, traderAddress) {
    this.apiKey = apiKey;
    this.traderAddress = traderAddress;
    this.baseUrl = 'https://builder.ostiscan.xyz/v1';
  }

  async openPosition(asset, isLong, price, size, leverage) {
    const response = await fetch(`${this.baseUrl}/exchange/open`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'X-Trader-Address': this.traderAddress,
        'X-API-Key': this.apiKey
      },
      body: JSON.stringify({
        open: {
          a: asset,
          b: isLong,
          p: price,
          s: size,
          l: leverage,
          t: 'market'
        }
      })
    });

    if (!response.ok) {
      throw new Error(`Trade failed: ${response.statusText}`);
    }

    return response.json();
  }
}

On this page