CONNECT

Authentication

Complete guide to Web3 signature authentication, agent keys, and security best practices.

Authentication Overview

AsterDex uses Web3 signature-based authentication for secure, gasless trading. This system allows you to trade without exposing your private keys to our servers.

INFO

Parameters

🔑

Agent API Wallet Setup (REQUIRED)

Required for ALL authenticated API calls - Browser AND Server

Step-by-Step Guide

  1. 1
    Navigate to API Wallet Dashboard:
  2. 2
    Connect Wallet: Click "Connect Wallet" and approve in MetaMask.
  3. 3
    Create Agent: Click the "Authorize new API wallet" button.
  4. 4
    Sign Authorization: Approve the signature request in MetaMask.
  5. 5
    CRITICAL - Save Immediately:

    Copy your Agent Private Key and Agent Address. You will NOT see the private key again!

💡 Why Agent Keys? Agent keys delegate trading permissions without exposing your main wallet. You can revoke them anytime from the dashboard.

🔐 Key Types Explained

Key Type What It Is When to Use
User Wallet Your main MetaMask wallet (0x...) Passed as user parameter
Agent Wallet Authorized sub-key for trading Passed as signer parameter
Agent Private Key Secret key for signing requests Used to generate signature

📋 Required Parameters (All Authenticated Requests)

nonce Unique timestamp in microseconds (prevents replay)
user Your main wallet address (0x...)
signer Agent wallet address (from step 5 above)
signature EIP-712 signature (signed by Agent Private Key)

Browser Authentication (MetaMask)

Complete guide for implementing Web3 authentication in your web application using MetaMask or other browser wallets.

INFO

Parameters

📱 Browser Flow Step-by-Step

  1. 1
    Connect Wallet: Request user's wallet address via ethereum.request()
  2. 2
    Build EIP-712 Message: Create typed data structure with order details
  3. 3
    Request Signature: User signs in MetaMask (no gas fees!)
  4. 4
    Submit to API: Send signed message to AsterDex API
🌐
EIP-712 Typed Data: This standard makes signatures human-readable and secure. Users see exactly what they're signing in MetaMask, preventing phishing attacks.

đŸ’ģ What You Need

  • ✓ MetaMask installed in browser
  • ✓ Basic JavaScript knowledge
  • ✓ Web3 library (ethers.js or web3.js)
const { ethers } = require('ethers');
const axios = require('axios');

const CONFIG = {
    BASE_URL: 'https://www.asterdex-testnet.com/api/v3',
    USER_WALLET: 'YOUR_USER_WALLET', // Main Wallet
    AGENT_WALLET: 'YOUR_AGENT_WALLET', // Agent Wallet
    AGENT_PRIVATE_KEY: 'YOUR_AGENT_PRIVATE_KEY' // Agent Key
};

async function signSpotRequest(params) {
    const wallet = new ethers.Wallet(CONFIG.AGENT_PRIVATE_KEY);
    const nonce = (Date.now() * 1000).toString();

    // Manual Construction (Strict verified order from test_spot_standalone_cycle.js)
    let paramString = '';
    if (params.symbol) paramString += `symbol=${params.symbol}`;
    if (params.side) paramString += `&side=${params.side}`;
    if (params.type) paramString += `&type=${params.type}`;
    if (params.quantity) paramString += `&quantity=${params.quantity}`;
    if (params.quoteOrderQty) paramString += `&quoteOrderQty=${params.quoteOrderQty}`;
    if (params.price) paramString += `&price=${params.price}`;
    if (params.timeInForce) paramString += `&timeInForce=${params.timeInForce}`;
    if (params.orderId) paramString += `&orderId=${params.orderId}`;

    if (paramString.startsWith('&')) paramString = paramString.substring(1);

    paramString += `&nonce=${nonce}&user=${CONFIG.USER_WALLET}&signer=${CONFIG.AGENT_WALLET}`;

    console.log(`📝 Signing String (Fixed): ${paramString}`);

    const domain = { name: "AsterSignTransaction", version: "1", chainId: 714, verifyingContract: "0x0000000000000000000000000000000000000000" };
    const types = { Message: [{ name: "msg", type: "string" }] };
    const signature = await wallet.signTypedData(domain, types, { msg: paramString });

    return { ...params, nonce, user: CONFIG.USER_WALLET, signer: CONFIG.AGENT_WALLET, signature };
}

async function placeLimitBuy() {
    console.log("🚀 Placing Spot LIMIT BUY...");

    // LIMIT BUY: Quantity (Base) + Price
    // 1. Fetch Price
    let currentPrice = 0.5;
    try {
        const pRes = await axios.get('https://www.asterdex-testnet.com/api/v3/ticker/price?symbol=ASTERUSDT');
        currentPrice = parseFloat(pRes.data.price);
        console.log(`â„šī¸  Current Price: ${currentPrice}`);
    } catch (e) { }

    const limitPrice = (currentPrice * 0.95).toFixed(4); // 5% below market
    const quantity = (10 / limitPrice).toFixed(1); // Buy ~10 USDT worth (Minimum >5)

    const params = {
        symbol: 'ASTERUSDT',
        side: 'BUY',
        type: 'LIMIT',
        quantity: quantity,
        price: limitPrice,
        timeInForce: 'GTC'
    };

    const signedBody = await signSpotRequest(params);
    const body = new URLSearchParams(signedBody);

    try {
        const res = await axios.post(`${CONFIG.BASE_URL}/order`, body, {
            headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
        });
        console.log(`✅ Limit Buy Placed: ID ${res.data.orderId}`);
    } catch (e) {
        console.error(`❌ Failed:`, e.response?.data || e.message);
    }
}

