# Javascript SDK

### 1DEX JavaScript SDK

A powerful JavaScript SDK for integrating with the 1DEX decentralized exchange platform, providing seamless access to trading functionality and market data.

### Installation

```bash
npm install 1dex-js-sdk
```

### Getting Started

#### Initializing the SDK

```typescript
import { DexKit, ETradeSide, EOrderType } from "1dex-js-sdk";

// Create a new DexKit instance
const dexKit = new DexKit({
  apiKey: "YOUR_API_KEY",
  secretKey: "YOUR_SECRET_KEY",
  enableProxy: false, // Optional, defaults to true
  apiClientConfig: {
    baseUrl: "https://api-v1.example.com", // Optional, defaults to 'https://api-v1.1dex.com'
  },
  blockchainRpcClientConfig: {
    chainID: "YOUR_CHAIN_ID", // Optional, defaults to 'aca376f206b8fc25a6ed44dbdc66547c36c6c33e3a119ffbeaef943642f0e906'
    rpcUrl: "https://rpc.example.com", // Optional, defaults to 'https://spring-rpc.1dex.com'
  },
  devMode: false, // Optional, if set to true, it will output debug information of certain methods in the console
  version: "v2" // Optional, if set to 'v2', it will enable AMM listing, default is 'v1'
});

// Initialize the DexKit instance
await dexKit.initialize();
```

### DexKit Interface

The DexKit class provides methods for trading operations on 1DEX.

#### Core Methods

**`initialize()`**

Initializes the DexKit instance by fetching system metadata, account information, and pool data.

```typescript
await dexKit.initialize();
```

**`initializeWithProvidedConfig(config)`**

Initializes the DexKit instance using the provided configuration instead of getting it from the server.

**All parameters are optional.**

```typescript
dexKit.initializeWithProvidedConfig({
  appContract: "app_contract", // app.1dex
  accountContract: "account_contract", // Your main account name
  pools: [
    {
      id: 1,
      baseToken: "TOKEN1",
      quoteToken: "TOKEN2",
      baseTokenContract: "token1.contract",
      quoteTokenContract: "token2.contract",
      baseTokenDecimals: 4,
      quoteTokenDecimals: 4,
      pricePrecision: 4,
    },
  ],
  proxyAccount: {
    name: "proxy.account",
    permission: "active",
  },
  account: {
    name: "user.account", // Your sub-account name
    permission: "trader", // Your sub-account permission
  },
});
```

**`placeLimitOrder(params)`**

Places a limit order on the specified pool.

If it is a **buy order**, the amount is the quantity of **quote coin**, if it is a **sell order**, the amount is the quantity of **base coin**.

For example, there is a BTC/USDT trading pair. If it is a buy order, 'amount = 80000' means '80000 USDT', if it is a sell order, 'amount = 1' means '1 BTC'.

Note: the amount will be **rounded up** to the precision unit, which means that if you enter **10.00001 EOS**, it will be formatted as **10.0001 EOS**, so it is recommended to enter the amount according to the token decimals.

```typescript
const { txID, clientOrderID } = await dexKit.placeLimitOrder({
  poolID: 1,
  side: ETradeSide.BUY, // or ETradeSide.SELL
  orderType: EOrderType.NO_RESTRICTION, // or EOrderType.IMMEDIATE_OR_CANCEL || EOrderType.FILL_OR_KILL || EOrderType.POST_ONLY
  amount: "10.0000", // if 'buy', amount is quote coin quantity; if 'sell', amount is base coin quantity
  price: "0.5000",
  clientOrderID: "your defined client order id", // optional
});
```

**`placeMarketOrder(params)`**

Places a market order on the specified pool.

If it is a **buy order**, the amount is the quantity of **quote coin**, if it is a **sell order**, the amount is the quantity of **base coin**.

For example, there is a BTC/USDT trading pair. If it is a buy order, 'amount = 80000' means '80000 USDT', if it is a sell order, 'amount = 1' means '1 BTC'.