placeLimitBuy();

Server-Side Authentication (Agent Keys)

Complete guide for implementing programmatic authentication using Agent Keys for automated trading bots and backend applications.

INFO

Parameters

âš™ī¸ Server Flow Step-by-Step

  1. 1
    Generate Agent Key:
    • Connect your MetaMask wallet.
    • Click the "Authorize new API wallet" button.
    • Sign the transaction in MetaMask (this authorizes the agent).
    • Copy your Agent Private Key and Agent Address immediately. You won't be able to see the private key again.
  2. 2
    Store Securely:

    Save these credentials in your environment variables. Never hardcode them.

  3. 3
    Build & Sign:

    Use the Agent Private Key to sign requests programmatically. See the code examples below for exact implementation.

âš ī¸
Security Best Practices:
  • â€ĸ Never commit private keys to Git repositories
  • â€ĸ Use environment variables or secret management services
  • â€ĸ Rotate agent keys periodically
  • â€ĸ Revoke immediately if compromised

đŸ› ī¸ Language Support

Complete examples available for all major languages:

JavaScript/Node.js
Most popular for bots
Python
Great for data analysis
Go
High performance apps
Rust
Ultra-safe, blazing fast
const { ethers } = require('ethers');
const axios = require('axios');

const CONFIG = {
    BASE_URL: 'https://www.asterdex-testnet.com/api/v3',
    USER_WALLET: 'YOUR_USER_WALLET', // Main Wallet
    AGENT_WALLET: 'YOUR_AGENT_WALLET', // Agent Wallet
    AGENT_PRIVATE_KEY: 'YOUR_AGENT_PRIVATE_KEY' // Agent Key
};

async function signSpotRequest(params) {
    const wallet = new ethers.Wallet(CONFIG.AGENT_PRIVATE_KEY);
    const nonce = (Date.now() * 1000).toString();

    // Alphabetical Sort (Spot Standard)
    const sortedKeys = Object.keys(params).sort();
    let paramString = sortedKeys.map(key => `${key}=${params[key]}`).join('&');

    paramString += `&nonce=${nonce}&user=${CONFIG.USER_WALLET}&signer=${CONFIG.AGENT_WALLET}`;

    const domain = { name: "AsterSignTransaction", version: "1", chainId: 714, verifyingContract: "0x0000000000000000000000000000000000000000" };
    const types = { Message: [{ name: "msg", type: "string" }] };
    const signature = await wallet.signTypedData(domain, types, { msg: paramString });

    return { ...params, nonce, user: CONFIG.USER_WALLET, signer: CONFIG.AGENT_WALLET, signature };
}

async function getAccountInfo() {
    console.log("\n--- GET Spot Account Info ---");

    // Spot Account Endpoint REQUIRES 'timestamp'
    const params = {
        timestamp: Date.now().toString()
    };

    const signedParams = await signSpotRequest(params);
    const qs = new URLSearchParams(signedParams).toString();

    try {
        // GET Request -> No Content-Type header
        const res = await axios.get(`${CONFIG.BASE_URL}/account?${qs}`);

        console.log("✅ Balance Data Retrieved:");
        const balances = res.data.balances.filter(b => parseFloat(b.free) > 0 || parseFloat(b.locked) > 0);
        balances.forEach(b => console.log(`   - ${b.asset}: Free ${b.free} / Locked ${b.locked}`));

    } catch (e) {
        console.error(`❌ Failed:`, e.response?.data || e.message);
    }
}

getAccountInfo();

Signature Technical Details (EIP-712)

Deep dive into the EIP-712 Typed Data signature standard used for secure, gasless Agent authentication.

INFO

Parameters

🔐 EIP-712 Specification

All Server/Agent requests must be signed using the EIP-712 standard. This ensures the user knows exactly what they are signing (if manual) and prevents replay attacks.

1. Domain Separator
{
  name: "AsterSignTransaction",
  version: "1",
  chainId: 714,
  verifyingContract: "0x0000000000000000000000000000000000000000"
}
2. Message Types
{
  EIP712Domain: [
    { name: "name", type: "string" },
    { name: "version", type: "string" },
    { name: "chainId", type: "uint256" },
    { name: "verifyingContract", type: "address" }
  ],
  Message: [
    { name: "msg", type: "string" }
  ]
}
3. Message Construction
The msg field is a URL-encoded string of parameters sorted by importance (but typically Order keys first).
symbol=BTCUSDT&side=BUY&type=LIMIT&quantity=0.001&price=90000&timeInForce=GTC&nonce=172...&user=0xUser...&signer=0xAgent...
Note: user is your Main Wallet. signer is the Agent Key signing this request.
💡
Why EIP-712? Unlike standard HMAC, EIP-712 signatures are readable by wallets (MetaMask) and bound to a specific Chain ID, making them phishing-resistant and secure for delegated actions.

📚 Implementation

See the Python or JavaScript tabs above for ready-to-use signing functions (sign_futures_request) that implement this exact specification.

const { ethers } = require('ethers');
const axios = require('axios');

const CONFIG = {
    BASE_URL: 'https://www.asterdex-testnet.com/fapi/v3',
    USER_WALLET: 'YOUR_USER_WALLET', // Main Wallet
    AGENT_WALLET: 'YOUR_AGENT_WALLET', // Agent Wallet
    AGENT_PRIVATE_KEY: 'YOUR_AGENT_PRIVATE_KEY' // Agent Key
};

async function signFuturesRequest(params) {
    const wallet = new ethers.Wallet(CONFIG.AGENT_PRIVATE_KEY);
    const nonce = (Date.now() * 1000).toString();

    // STRICT LIST
    const STRICT_KEYS = ['symbol', 'side', 'type', 'quantity', 'price', 'timeInForce', 'leverage', 'orderId'];
    let val = "";
    STRICT_KEYS.forEach(k => { if (params[k]) val += `${val ? '&' : ''}${k}=${params[k]}`; });

    val += `&nonce=${nonce}&user=${CONFIG.USER_WALLET}&signer=${CONFIG.AGENT_WALLET}`;

    const domain = { name: "AsterSignTransaction", version: "1", chainId: 714, verifyingContract: "0x0000000000000000000000000000000000000000" };
    const types = { Message: [{ name: "msg", type: "string" }] };
    const signature = await wallet.signTypedData(domain, types, { msg: val });
    return `${CONFIG.BASE_URL}/order?${val}&signature=${signature}`;
}

async function run() {
    console.log("🚀 Placing Futures LIMIT BUY...");
    const params = {
        symbol: 'BTCUSDT',
        side: 'BUY',
        type: 'LIMIT',
        quantity: '0.001',
        price: '90000',
        timeInForce: 'GTC'
    };

    try {
        const url = await signFuturesRequest(params);
        const res = await axios.post(url);
        console.log(`✅ Success: ${res.data.orderId}`);
    } catch (e) { console.error(e.response?.data); }
}

run();

Spot Trading API

Execute secure, gasless trades on the Spot market. Requires Agent Authentication.

Account Information

Get current account balances and permissions.

GET
/api/v3/account

Parameters

Requires standard authentication (nonce, signature, user, signer).

const { ethers } = require('ethers');
const axios = require('axios');

const CONFIG = {
    BASE_URL: 'https://www.asterdex-testnet.com/api/v3',
    USER_WALLET: 'YOUR_USER_WALLET', // Main Wallet
    AGENT_WALLET: 'YOUR_AGENT_WALLET', // Agent Wallet
    AGENT_PRIVATE_KEY: 'YOUR_AGENT_PRIVATE_KEY' // Agent Key
};

async function signSpotRequest(params) {
    const wallet = new ethers.Wallet(CONFIG.AGENT_PRIVATE_KEY);
    const nonce = (Date.now() * 1000).toString();

    // Alphabetical Sort (Spot Standard)
    const sortedKeys = Object.keys(params).sort();
    let paramString = sortedKeys.map(key => `${key}=${params[key]}`).join('&');

    paramString += `&nonce=${nonce}&user=${CONFIG.USER_WALLET}&signer=${CONFIG.AGENT_WALLET}`;

    const domain = { name: "AsterSignTransaction", version: "1", chainId: 714, verifyingContract: "0x0000000000000000000000000000000000000000" };
    const types = { Message: [{ name: "msg", type: "string" }] };
    const signature = await wallet.signTypedData(domain, types, { msg: paramString });

    return { ...params, nonce, user: CONFIG.USER_WALLET, signer: CONFIG.AGENT_WALLET, signature };
}

async function getAccountInfo() {
    console.log("\n--- GET Spot Account Info ---");

    // Spot Account Endpoint REQUIRES 'timestamp'
    const params = {
        timestamp: Date.now().toString()
    };

    const signedParams = await signSpotRequest(params);
    const qs = new URLSearchParams(signedParams).toString();

    try {
        // GET Request -> No Content-Type header
        const res = await axios.get(`${CONFIG.BASE_URL}/account?${qs}`);

        console.log("✅ Balance Data Retrieved:");
        const balances = res.data.balances.filter(b => parseFloat(b.free) > 0 || parseFloat(b.locked) > 0);
        balances.forEach(b => console.log(`   - ${b.asset}: Free ${b.free} / Locked ${b.locked}`));

    } catch (e) {
        console.error(`❌ Failed:`, e.response?.data || e.message);
    }
}

getAccountInfo();

Place Order

Place a new limit or market order.

POST
/api/v3/order

Parameters

ParamRequiredDescription
symbolYESBTCUSDT
sideYESBUY / SELL
typeYESLIMIT / MARKET
priceLIMITPrice
const { ethers } = require('ethers');
const axios = require('axios');

const CONFIG = {
    BASE_URL: 'https://www.asterdex-testnet.com/api/v3',
    USER_WALLET: 'YOUR_USER_WALLET', // Main Wallet
    AGENT_WALLET: 'YOUR_AGENT_WALLET', // Agent Wallet
    AGENT_PRIVATE_KEY: 'YOUR_AGENT_PRIVATE_KEY' // Agent Key
};