Note: the amount will be **rounded up** to the precision unit, which means that if you enter **10.00001 EOS**, it will be formatted as **10.0001 EOS**, so it is recommended to enter the amount according to the token decimals.

```typescript
const { txID, clientOrderID } = await dexKit.placeMarketOrder({
  poolID: 1,
  side: ETradeSide.BUY, // or ETradeSide.SELL
  amount: "10.0000", // if 'buy', amount is quote coin quantity; if 'sell', amount is base coin quantity
  clientOrderID: "your defined client order id", // optional
});
```

**`cancelOrder(params)`**

Cancels an existing order.

```typescript
const txID = await dexKit.cancelOrder({
  poolID: 1,
  orderID: 1,
  side: ETradeSide.BUY, // or ETradeSide.SELL
});
```

**`cancelOrderByCid(cid)`**

Cancels an existing order by client order id.

Client order id will be returned by `placeMarketOrder` and `placeLimitOrder`.

```typescript
const txID = await dexKit.cancelOrderByCid(cid);
```

**`batchCancelOrders(params)`**

Cancels multiple open orders at once.

```typescript
const txID = await dexKit.batchCancelOrders({
  poolID: 1, // optional
  side: ETradeSide.SELL, // optional, ETradeSide.SELL or ETradeSide.BUY
  limit: 100, // optional, default is 500
});
```

#### Resource Management

**`getAccountResources(account)`**

Gets the account resources including CPU, NET, and RAM information.

If name is empty, the default sub-account's name obtained during initialization is used.

```typescript
const resources = await dexKit.getAccountResources("name");
// Returns:
// {
//   cpuMax: string,
//   cpuAvailable: string,
//   netMax: string,
//   netAvailable: string,
//   ramQuota: string,
//   ramUsed: string
// }
```

**`powerup(params)`**

Powers up the account with CPU and NET resources.

```typescript
const txID = await dexKit.powerup({
  netEOS: 100000, // optional
  cpuEOS: 1000000000, // optional
  maxPayment: 100000, // optional
  days: 1, // optional, defaults to 1 day
});
```

#### Constructor Options

When creating a new DexKit instance, you can provide various configuration options:

```typescript
const dexKit = new DexKit({
  apiKey: "your-api-key",
  secretKey: "your-secret-key",
  enableProxy: true, // optional, defaults to true
  devMode: false, // optional, defaults to false
  apiClientConfig: {
    // HTTP API client configuration
    baseUrl: "https://api-v1.example.com", // optional
    timeout: 30000, // optional
    headers: {
      ["key"]: "value",
    }, // optional
  },
  blockchainRpcClientConfig: {
    // Blockchain RPC client configuration
    chainID: "aca376f206b8fc25a6ed44dbdc66547c36c6c33e3a119ffbeaef943642f0e906", // optional
    rpcUrl: "https://spring-rpc.1dex.com", // optional
  },
  powerupConfig: {
    // Powerup payer account
    payer: "powerup.account", // optional
    permission: "active", // optional
    privateKey: "powerup-private-key", // optional
  },
});
```

### HTTP API Client

The DexKit instance exposes an `httpApiClient` property that provides access to various API endpoints for retrieving market data and account information.

#### Account and Balance

**`getAccount()`**

Retrieves account information.

```typescript
const account = await dexKit.httpApiClient.getAccount();
```

**`getBalance()`**

Retrieves the user's balance information.

```typescript
const balance = await dexKit.httpApiClient.getBalance();
```

#### Market Data

**`getAllPools(params?)`**

Retrieves all available trading pools.

```typescript
// Get all pools
const allPools = await dexKit.httpApiClient.getAllPools();

// Get pools filtered by base or quote coin
const filteredPools = await dexKit.httpApiClient.getAllPools({
  baseCoin: "EOS",
  quoteCoin: "USDT",
});
```