async function signSpotRequest(params) {
    const wallet = new ethers.Wallet(CONFIG.AGENT_PRIVATE_KEY);
    const nonce = (Date.now() * 1000).toString();

    // Manual Construction (Strict verified order from test_spot_standalone_cycle.js)
    let paramString = '';
    if (params.symbol) paramString += `symbol=${params.symbol}`;
    if (params.side) paramString += `&side=${params.side}`;
    if (params.type) paramString += `&type=${params.type}`;
    if (params.quantity) paramString += `&quantity=${params.quantity}`;
    if (params.quoteOrderQty) paramString += `&quoteOrderQty=${params.quoteOrderQty}`;
    if (params.price) paramString += `&price=${params.price}`;
    if (params.timeInForce) paramString += `&timeInForce=${params.timeInForce}`;
    if (params.orderId) paramString += `&orderId=${params.orderId}`;

    if (paramString.startsWith('&')) paramString = paramString.substring(1);

    paramString += `&nonce=${nonce}&user=${CONFIG.USER_WALLET}&signer=${CONFIG.AGENT_WALLET}`;

    console.log(`📝 Signing String (Fixed): ${paramString}`);

    const domain = { name: "AsterSignTransaction", version: "1", chainId: 714, verifyingContract: "0x0000000000000000000000000000000000000000" };
    const types = { Message: [{ name: "msg", type: "string" }] };
    const signature = await wallet.signTypedData(domain, types, { msg: paramString });

    return { ...params, nonce, user: CONFIG.USER_WALLET, signer: CONFIG.AGENT_WALLET, signature };
}

async function placeLimitBuy() {
    console.log("🚀 Placing Spot LIMIT BUY...");

    // LIMIT BUY: Quantity (Base) + Price
    // 1. Fetch Price
    let currentPrice = 0.5;
    try {
        const pRes = await axios.get('https://www.asterdex-testnet.com/api/v3/ticker/price?symbol=ASTERUSDT');
        currentPrice = parseFloat(pRes.data.price);
        console.log(`â„šī¸  Current Price: ${currentPrice}`);
    } catch (e) { }

    const limitPrice = (currentPrice * 0.95).toFixed(4); // 5% below market
    const quantity = (10 / limitPrice).toFixed(1); // Buy ~10 USDT worth (Minimum >5)

    const params = {
        symbol: 'ASTERUSDT',
        side: 'BUY',
        type: 'LIMIT',
        quantity: quantity,
        price: limitPrice,
        timeInForce: 'GTC'
    };

    const signedBody = await signSpotRequest(params);
    const body = new URLSearchParams(signedBody);

    try {
        const res = await axios.post(`${CONFIG.BASE_URL}/order`, body, {
            headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
        });
        console.log(`✅ Limit Buy Placed: ID ${res.data.orderId}`);
    } catch (e) {
        console.error(`❌ Failed:`, e.response?.data || e.message);
    }
}

placeLimitBuy();

Cancel Order

Cancel an active order.

DELETE
/api/v3/order

Parameters

orderId or origClientOrderId required.

// Cancel Spot Order
// Endpoint: /api/v3/order

const axios = require('axios');
const { signature, getTimestamp } = require('./utils');

const BASE_URL = 'https://www.asterdex-testnet.com';
const KEY = 'YOUR_AGENT_WALLET';
const PRIVATE_KEY = 'YOUR_AGENT_PRIVATE_KEY';

async function main() {
    const endpoint = '/api/v3/order';
    const timestamp = getTimestamp();
    
    // Params
    const params = {
        timestamp: timestamp,
        symbol: 'BTCUSDT',
        orderId: 123456
    };

    // Sign (if private)
    // For public endpoints, authentication headers might not be needed
    // but we include logic just in case.
    const queryString = new URLSearchParams(params).toString();
    const signatureVal = signature(timestamp, 'GET', endpoint, queryString, PRIVATE_KEY);

    try {
        const response = await axios.get(`${BASE_URL}${endpoint}?${queryString}`, {
            headers: {
                'X-Aster-Client-Id': KEY,
                'X-Aster-Timestamp': timestamp,
                'X-Aster-Signature': signatureVal
            }
        });
        console.log('Response:', response.data);
    } catch (error) {
        console.error('Error:', error.response ? error.response.data : error.message);
    }
}

main();

Cancel All Orders

Cancel all open orders on a symbol.

DELETE
/api/v3/openOrders

Parameters

ParamRequiredDescription
symbolYESBTCUSDT
const { ethers } = require('ethers');
const axios = require('axios');

const CONFIG = {
    BASE_URL: 'https://www.asterdex-testnet.com/api/v3',
    USER_WALLET: 'YOUR_USER_WALLET', // Main Wallet
    AGENT_WALLET: 'YOUR_AGENT_WALLET', // Agent Wallet
    AGENT_PRIVATE_KEY: 'YOUR_AGENT_PRIVATE_KEY' // Agent Key
};

async function signSpotRequest(params) {
    const wallet = new ethers.Wallet(CONFIG.AGENT_PRIVATE_KEY);
    const nonce = (Date.now() * 1000).toString();

    // Manual Construction (Strict verified order from test_spot_standalone_cycle.js)
    let paramString = '';
    if (params.symbol) paramString += `symbol=${params.symbol}`;
    if (params.side) paramString += `&side=${params.side}`;
    if (params.type) paramString += `&type=${params.type}`;
    if (params.quantity) paramString += `&quantity=${params.quantity}`;
    if (params.quoteOrderQty) paramString += `&quoteOrderQty=${params.quoteOrderQty}`;
    if (params.price) paramString += `&price=${params.price}`;
    if (params.timeInForce) paramString += `&timeInForce=${params.timeInForce}`;
    if (params.orderId) paramString += `&orderId=${params.orderId}`;

    if (paramString.startsWith('&')) paramString = paramString.substring(1);

    paramString += `&nonce=${nonce}&user=${CONFIG.USER_WALLET}&signer=${CONFIG.AGENT_WALLET}`;

    const domain = { name: "AsterSignTransaction", version: "1", chainId: 714, verifyingContract: "0x0000000000000000000000000000000000000000" };
    const types = { Message: [{ name: "msg", type: "string" }] };
    const signature = await wallet.signTypedData(domain, types, { msg: paramString });

    return { ...params, nonce, user: CONFIG.USER_WALLET, signer: CONFIG.AGENT_WALLET, signature };
}

async function cancelAllSpotOrders() {
    console.log("🚀 Spot Cancel All (Loop Strategy)...");

    // 1. Fetch Open Orders
    console.log("1. Fetching open orders...");
    const openParams = { symbol: 'ASTERUSDT' }; // No timestamp needed for openOrders usually, check master guide. 
    // Master Guide says: "Open Orders ... GET symbol + Auth". No timestamp.

    const signedOpen = await signSpotRequest(openParams);
    const qs = new URLSearchParams(signedOpen).toString();

    try {
        const res = await axios.get(`${CONFIG.BASE_URL}/openOrders?${qs}`);
        const orders = res.data;
        console.log(`   Found ${orders.length} open orders.`);

        // 2. Loop and Cancel
        for (const order of orders) {
            console.log(`   Cancelling ${order.orderId}...`);
            const cancelParams = { symbol: 'ASTERUSDT', orderId: order.orderId };
            const signedCancel = await signSpotRequest(cancelParams);
            const cancelQs = new URLSearchParams(signedCancel).toString();

            await axios.delete(`${CONFIG.BASE_URL}/order?${cancelQs}`);
            console.log(`   ✅ Cancelled ${order.orderId}`);
        }

        console.log("✅ All Orders Cancelled.");

    } catch (e) {
        console.error(`❌ Failed:`, e.response?.data || e.message);
    }
}

cancelAllSpotOrders();

Open Orders

Get all open orders on a symbol.

GET
/api/v3/openOrders

Parameters

Symbol required.

// Get Open Spot Orders
// Endpoint: /api/v3/openOrders

const axios = require('axios');
const { signature, getTimestamp } = require('./utils');

const BASE_URL = 'https://www.asterdex-testnet.com';
const KEY = 'YOUR_AGENT_WALLET';
const PRIVATE_KEY = 'YOUR_AGENT_PRIVATE_KEY';

async function main() {
    const endpoint = '/api/v3/openOrders';
    const timestamp = getTimestamp();
    
    // Params
    const params = {
        timestamp: timestamp,
        symbol: 'BTCUSDT'
    };

    // Sign (if private)
    // For public endpoints, authentication headers might not be needed
    // but we include logic just in case.
    const queryString = new URLSearchParams(params).toString();
    const signatureVal = signature(timestamp, 'GET', endpoint, queryString, PRIVATE_KEY);

    try {
        const response = await axios.get(`${BASE_URL}${endpoint}?${queryString}`, {
            headers: {
                'X-Aster-Client-Id': KEY,
                'X-Aster-Timestamp': timestamp,
                'X-Aster-Signature': signatureVal
            }
        });
        console.log('Response:', response.data);
    } catch (error) {
        console.error('Error:', error.response ? error.response.data : error.message);
    }
}

main();

Order History

Get all account orders; active, canceled, or filled.

GET
/api/v3/allOrders

Parameters

Symbol required.

// Get Spot Order History
// Endpoint: /api/v3/allOrders

const axios = require('axios');
const { signature, getTimestamp } = require('./utils');

const BASE_URL = 'https://www.asterdex-testnet.com';
const KEY = 'YOUR_AGENT_WALLET';
const PRIVATE_KEY = 'YOUR_AGENT_PRIVATE_KEY';

async function main() {
    const endpoint = '/api/v3/allOrders';
    const timestamp = getTimestamp();
    
    // Params
    const params = {
        timestamp: timestamp,
        symbol: 'BTCUSDT'
    };

    // Sign (if private)
    // For public endpoints, authentication headers might not be needed
    // but we include logic just in case.
    const queryString = new URLSearchParams(params).toString();
    const signatureVal = signature(timestamp, 'GET', endpoint, queryString, PRIVATE_KEY);

    try {
        const response = await axios.get(`${BASE_URL}${endpoint}?${queryString}`, {
            headers: {
                'X-Aster-Client-Id': KEY,
                'X-Aster-Timestamp': timestamp,
                'X-Aster-Signature': signatureVal
            }
        });
        console.log('Response:', response.data);
    } catch (error) {
        console.error('Error:', error.response ? error.response.data : error.message);
    }
}

main();

Futures Trading API

High-performance perpetual futures trading. Supports leverage, stop-loss, and advanced order types.