**`getPoolInfo(symbolOrPoolID)`**

Retrieves detailed information about a specific pool.

```typescript
// Get pool by ID
const poolInfo = await dexKit.httpApiClient.getPoolInfo(1);
```

**`getDepth(params)`**

Retrieves order book depth data for a specific pool.

```typescript
const depth = await dexKit.httpApiClient.getDepth({
  id: 1,
  precision: 0.001,
  limit: 20, // Optional
});
```

**`getKline(params)`**

Retrieves kline/candlestick data for a specific pool.

```typescript
const klineData = await dexKit.httpApiClient.getKline({
  poolID: 1,
  period: "1h", // Options: '1min', '5min', '15min', '30min', '1h', '4h', '1d', '1w', '1M'
  startTime: 1609459200, // Optional: Unix timestamp in seconds
  endTime: 1609545600, // Optional: Unix timestamp in seconds
});
```

**`getLatestTrades(params)`**

Retrieves the latest trades for a specific pool.

```typescript
const latestTrades = await dexKit.httpApiClient.getLatestTrades({
  poolID: 1,
  limit: 20, // Optional
});
```

#### Order Management

**`getOpenOrders(params)`**

Retrieves open (active) orders.

```typescript
const openOrders = await dexKit.httpApiClient.getOpenOrders({
  poolID: 1,
  side: "buy", // Optional: 'buy' or 'sell'
});
```

**`getOrderHistory(params)`**

Retrieves order history.

```typescript
const orderHistory = await dexKit.httpApiClient.getOrderHistory({
  poolID: 1,
  side: "buy", // Optional: 'buy' or 'sell'
  type: "limit", // Optional: 'limit' or 'market'
  status: "full_filled", // Optional: 'canceled', 'full_filled', 'partially_filled'
});
```

**`getOrderDetail(params)`**

Retrieves detailed information about a specific order.

```typescript
const orderDetail = await dexKit.httpApiClient.getOrderDetail({
  poolID: 1,
  orderID: 1,
  side: "buy", // Required: 'buy' or 'sell'
});
```

**`getOrderDetailByCid(cid)`**

Retrieves detailed information about a specific order by client order id.

```typescript
const orderDetail = await dexKit.httpApiClient.getOrderDetailByCid(cid);
```

#### Token Information

**`getSupportedTokens()`**

Retrieves all supported tokens.

```typescript
const tokens = await dexKit.httpApiClient.getSupportedTokens();
```

**`getTokenInfo(token)`**

Retrieves detailed information about a specific token.

```typescript
const tokenInfo = await dexKit.httpApiClient.getTokenInfo("EOS");
```

### Complete Trading Example

```typescript
import { DexKit, ETradeSide, EOrderType } from "1dex-js-sdk";

async function tradingExample() {
  // Initialize SDK
  const dexKit = new DexKit({
    apiKey: "YOUR_API_KEY",
    secretKey: "YOUR_SECRET_KEY",
    apiClientConfig: {
      baseUrl: "https://api-v1.example.com", // Optional
    },
    blockchainRpcClientConfig: {
      chainID: "YOUR_CHAIN_ID", // Default: 'aca376f206b8fc25a6ed44dbdc66547c36c6c33e3a119ffbeaef943642f0e906'
      rpcUrl: "https://rpc.example.com", // Default: 'https://spring-rpc.1dex.com'
    },
  });

  await dexKit.initialize();

  // Get available pools
  const pools = await dexKit.httpApiClient.getAllPools();
  const poolID = pools[0].pool_id;

  // Check market depth
  const depth = await dexKit.httpApiClient.getDepth({
    id: poolID,
    precision: 0.001,
  });

  // Place a limit buy order
  const txID = await dexKit.placeLimitOrder({
    poolID,
    side: ETradeSide.BUY,
    orderType: EOrderType.NO_RESTRICTION,
    amount: "10.0000",
    price: depth.bids[0][0], // Using the best bid price
  });

  console.log(`Order placed with transaction ID: ${txID}`);

  // Check open orders
  const openOrders = await dexKit.httpApiClient.getOpenOrders({
    poolID,
    side: "buy",
  });

  if (openOrders.length > 0) {
    // Cancel the first open order
    const orderID = openOrders[0].order_id;

    const cancelTxID = await dexKit.cancelOrder({
      poolID,
      orderID,
      side: ETradeSide.BUY,
    });

    console.log(`Order cancelled with transaction ID: ${cancelTxID}`);
  }
}

tradingExample().catch(console.error);
```

### Powerup Example

```typescript
import { DexKit } from "1dex-js-sdk";

const dexKit = new DexKit({
  apiKey: "",
  secretKey: "",
  enableProxy: false,
  powerupConfig: {
    payer: "",
    permission: "",
    privateKey: "",
  },
});

const MAX_RETRY_COUNT = 3; // 3 times
const CHECK_INTERVAL = 1000; // 1 second
const POWERUP_AVAILABLE_RATE = 0.1; // 10%

const powerupExample = async () => {
  await dexKit.initialize();

  const checkAndPowerup = async () => {
    let retryCount = 0;

    const tryPowerup = async () => {
      try {
        await dexKit.powerup();
        console.log("Powerup successful");
        return true;
      } catch (error) {
        console.error(`Powerup attempt ${retryCount + 1} failed:`, error);
        return false;
      }
    };

    while (true) {
      try {
        const resources = await dexKit.getAccountResources();

        const cpuAvailable = parseFloat(resources.cpuAvailable);
        const cpuMax = parseFloat(resources.cpuMax);
        const netAvailable = parseFloat(resources.netAvailable);
        const netMax = parseFloat(resources.netMax);

        console.log(
          `Current resources - CPU: ${((cpuAvailable / cpuMax) * 100).toFixed(
            2
          )}%, NET: ${((netAvailable / netMax) * 100).toFixed(2)}%`
        );

        if (cpuMax === 0 || netMax === 0) {
          retryCount = 0;
          while (retryCount < MAX_RETRY_COUNT) {
            const result = await tryPowerup();
            if (result) break;
            retryCount++;
            if (retryCount < MAX_RETRY_COUNT) {
              await new Promise((resolve) => setTimeout(resolve, 1000)); // Wait 1s before retry
            }
          }
        } else {
          const cpuRate = cpuAvailable / cpuMax;
          const netRate = netAvailable / netMax;

          if (
            cpuRate < POWERUP_AVAILABLE_RATE ||
            netRate < POWERUP_AVAILABLE_RATE
          ) {
            retryCount = 0;
            while (retryCount < MAX_RETRY_COUNT) {
              const result = await tryPowerup();
              if (result) break;
              retryCount++;
              if (retryCount < MAX_RETRY_COUNT) {
                await new Promise((resolve) => setTimeout(resolve, 1000)); // Wait 1s before retry
              }
            }
          }
        }
      } catch (error) {
        console.error("Error checking resources:", error);
      }

      // Wait for the next check interval
      await new Promise((resolve) => setTimeout(resolve, CHECK_INTERVAL));
    }
  };

  // Start the continuous monitoring
  await checkAndPowerup();
};

powerupExample();
```

### Error Handling

The SDK uses standardized error handling. Errors thrown by the SDK include detailed information about what went wrong. It's recommended to use try-catch blocks when interacting with the SDK:

```typescript
try {
  await dexKit.placeLimitOrder({
    poolID: 1,
    side: ETradeSide.BUY,
    orderType: EOrderType.NO_RESTRICTION,
    amount: "10.0000",
    price: "0.5000",
  });
} catch (error) {
  console.error("Error placing order:", error.message);
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.1dex.com/developer/sdks/javascript-sdk.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