Account Information

Get futures account details including positions, margin balance, and unrealized profit.

GET
/fapi/v3/account

Parameters

Requires standard authentication.

const { ethers } = require('ethers');
const axios = require('axios');

const CONFIG = {
    BASE_URL: 'https://www.asterdex-testnet.com/fapi/v3',
    USER_WALLET: 'YOUR_USER_WALLET',
    AGENT_WALLET: 'YOUR_AGENT_WALLET',
    AGENT_PRIVATE_KEY: 'YOUR_AGENT_PRIVATE_KEY'
};

async function signFuturesRequest(endpoint) {
    const wallet = new ethers.Wallet(CONFIG.AGENT_PRIVATE_KEY);
    const nonce = (Date.now() * 1000).toString();
    const val = `nonce=${nonce}&user=${CONFIG.USER_WALLET}&signer=${CONFIG.AGENT_WALLET}`;

    const domain = { name: "AsterSignTransaction", version: "1", chainId: 714, verifyingContract: "0x0000000000000000000000000000000000000000" };
    const types = { Message: [{ name: "msg", type: "string" }] };
    const signature = await wallet.signTypedData(domain, types, { msg: val });

    return `${CONFIG.BASE_URL}${endpoint}?${val}&signature=${signature}`;
}

async function run() {
    console.log("🚀 Futures Account Data...");
    try {
        const url = await signFuturesRequest('/account');
        const res = await axios.get(url);
        console.log(`✅ Balance: ${res.data.totalWalletBalance}`);
    } catch (e) { console.error(e.response?.data || e.message); }
}

run();

Place Order

Place a new futures order. Supports STOP, TAKE_PROFIT, and HIDDEN orders.

POST
/fapi/v3/order

Parameters

ParamRequiredDescription
symbolYESBTCUSDT
sideYESBUY / SELL
typeYESLIMIT / MARKET / STOP / TAKE_PROFIT
timeInForceNOGTC / IOC / FOK / HIDDEN
const { ethers } = require('ethers');
const axios = require('axios');

const CONFIG = {
    BASE_URL: 'https://www.asterdex-testnet.com/fapi/v3',
    USER_WALLET: 'YOUR_USER_WALLET', // Main Wallet
    AGENT_WALLET: 'YOUR_AGENT_WALLET', // Agent Wallet
    AGENT_PRIVATE_KEY: 'YOUR_AGENT_PRIVATE_KEY' // Agent Key
};

async function signFuturesRequest(params) {
    const wallet = new ethers.Wallet(CONFIG.AGENT_PRIVATE_KEY);
    const nonce = (Date.now() * 1000).toString();

    // STRICT LIST
    const STRICT_KEYS = ['symbol', 'side', 'type', 'quantity', 'price', 'timeInForce', 'leverage', 'orderId'];
    let val = "";
    STRICT_KEYS.forEach(k => { if (params[k]) val += `${val ? '&' : ''}${k}=${params[k]}`; });

    val += `&nonce=${nonce}&user=${CONFIG.USER_WALLET}&signer=${CONFIG.AGENT_WALLET}`;

    const domain = { name: "AsterSignTransaction", version: "1", chainId: 714, verifyingContract: "0x0000000000000000000000000000000000000000" };
    const types = { Message: [{ name: "msg", type: "string" }] };
    const signature = await wallet.signTypedData(domain, types, { msg: val });
    return `${CONFIG.BASE_URL}/order?${val}&signature=${signature}`;
}

async function run() {
    console.log("🚀 Placing Futures LIMIT BUY...");
    const params = {
        symbol: 'BTCUSDT',
        side: 'BUY',
        type: 'LIMIT',
        quantity: '0.001',
        price: '90000',
        timeInForce: 'GTC'
    };

    try {
        const url = await signFuturesRequest(params);
        const res = await axios.post(url);
        console.log(`✅ Success: ${res.data.orderId}`);
    } catch (e) { console.error(e.response?.data); }
}

run();

Cancel Order

Cancel an active order.

DELETE
/fapi/v3/order

Parameters

orderId or origClientOrderId required.

// Cancel Futures Order
// Endpoint: /fapi/v3/order

const axios = require('axios');
const { signature, getTimestamp } = require('./utils');

const BASE_URL = 'https://www.asterdex-testnet.com';
const KEY = 'YOUR_AGENT_WALLET';
const PRIVATE_KEY = 'YOUR_AGENT_PRIVATE_KEY';

async function main() {
    const endpoint = '/fapi/v3/order';
    const timestamp = getTimestamp();
    
    // Params
    const params = {
        timestamp: timestamp,
        symbol: 'BTCUSDT',
        orderId: 123456
    };

    // Sign (if private)
    // For public endpoints, authentication headers might not be needed
    // but we include logic just in case.
    const queryString = new URLSearchParams(params).toString();
    const signatureVal = signature(timestamp, 'GET', endpoint, queryString, PRIVATE_KEY);

    try {
        const response = await axios.get(`${BASE_URL}${endpoint}?${queryString}`, {
            headers: {
                'X-Aster-Client-Id': KEY,
                'X-Aster-Timestamp': timestamp,
                'X-Aster-Signature': signatureVal
            }
        });
        console.log('Response:', response.data);
    } catch (error) {
        console.error('Error:', error.response ? error.response.data : error.message);
    }
}

main();

Cancel All Orders

Cancel all open orders on a symbol.

DELETE
/fapi/v3/allOpenOrders

Parameters

Symbol required.

const { ethers } = require('ethers');
const axios = require('axios');

const CONFIG = {
    BASE_URL: 'https://www.asterdex-testnet.com/fapi/v3',
    USER_WALLET: 'YOUR_USER_WALLET', // Main Wallet
    AGENT_WALLET: 'YOUR_AGENT_WALLET', // Agent Wallet
    AGENT_PRIVATE_KEY: 'YOUR_AGENT_PRIVATE_KEY' // Agent Key
};

async function signFuturesRequest(endpoint, params) {
    const wallet = new ethers.Wallet(CONFIG.AGENT_PRIVATE_KEY);
    const nonce = (Date.now() * 1000).toString();

    // STRICT LIST
    const STRICT_KEYS = ['symbol', 'side', 'type', 'quantity', 'price', 'timeInForce', 'leverage', 'orderId'];
    let val = "";
    STRICT_KEYS.forEach(k => { if (params[k]) val += `${val ? '&' : ''}${k}=${params[k]}`; });

    val += `&nonce=${nonce}&user=${CONFIG.USER_WALLET}&signer=${CONFIG.AGENT_WALLET}`;

    const domain = { name: "AsterSignTransaction", version: "1", chainId: 714, verifyingContract: "0x0000000000000000000000000000000000000000" };
    const types = { Message: [{ name: "msg", type: "string" }] };
    const signature = await wallet.signTypedData(domain, types, { msg: val });
    return `${CONFIG.BASE_URL}${endpoint}?${val}&signature=${signature}`;
}

async function run() {
    console.log("🚀 Futures CANCEL ALL...");
    const params = { symbol: 'BTCUSDT' };

    try {
        const url = await signFuturesRequest('/allOpenOrders', params);
        const res = await axios.delete(url);
        console.log(`✅ Success:`, res.data);
    } catch (e) { console.error(e.response?.data); }
}

run();

Open Orders

Get all open orders on a symbol.

GET
/fapi/v3/openOrders

Parameters

Symbol required.

// Get Open Futures Orders
// Endpoint: /fapi/v3/openOrders

const axios = require('axios');
const { signature, getTimestamp } = require('./utils');

const BASE_URL = 'https://www.asterdex-testnet.com';
const KEY = 'YOUR_AGENT_WALLET';
const PRIVATE_KEY = 'YOUR_AGENT_PRIVATE_KEY';

async function main() {
    const endpoint = '/fapi/v3/openOrders';
    const timestamp = getTimestamp();
    
    // Params
    const params = {
        timestamp: timestamp,
        symbol: 'BTCUSDT'
    };

    // Sign (if private)
    // For public endpoints, authentication headers might not be needed
    // but we include logic just in case.
    const queryString = new URLSearchParams(params).toString();
    const signatureVal = signature(timestamp, 'GET', endpoint, queryString, PRIVATE_KEY);

    try {
        const response = await axios.get(`${BASE_URL}${endpoint}?${queryString}`, {
            headers: {
                'X-Aster-Client-Id': KEY,
                'X-Aster-Timestamp': timestamp,
                'X-Aster-Signature': signatureVal
            }
        });
        console.log('Response:', response.data);
    } catch (error) {
        console.error('Error:', error.response ? error.response.data : error.message);
    }
}

main();

Algorithmic Orders

Place advanced algorithmic orders like TWAP or VP.

POST
/fapi/v3/algo/order

Parameters

Advanced parameters required (strategyType, urgency, etc).

const { ethers } = require('ethers');
const axios = require('axios');

const CONFIG = {
    BASE_URL: 'https://www.asterdex-testnet.com/fapi/v3',
    USER_WALLET: 'YOUR_USER_WALLET', // Main Wallet
    AGENT_WALLET: 'YOUR_AGENT_WALLET', // Agent Wallet
    AGENT_PRIVATE_KEY: 'YOUR_AGENT_PRIVATE_KEY' // Agent Key
};

async function signAlgoRequest(endpoint, params) {
    const wallet = new ethers.Wallet(CONFIG.AGENT_PRIVATE_KEY);
    const nonce = (Date.now() * 1000).toString();

    // 1. Standard Strict List
    const STRICT_KEYS = [
        'symbol', 'side', 'type', 'quantity', 'price',
        'timeInForce', 'leverage', 'orderId'
    ];

    let paramString = "";
    STRICT_KEYS.forEach(key => {
        if (params[key] !== undefined && params[key] !== null) {
            paramString += `${paramString ? '&' : ''}${key}=${params[key]}`;
        }
    });

    // 2. DYNAMIC ALGO PARAM: 'stopPrice'
    // This MUST be appended if present, otherwise signature fails for SL/TP.
    if (params.stopPrice) {
        paramString += `&stopPrice=${params.stopPrice}`;
    }

    paramString += `&nonce=${nonce}&user=${CONFIG.USER_WALLET}&signer=${CONFIG.AGENT_WALLET}`;
    console.log(`📝 Signing String: ${paramString}`);

    const domain = { name: "AsterSignTransaction", version: "1", chainId: 714, verifyingContract: "0x0000000000000000000000000000000000000000" };
    const types = { Message: [{ name: "msg", type: "string" }] };
    const signature = await wallet.signTypedData(domain, types, { msg: paramString });

    return `${CONFIG.BASE_URL}${endpoint}?${paramString}&signature=${signature}`;
}

async function placeAlgoOrder(type, stopPrice, side) {
    console.log(`\n--- Place ${type} @ ${stopPrice} ---`);
    const params = {
        symbol: 'BTCUSDT',
        side: side,
        type: type,
        quantity: '0.001',
        stopPrice: stopPrice,
        timeInForce: 'GTC'
    };

    const url = await signAlgoRequest('/order', params);
    try {
        const res = await axios.post(url);
        console.log(`✅ Success: Order ID ${res.data.orderId}`);
    } catch (e) {
        console.error(`❌ Failed:`, e.response?.data);
    }
}

async function run() {
    // Note: You need an open position for SL/TP ReduceOnly to make sense usually.
    // This script assumes you have a position or allows open orders.

    // Stop Loss
    await placeAlgoOrder('STOP_MARKET', '90000', 'SELL');

    // Take Profit
    await placeAlgoOrder('TAKE_PROFIT_MARKET', '100000', 'SELL');
}

run();

Position Information

Get current position information and risk details.

GET
/fapi/v3/positionRisk

Parameters

Symbol optional.

// Get Position Risk
// Endpoint: /fapi/v3/positionRisk

const axios = require('axios');
const { signature, getTimestamp } = require('./utils');

const BASE_URL = 'https://www.asterdex-testnet.com';
const KEY = 'YOUR_AGENT_WALLET';
const PRIVATE_KEY = 'YOUR_AGENT_PRIVATE_KEY';

async function main() {
    const endpoint = '/fapi/v3/positionRisk';
    const timestamp = getTimestamp();
    
    // Params
    const params = {
        timestamp: timestamp,
        symbol: 'BTCUSDT'
    };

    // Sign (if private)
    // For public endpoints, authentication headers might not be needed
    // but we include logic just in case.
    const queryString = new URLSearchParams(params).toString();
    const signatureVal = signature(timestamp, 'GET', endpoint, queryString, PRIVATE_KEY);

    try {
        const response = await axios.get(`${BASE_URL}${endpoint}?${queryString}`, {
            headers: {
                'X-Aster-Client-Id': KEY,
                'X-Aster-Timestamp': timestamp,
                'X-Aster-Signature': signatureVal
            }
        });
        console.log('Response:', response.data);
    } catch (error) {
        console.error('Error:', error.response ? error.response.data : error.message);
    }
}

main();

Income History

Get income history (Realized PnL, Funding Fee, Commission, etc).

GET
/fapi/v3/income

Parameters

None.

// Get Income History
// Endpoint: /fapi/v3/income

const axios = require('axios');
const { signature, getTimestamp } = require('./utils');

const BASE_URL = 'https://www.asterdex-testnet.com';
const KEY = 'YOUR_AGENT_WALLET';
const PRIVATE_KEY = 'YOUR_AGENT_PRIVATE_KEY';

async function main() {
    const endpoint = '/fapi/v3/income';
    const timestamp = getTimestamp();
    
    // Params
    const params = {
        timestamp: timestamp,
        
    };

    // Sign (if private)
    // For public endpoints, authentication headers might not be needed
    // but we include logic just in case.
    const queryString = new URLSearchParams(params).toString();
    const signatureVal = signature(timestamp, 'GET', endpoint, queryString, PRIVATE_KEY);

    try {
        const response = await axios.get(`${BASE_URL}${endpoint}?${queryString}`, {
            headers: {
                'X-Aster-Client-Id': KEY,
                'X-Aster-Timestamp': timestamp,
                'X-Aster-Signature': signatureVal
            }
        });
        console.log('Response:', response.data);
    } catch (error) {
        console.error('Error:', error.response ? error.response.data : error.message);
    }
}

main();

Funding Rate

Get funding rate history.

GET
/fapi/v3/fundingRate

Parameters

Symbol optional.

// Get Funding Rate
// Endpoint: /fapi/v3/fundingRate

const axios = require('axios');
const { signature, getTimestamp } = require('./utils');

const BASE_URL = 'https://www.asterdex-testnet.com';
const KEY = 'YOUR_AGENT_WALLET';
const PRIVATE_KEY = 'YOUR_AGENT_PRIVATE_KEY';

async function main() {
    const endpoint = '/fapi/v3/fundingRate';
    const timestamp = getTimestamp();
    
    // Params
    const params = {
        timestamp: timestamp,
        symbol: 'BTCUSDT'
    };

    // Sign (if private)
    // For public endpoints, authentication headers might not be needed
    // but we include logic just in case.
    const queryString = new URLSearchParams(params).toString();
    const signatureVal = signature(timestamp, 'GET', endpoint, queryString, PRIVATE_KEY);

    try {
        const response = await axios.get(`${BASE_URL}${endpoint}?${queryString}`, {
            headers: {
                'X-Aster-Client-Id': KEY,
                'X-Aster-Timestamp': timestamp,
                'X-Aster-Signature': signatureVal
            }
        });
        console.log('Response:', response.data);
    } catch (error) {
        console.error('Error:', error.response ? error.response.data : error.message);
    }
}

main();