# @decibeltrade/sdk 中文文档

规范地址：https://npmcn.com/package/%40decibeltrade/sdk/

版本：0\.8\.2
npm 元数据更新时间：2026-09-17T21:09:45.851Z
中文译文更新时间：2026-11-11T19:05:22.270Z
软件包许可：未声明

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40decibeltrade/sdk
原文对照：https://npmcn.com/package/%40decibeltrade/sdk/?lang=original
项目主页：https://github.com/decibeltrade/sdk#readme
源码仓库：https://github.com/decibeltrade/sdk

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：1.6 MB，385 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- 运行依赖：3 个
- peer 依赖：zod ^3\.25\.62，@types/ws ^8\.18\.0，@aptos-labs/ts-sdk ^7\.1\.0
- 首次发布：2025-11-30T07:35:08.302Z
- 最新版本发布：2026-09-17T21:09:45.489Z
- 近 30 天下载量：5849（2026-10-12 至 2026-11-10，npm 官方下载统计）
- 已发布版本数：30（近 12 个月 30 个）

## 中文简介

用于与Decibel互动的TypeScript SDK,这是一款由Aptos所建的全链上交易引擎.

## 安装

```sh
npm install @decibeltrade/sdk
```

也可以使用：`pnpm add @decibeltrade/sdk`、`yarn add @decibeltrade/sdk`、`bun add @decibeltrade/sdk`

## README

# @ decibeltrade/ sdk (英语)

用于与Decibel互动的TypeScript SDK,这是一款由Aptos所建的全链上交易引擎.

**📚 [查看完整的文档 –](https://docs.decibel.trade/)**

## 概览

Decibel TypeSDK提供了一个干净,打入的界面,在Aptos上与Decibel交互:

-   **读取操作** (单位:千美元)`DecibelReadDex`)——查询市场,深度,价格,交易,头寸,订单,分账户,金库
-   **写入操作** (单位:千美元)`DecibelWriteDex`(a) 地点/终止命令、管理职位和分账户、金库业务、授权

## 安装

```bash
npm install @decibeltrade/sdk @aptos-labs/ts-sdk zod
```

```bash
yarn add @decibeltrade/sdk @aptos-labs/ts-sdk zod
```

```bash
pnpm add @decibeltrade/sdk @aptos-labs/ts-sdk zod
```

对于节点环境中的TypeScript,您也可能想要:

```bash
npm install -D @types/ws
```

## 快速启动

### 读取: 市场和账户数据

```typescript
import { DecibelReadDex, TESTNET_CONFIG } from "@decibeltrade/sdk";

const read = new DecibelReadDex(TESTNET_CONFIG, {
  nodeApiKey: process.env.APTOS_NODE_API_KEY, // required
  onWsError: (error) => console.error("WebSocket error:", error), // optional
});

// Get all markets
const markets = await read.markets.getAll();

// Get account overview
const account = await read.accountOverview.getByAddr("0x...account");

// Get market prices
const prices = await read.marketPrices.getAll();

// Get order book depth
const depth = await read.marketDepth.getBySymbol("BTC-PERP", { depth: 10 });
```

### 写入: 提交交易

```typescript
import { DecibelReadDex, DecibelWriteDex, TESTNET_CONFIG } from "@decibeltrade/sdk";
import { Ed25519Account, Ed25519PrivateKey } from "@aptos-labs/ts-sdk";

const account = new Ed25519Account({
  privateKey: new Ed25519PrivateKey(process.env.PRIVATE_KEY!),
});

const read = new DecibelReadDex(TESTNET_CONFIG, {
  nodeApiKey: process.env.APTOS_NODE_API_KEY,
});

const write = new DecibelWriteDex(TESTNET_CONFIG, account, {
  nodeApiKey: process.env.APTOS_NODE_API_KEY, // optional
});

const markets = await read.markets.getAll();
const market = markets.find((m) => m.market_addr === "0x...");
if (!market) throw new Error("Market not found");

function amountToChainUnits(amount: number, decimals: number) {
  return Math.floor(amount * 10 ** decimals);
}

// Place an order
const order = await write.placeOrder({
  subaccountAddr: "0x...",
  marketAddr: "0x...",
  price: amountToChainUnits(5.67, market.px_decimals),
  size: amountToChainUnits(1, market.sz_decimals),
  isBuy: true,
  timeInForce: 0, // GoodTillCanceled
});
```

## 文档

### 开始

-   [SDK 概览](https://docs.decibel.trade/typescript-sdk/overview) - 类型脚本SDK介绍
-   [安装](https://docs.decibel.trade/typescript-sdk/installation) - 安装和配置SDK
-   [配置](https://docs.decibel.trade/typescript-sdk/configuration) - 网络配置和预设

### 读取 SDK

-   [读取 SDK 指南](https://docs.decibel.trade/typescript-sdk/read-sdk) - 查询市场数据和账户信息
    -   市场数据(价格、深度、行业、烛台)
    -   账户概况和职位
    -   命令历史和开放命令
    -   分账户和代表团
    -   默认信息
    -   运动奖励,包括附属委员会

### 写入 SDK

-   [写入 SDK 指南](https://docs.decibel.trade/typescript-sdk/write-sdk) - 建立和提交交易
    -   设置和取消命令
    -   TWAP和批发订单
    -   职位管理(TP/SL)
    -   分账户管理
    -   断层作业
    -   代表团

### 高级

-   [高级使用](https://docs.decibel.trade/typescript-sdk/advanced) - 先进的SDK特性和模式

## 配置

SDK支持多个网络配置 :

```typescript
import { MAINNET_CONFIG, TESTNET_CONFIG, LOCAL_CONFIG, DOCKER_CONFIG } from "@decibeltrade/sdk";

// Mainnet
const read = new DecibelReadDex(MAINNET_CONFIG);

// Testnet
const read = new DecibelReadDex(TESTNET_CONFIG);

// Local development
const read = new DecibelReadDex(LOCAL_CONFIG);

// Docker environment
const read = new DecibelReadDex(DOCKER_CONFIG);
```

### 自定义配置

```typescript
import { DecibelConfig } from "@decibeltrade/sdk";
import { Network } from "@aptos-labs/ts-sdk";

const customConfig: DecibelConfig = {
  network: Network.CUSTOM,
  fullnodeUrl: "https://api.testnet.aptoslabs.com/v1",
  tradingHttpUrl: "https://api.testnet.aptoslabs.com/decibel",
  tradingWsUrl: "wss://api.testnet.aptoslabs.com/decibel/ws",
  gasStationUrl: "https://api.testnet.aptoslabs.com/gs/v1", // optional: enables gas sponsorship
  gasStationApiKey: "your-gas-station-api-key", // optional: enables gas sponsorship
  gasStationAddress: "0x...", // optional: fee-payer address, required for encrypted submission
  deployment: {
    package: "0x...",
    usdc: "0x...",
    testc: "0x...",
    perpEngineGlobal: "0x...",
  },
};
```

## 何时使用

-   **使用 `DecibelReadDex`** 当您需要市场数据、顺序/位置历史或账户状态时。 不需要私人密钥 .
-   **使用 `DecibelWriteDex`** 用于链上行动和贸易。 在浏览器中,避免嵌入私密密钥——偏好会话密钥或钱包并传递 `accountOverride` 具体电话.

## 读取操作 API

### 十进制读取器

主要读取客户端提供所有市场数据和账户信息.

#### 构造器

```typescript
new DecibelReadDex(config: DecibelConfig, opts?: {
  nodeApiKey?: string;
  onWsError?: (error: ErrorEvent) => void;
  onChainFallback?: (info: ChainFallbackInfo) => void;
})
```

#### 全球方法

```typescript
// Get global perpetual engine state
await readDex.globalPerpEngineState();

// Get collateral balance decimals
await readDex.collateralBalanceDecimals();

// Get USDC decimals (cached)
await readDex.usdcDecimals();

// Get USDC balance for an address
await readDex.usdcBalance("0x123...");

// Get account balance
await readDex.accountBalance("0x123...");

// Read on-chain fungible-asset metadata (symbol, decimals, name) for any
// asset address — e.g. entries in account_overview.secondary_collateral
await readDex.fungibleAssetMetadata("0x...asset_metadata");

// Resolve a spot market's base/quote asset addresses (not exposed by /markets)
await readDex.spotMarketAssets("0x...spot_market");

// Get position size
await readDex.positionSize("0x123...", "metadata_address");

// Get crossed position
await readDex.getCrossedPosition("0x123...");
```

### 市场

市场准入信息和配置.

```typescript
// Get all available perp markets
const markets = await readDex.markets.getAll();

// Include spot markets too (rows are discriminated by asset_type), or get
// spot markets alone. Narrow union rows with isSpotMarket / isPerpMarket.
const allMarkets = await readDex.markets.getAll({ includeSpot: true });
const spotMarkets = await readDex.markets.getAllSpot();

// Get specific market by name
const market = await readDex.markets.getByName("BTC-USD");

// Get market by symbol
const market = await readDex.markets.getBySymbol("BTC-PERP");

// List all market addresses
const addresses = await readDex.markets.listMarketAddresses();

// Get market name by address
const name = await readDex.markets.marketNameByAddress("0x123...");
```

### 运动奖

```typescript
const campaigns = await readDex.campaigns.getActive();
const summary = await readDex.campaigns.getSummary({
  accountAddress: "0x...",
  limit: 20,
  offset: 0,
});
```

运动元数据, `summary.claims`,以及 `summary.breakdownByType` 使用情况 `campaignType`数字 : `"fee_rebate"`, (中文(简体) ), `"maker_incentive"`, (中文(简体) ), `"liquidation_rebate"`, (中文(简体) ), `"volume_milestone"`, (中文(简体) ), `"first_funded_trial"`,或 `"affiliate"`。未知的运动类型失败响应验证. 奖励金额是原始的代号单位(按美元数额分列) `10 ** 6`) (中文(简体) ). 每项索赔均披露 `hasAllocation`, (中文(简体) ), `readyToClaim`, (中文(简体) ), `claimedAmount`, (中文(简体) ), `claimedAtTsSec`,以及 `claimTxHash`。 。 。 .

### 账户概览

获得全面的账户信息,包括余额和职位.

```typescript
// Get account overview
const overview = await readDex.accountOverview.getByAddr("subaccount_address", "30d"); // volume_window = "30d"

// Subscribe to real-time account updates
const unsubscribe = readDex.accountOverview.subscribeByAddr("subaccount_address", (data) =>
  console.log("Account update:", data),
);

// Later, unsubscribe
unsubscribe();
```

### 用户费

获得子账户的有效制作人/交易商的收费标准,当期收费水平,全额 贵宾收费表 及其上链收费窗口的日用量历史. 收费 比率为小数(如:. `0.00034` =0.034%;体积值为整美元整数 字符串.

```typescript
const fees = await readDex.userFees.getByAddr({ subAddr: "subaccount_address" });
// fees.user_taker_rate, fees.user_maker_rate, fees.fee_tier
// fees.fee_schedule.tiers.vip[], fees.daily_user_volume[]
```

### 用户位置

查询市场的用户位置.

```typescript
// Get all positions for a user
const positions = await readDex.userPositions.getByAddr({
  subAddr: "subaccount_address",
  includeDeleted: false,
  limit: 10,
});

// Get positions for specific market
const marketPositions = await readDex.userPositions.getByAddr({
  subAddr: "subaccount_address",
  marketAddr: "market_address",
  limit: 10,
});

// Subscribe to position updates
const unsubscribe = readDex.userPositions.subscribeByAddr("subaccount_address", (data) =>
  console.log("Position update:", data),
);
```

### 用户命令

查取开封令和令史. 命令的终点是罪犯和现场 在每行共享路线上 `asset_type` 歧视者; 列表阅读器 默认为 `assetType: "perp"`。通过 `"spot"` - 发现范围,或 `"all"` 改为 获得两种产品合并.

#### 打开命令

```typescript
// Get open orders (perp by default)
const openOrders = await readDex.userOpenOrders.getByAddr({ subAddr: "subaccount_address" });

// Spot only, or both products merged
const spotOrders = await readDex.userOpenOrders.getByAddr({
  subAddr: "subaccount_address",
  assetType: "spot",
});
const allOrders = await readDex.userOpenOrders.getByAddr({
  subAddr: "subaccount_address",
  assetType: "all",
});

// Subscribe to open orders updates
const unsubscribe = readDex.userOpenOrders.subscribeByAddr("subaccount_address", (data) =>
  console.log("Orders update:", data),
);
```

#### 顺序历史

```typescript
// Get order history (perp by default; assetType works as above)
const orderHistory = await readDex.userOrderHistory.getByAddr({
  subAddr: "subaccount_address",
  limit: 50,
});

// Subscribe to order history updates
const unsubscribe = readDex.userOrderHistory.subscribeByAddr("subaccount_address", (data) =>
  console.log("Order history update:", data),
);
```

#### 单次搜索

```typescript
// Look up one order by orderId (perp + spot) or clientOrderId (perp only).
// assetType defaults to unset: the API checks perp first, then spot.
const order = await readDex.userOrders.getOrder({
  subAddr: "subaccount_address",
  market: "market_address",
  orderId: "42",
});
```

#### 散装命令

```typescript
// Get bulk orders (perp by default; assetType works as above)
const bulkOrders = await readDex.userBulkOrders.getByAddr({ subAddr: "subaccount_address" });

// Placement status of one bulk order by sequence number
const status = await readDex.userBulkOrders.getStatus({
  subAddr: "subaccount_address",
  market: "market_address",
  sequenceNumber: 7,
});

// Bulk order fills (optionally by market and sequence number range)
const fills = await readDex.userBulkOrders.getFills({
  subAddr: "subaccount_address",
  startSequenceNumber: 5,
  endSequenceNumber: 9,
});
```

### 市场数据

#### 市场深度(命令书)

```typescript
// Subscribe to depth updates (aggregationSize buckets price levels)
const unsubscribe = readDex.marketDepth.subscribeByName("BTC-USD", 1, (data) =>
  console.log("Depth update:", data),
);

// Spot markets derive a different address than perp markets with the same
// name, so pass the asset type (defaults to "perp")
const unsubSpot = readDex.marketDepth.subscribeByName("APT/USDC", 1, onDepth, "spot");

// Or skip name→address derivation when you already hold the market address
const unsubByAddr = readDex.marketDepth.subscribeByAddr(market.market_addr, 1, onDepth);

// Reset subscription (clear cached data)
readDex.marketDepth.resetSubscriptionByName("BTC-USD", 1);
readDex.marketDepth.resetSubscriptionByAddr(market.market_addr, 1);
```

#### 市场价格

```typescript
// Get current prices
const prices = await readDex.marketPrices.getByName("BTC-USD");
const prices = await readDex.marketPrices.getAll();

// Subscribe to price updates
const unsubscribe = readDex.marketPrices.subscribeByName("BTC-USD", (data) =>
  console.log("Price update:", data),
);
```

#### 市场贸易

```typescript
// Get recent trades
const trades = await readDex.marketTrades.getByName({ marketName: "BTC-USD", limit: 50 });

// Spot markets: pass assetType (defaults to "perp")
const spotTrades = await readDex.marketTrades.getByName({
  marketName: "APT/USDC",
  assetType: "spot",
});

// Or skip name→address derivation when you already hold the market address
const tradesByAddr = await readDex.marketTrades.getByAddr({ marketAddr: market.market_addr });

// Subscribe to trade updates
const unsubscribe = readDex.marketTrades.subscribeByName("BTC-USD", (data) =>
  console.log("Trade update:", data),
);
const unsubSpot = readDex.marketTrades.subscribeByName("APT/USDC", onTrades, "spot");
const unsubByAddr = readDex.marketTrades.subscribeByAddr(market.market_addr, onTrades);
```

#### 烛台

```typescript
import { CandlestickInterval } from "@decibeltrade/sdk";

// Get historical candlestick data (assetType defaults to "perp"; pass "spot"
// for spot markets — perp and spot derive different addresses for the same name)
const candlesticks = await readDex.candlesticks.getByName({
  marketName: "BTC-USD",
  interval: CandlestickInterval.OneMinute,
  startTime: startTimestamp,
  endTime: endTimestamp,
});

// Or skip name→address derivation when you already hold the market address
const byAddr = await readDex.candlesticks.getByAddr({
  marketAddr: market.market_addr,
  interval: CandlestickInterval.OneMinute,
  startTime: startTimestamp,
  endTime: endTimestamp,
});

// Subscribe to candlestick updates
const unsubscribe = readDex.candlesticks.subscribeByName(
  "BTC-USD",
  CandlestickInterval.OneMinute,
  (data) => console.log("Candlestick update:", data),
);
const unsubByAddr = readDex.candlesticks.subscribeByAddr(
  market.market_addr,
  CandlestickInterval.OneMinute,
  (data) => console.log("Candlestick update:", data),
);
```

### 市场背景

获取更多市场元数据和上下文.

```typescript
// Get market contexts
const contexts = await readDex.marketContexts.getAll();

// Subscribe to market context updates
const unsubscribe = readDex.marketContexts.subscribeAll((data) =>
  console.log("Market contexts update:", data),
);
```

### 用户贸易历史

为用户查询历史贸易数据.

```typescript
// Get trade history
const trades = await readDex.userTradeHistory.getByAddr({
  subAddr: "subaccount_address",
  marketAddr: "market_address", // optional
  limit: 100,
});

// Subscribe to trade history updates
const unsubscribe = readDex.userTradeHistory.subscribeByAddr("subaccount_address", (data) =>
  console.log("Trade history update:", data),
);
```

### 用户供资历史

查询资助支付历史.

```typescript
// Get funding history
const funding = await readDex.userFundingHistory.getByAddr({
  subAddr: "subaccount_address",
  marketAddr: "market_address", // optional
  limit: 50,
});

// Subscribe to funding history updates
const unsubscribe = readDex.userFundingHistory.subscribeByAddr("subaccount_address", (data) =>
  console.log("Funding history update:", data),
);
```

### 用户子账户

```typescript
// Get all subaccounts for a user
const subaccounts = await readDex.userSubaccounts.getByAddr("account_address");
```

### 断层

```typescript
// Get user vault positions
const userVaults = await readDex.userVaults.getByAddr("account_address");

// Get public vault information
const vaults = await readDex.vaults.getAll();
```

### 第一次贸易

运动代表了资金到位的第一次贸易流动。 总计为 SQL 级计数 : 在塑造时跳过服务器并进行计数,因此驱动页码 `offset + limit < total`,从不通过查找空/短页.

```typescript
// Composed on-chain eligibility snapshot (locks, credits, budgets, live tier/payout config)
const eligibility = await readDex.fundedFirstTrade.getEligibility({ account: "account_address" });

// Active trial, or null
const activeTrial = await readDex.fundedFirstTrade.getActiveTrial({ account: "account_address" });

// Terminal trial history — { history, historyTotalCount }
const page = await readDex.fundedFirstTrade.getTrialHistory({
  account: "account_address",
  limit: 20,
  offset: 0,
});

// Campaign reward locks — { account, locks, total_count }; server default limit 10
const locks = await readDex.fundedFirstTrade.getCampaignLocks({
  account: "account_address",
  status: "Active", // optional: "Active" | "Claimed"
});

// Real-time trial updates (TrialOpened / TrialClosed / TrialResetByAdmin)
const unsubscribe = readDex.fundedFirstTrade.subscribeByAddr("account_address", ({ trials }) => {
  console.log(trials);
});
```

## 写入操作 API

### 十进制WriteDex

主要书写客户执行交易和管理交易账户、职位、金库和竞选奖励.

#### 构造器

```typescript
import { GasPriceManager } from "@decibeltrade/sdk";
import { Ed25519Account, Ed25519PrivateKey } from "@aptos-labs/ts-sdk";

const account = new Ed25519Account({
  privateKey: new Ed25519PrivateKey("your-private-key"),
});

const gasPriceManager = new GasPriceManager(config);

const writeDex = new DecibelWriteDex(config, account, {
  nodeApiKey: process.env.APTOS_NODE_API_KEY,
  skipSimulate: false,
  gasPriceManager,
  timeDeltaMs: 0,
  defaultEncrypted: false,
});
```

`defaultEncrypted` 决定是否将前端运行敏感写作为加密待决提交 交易; 可读取实例 `writeDex.defaultEncrypted`加密 提交要求有一个暴露加密密钥的全节点 配置 - a `gasStationAddress` 在配置中, 因为付费者被烤入加密 建造时的有效载荷。 提前检查一下 `configSupportsEncryptedSubmission(config)`。 。 。 .

### 公开写作方法

-   交易账户和抵押品: `renameSubaccount`, (中文(简体) ), `createSubaccount`, (中文(简体) ), `adminCreateSubaccount`, (中文(简体) ), `sendSubaccountTx`, (中文(简体) ), `withSubaccount`, (中文(简体) ), `deposit`, (中文(简体) ), `withdraw`, (中文(简体) ), `withdrawNonCollateral`, (中文(简体) ), `configureUserSettingsForMarket`, (中文(简体) ), `buildDeactiveSubaccountTx`
-   命令和匹配 : `placeOrder`, (中文(简体) ), `triggerMatching`, (中文(简体) ), `placeTwapOrder`, (中文(简体) ), `cancelOrder`, (中文(简体) ), `cancelClientOrder`, (中文(简体) ), `cancelBulkOrder`, (中文(简体) ), `updateOrder`, (中文(简体) ), `cancelTwapOrder`
-   点交易 : `placeSpotOrder`, (中文(简体) ), `cancelSpotOrder`, (中文(简体) ), `placeSpotBulkOrder`, (中文(简体) ), `cancelSpotBulkOrder`, (中文(简体) ), `cancelSpotBulkOrderAtPriceLevel`, (中文(简体) ), `approveMaxSpotBuilderFee`, (中文(简体) ), `revokeMaxSpotBuilderFee`, (中文(简体) ), `setHoldAsNonCollateral`, (中文(简体) ), `processSpotPendingRequests`
-   TP/SL位置 : `placeTpSlOrderForPosition`, (中文(简体) ), `updateTpOrderForPosition`, (中文(简体) ), `updateSlOrderForPosition`, (中文(简体) ), `cancelTpSlOrderForPosition`
-   代表团、金库和奖励: `delegateTradingToForSubaccount`, (中文(简体) ), `revokeDelegation`, (中文(简体) ), `createVault`, (中文(简体) ), `buildCreateVaultTx`, (中文(简体) ), `buildActivateVaultTx`, (中文(简体) ), `buildDepositToVaultTx`, (中文(简体) ), `depositToVault`, (中文(简体) ), `withdrawFromVault`, (中文(简体) ), `buildDelegateDexActionsToTx`, (中文(简体) ), `approveMaxBuilderFee`, (中文(简体) ), `revokeMaxBuilderFee`, (中文(简体) ), `claimCampaignReward`, (中文(简体) ), `openFftTrial`, (中文(简体) ), `claimFftUnlock`, (中文(简体) ), `settleFftTrial`

### 交易账户和抵押品

```typescript
// Create a new subaccount
await writeDex.createSubaccount();

// Admin-only: create a subaccount for another owner
await writeDex.adminCreateSubaccount("0x...owner");

// Rename a subaccount via trading API
await writeDex.renameSubaccount({
  subaccountAddress: "0x...subaccount",
  newName: "Treasury",
});

// Deposit collateral to primary subaccount
await writeDex.deposit(1000000); // amount in smallest unit

// Deposit to specific subaccount
await writeDex.deposit(1000000, "subaccount_address");

// Withdraw from subaccount
await writeDex.withdraw(500000, "subaccount_address");

// Withdraw a non-collateral asset from a subaccount
await writeDex.withdrawNonCollateral("0x...asset_metadata", 250000, "subaccount_address");
```

### 贸易代表团和建筑商收费

```typescript
// Delegate trading permissions
await writeDex.delegateTradingToForSubaccount({
  subaccountAddr: "your_subaccount",
  accountToDelegateTo: "delegate_account_address",
  expirationTimestampSecs: 1735689600, // optional
});

// Revoke delegation
await writeDex.revokeDelegation({
  subaccountAddr: "your_subaccount",
  accountToRevoke: "delegate_account_address",
});

// Approve and revoke builder fees (values are basis points)
await writeDex.approveMaxBuilderFee({
  builderAddr: "0x...builder",
  maxFee: 25,
});

await writeDex.revokeMaxBuilderFee({
  builderAddr: "0x...builder",
});
```

### 市场配置

```typescript
// Configure user settings for a market
await writeDex.configureUserSettingsForMarket({
  marketAddr: "market_address",
  subaccountAddr: "subaccount_address",
  isCross: true, // cross-margin mode
  userLeverage: 1000, // 10x leverage (basis points)
});
```

### 订单管理

```typescript
import { DecibelReadDex, getMarketAddr, TimeInForce } from "@decibeltrade/sdk";

const readDex = new DecibelReadDex(config, {
  nodeApiKey: process.env.APTOS_NODE_API_KEY,
});

const marketAddr = getMarketAddr("BTC-USD", config.deployment.perpEngineGlobal).toString();
const market = await readDex.markets.getByName("BTC-USD");
if (!market) throw new Error("Market not found");

const amountToChainUnits = (amount: number, decimals: number) =>
  Math.floor(amount * 10 ** decimals);

// Place a limit order
const result = await writeDex.placeOrder({
  marketName: "BTC-USD",
  price: amountToChainUnits(45_000, market.px_decimals),
  size: amountToChainUnits(1.5, market.sz_decimals),
  isBuy: true,
  timeInForce: TimeInForce.GoodTillCanceled,
  isReduceOnly: false,
  clientOrderId: "12345", // optional
  subaccountAddr: "subaccount_address", // optional
});

// Place order with stop-loss and take-profit
await writeDex.placeOrder({
  marketName: "BTC-USD",
  price: amountToChainUnits(45_000, market.px_decimals),
  size: amountToChainUnits(1, market.sz_decimals),
  isBuy: true,
  timeInForce: TimeInForce.GoodTillCanceled,
  isReduceOnly: false,
  stopPrice: amountToChainUnits(44_000, market.px_decimals),
  tpTriggerPrice: amountToChainUnits(46_000, market.px_decimals),
  tpLimitPrice: amountToChainUnits(45_900, market.px_decimals),
  slTriggerPrice: amountToChainUnits(44_000, market.px_decimals),
  slLimitPrice: amountToChainUnits(44_100, market.px_decimals),
});

// Place order with builder fee and automatic tick-size snapping
await writeDex.placeOrder({
  marketName: "BTC-USD",
  price: amountToChainUnits(45_000, market.px_decimals),
  size: amountToChainUnits(1, market.sz_decimals),
  isBuy: true,
  timeInForce: TimeInForce.GoodTillCanceled,
  isReduceOnly: false,
  builderAddr: "builder_account_address",
  builderFee: 100,
  tickSize: market.tick_size,
});

// Place a TWAP order
await writeDex.placeTwapOrder({
  marketName: "BTC-USD",
  size: amountToChainUnits(10, market.sz_decimals),
  isBuy: true,
  isReduceOnly: false,
  twapFrequencySeconds: 60,
  twapDurationSeconds: 3600,
});

// Cancel orders
// Choose `marketName` when you only have a symbol/name.
await writeDex.cancelOrder({
  orderId: 12345,
  marketName: "BTC-USD",
  subaccountAddr: "subaccount_address", // optional
});

// Choose `marketAddr` when the address is already resolved/cached.
await writeDex.cancelOrder({
  orderId: 12345,
  marketAddr,
  subaccountAddr: "subaccount_address", // optional
});

await writeDex.cancelClientOrder({
  clientOrderId: "54321",
  marketName: "BTC-USD",
});

await writeDex.cancelTwapOrder({
  orderId: "twap_order_id",
  marketAddr,
});

// Cancel all bulk orders for a market
// By market name (symbol-driven flow)
await writeDex.cancelBulkOrder({
  marketName: "BTC-USD",
  subaccountAddr: "subaccount_address", // optional
});

// By market address (address-driven flow)
await writeDex.cancelBulkOrder({
  marketAddr,
  subaccountAddr: "subaccount_address", // optional
});

// Update an existing order
await writeDex.updateOrder({
  orderId: 12345,
  marketAddr,
  price: amountToChainUnits(45_500, market.px_decimals),
  size: amountToChainUnits(1.25, market.sz_decimals),
  isBuy: true,
  timeInForce: TimeInForce.GoodTillCanceled,
  isReduceOnly: false,
  tpTriggerPrice: amountToChainUnits(47_000, market.px_decimals),
  tpLimitPrice: amountToChainUnits(46_900, market.px_decimals),
});
```

### 点点交易

所有即时方法都是子账户范围(默认为主交易账户)并接受 `marketName` 或者说 `marketAddr`一样 `cancelOrder`。 。 。 .

```typescript
import { roundToTickSizeForSide, TimeInForce } from "@decibeltrade/sdk";

const spotMarkets = await readDex.markets.getAllSpot();
const spotMarket = spotMarkets.find((m) => m.market_name === "APT/USDC");
if (!spotMarket) throw new Error("Market not found");

// Place a spot limit order. On spot markets sz_decimals is the base-asset
// decimals and px_decimals the quote-asset decimals.
const spotResult = await writeDex.placeSpotOrder({
  marketName: "APT/USDC",
  price: amountToChainUnits(4.25, spotMarket.px_decimals),
  size: amountToChainUnits(100, spotMarket.sz_decimals),
  isBuy: true,
  timeInForce: TimeInForce.GoodTillCanceled,
  tickSize: spotMarket.tick_size, // optional price snapping
});

// Spot placement is CBS-backed and async: when funding needs a rate-limited
// CBS withdrawal the transaction succeeds but the order is queued, not
// resting. `pendingCbs: true` signals this — resolve the outcome via
// readDex.userOrders.getOrder / userOrderHistory, which cover every terminal
// state. userOpenOrders only sees orders that rest, so an IOC order never
// shows up there whether it filled, cancelled, or is still queued.
if (spotResult.success && spotResult.pendingCbs) {
  console.log("Order queued behind a CBS withdrawal", spotResult.orderId);
}

// There is no market order on chain for spot: submit an IOC limit at the
// slippage cap. `roundToTickSizeForSide` is the same side-safe rounding
// `tickSize` applies internally (buys down, sells up, so the cap is never
// crossed) — pre-round with it to know the exact price the order is
// submitted and escrowed at. It is idempotent.
//
// Spot has no perp-style price feed, so the reference price comes from the
// spot asset contexts (mid of the book, or the last trade).
const spotContexts = await readDex.spotAssetContexts.getAll();
const spotContext = spotContexts.find((c) => c.market_addr === spotMarket.market_addr);
const mid = spotContext?.mid ?? spotContext?.last_price;
if (mid == null) throw new Error("No spot reference price");

// Scale WITHOUT rounding first: amountToChainUnits rounds to the nearest
// integer, which can carry the value across a tick boundary and put the
// submitted price on the wrong side of the cap. Let the side-safe rounding
// consume the exact fractional value instead.
const cap = mid * 1.01 * 10 ** spotMarket.px_decimals;
const submittedPrice = roundToTickSizeForSide(cap, spotMarket.tick_size, true);

const spotMarketOrder = await writeDex.placeSpotOrder({
  marketName: "APT/USDC",
  price: submittedPrice,
  size: amountToChainUnits(100, spotMarket.sz_decimals),
  isBuy: true,
  timeInForce: TimeInForce.ImmediateOrCancel,
  tickSize: spotMarket.tick_size,
});

// Cancel a spot order
if (spotResult.success && spotResult.orderId) {
  await writeDex.cancelSpotOrder({
    orderId: spotResult.orderId,
    marketName: "APT/USDC",
  });
}

// Spot bulk orders (funded from the subaccount PFS only)
await writeDex.placeSpotBulkOrder({
  marketName: "APT/USDC",
  sequenceNumber: 1, // strictly increasing per market
  bidPrices: [amountToChainUnits(4.2, spotMarket.px_decimals)],
  bidSizes: [amountToChainUnits(50, spotMarket.sz_decimals)],
  askPrices: [amountToChainUnits(4.3, spotMarket.px_decimals)],
  askSizes: [amountToChainUnits(50, spotMarket.sz_decimals)],
});

await writeDex.cancelSpotBulkOrderAtPriceLevel({
  marketName: "APT/USDC",
  price: amountToChainUnits(4.2, spotMarket.px_decimals),
  isBuy: true,
});

await writeDex.cancelSpotBulkOrder({ marketName: "APT/USDC" });

// Spot builder fees (basis points). Unlike perp, the builder address may be
// a subaccount or a primary wallet.
await writeDex.approveMaxSpotBuilderFee({ builderAddr: "0x...builder", maxFee: 10 });
await writeDex.revokeMaxSpotBuilderFee({ builderAddr: "0x...builder" });

// Keep future deposits of an asset in the PFS (non-collateral) instead of
// routing them into CBS collateral. Flag-only: existing balances don't move.
await writeDex.setHoldAsNonCollateral({ assetAddr: "0x...asset_metadata", hold: true });
```

### 职位管理

```typescript
const markets = await readDex.markets.getAll();
const market = markets.find((m) => m.market_addr === "market_address");
if (!market) throw new Error("Market not found");

// Place TP/SL order for an existing position
await writeDex.placeTpSlOrderForPosition({
  marketAddr: "market_address",
  tpTriggerPrice: amountToChainUnits(46_000, market.px_decimals),
  tpLimitPrice: amountToChainUnits(45_900, market.px_decimals),
  tpSize: amountToChainUnits(0.5, market.sz_decimals),
  slTriggerPrice: amountToChainUnits(44_000, market.px_decimals),
  slLimitPrice: amountToChainUnits(44_100, market.px_decimals),
  slSize: amountToChainUnits(1, market.sz_decimals),
  subaccountAddr: "subaccount_address",
});

// Update TP and SL orders independently
await writeDex.updateTpOrderForPosition({
  marketAddr: "market_address",
  prevOrderId: "previous_tp_order_id",
  tpTriggerPrice: amountToChainUnits(47_000, market.px_decimals),
  tpLimitPrice: amountToChainUnits(46_900, market.px_decimals),
  tpSize: amountToChainUnits(0.75, market.sz_decimals),
});

await writeDex.updateSlOrderForPosition({
  marketAddr: "market_address",
  prevOrderId: "previous_sl_order_id",
  slTriggerPrice: amountToChainUnits(43_800, market.px_decimals),
  slLimitPrice: amountToChainUnits(43_750, market.px_decimals),
  slSize: amountToChainUnits(1, market.sz_decimals),
});

await writeDex.cancelTpSlOrderForPosition({
  marketAddr: "market_address",
  orderId: 12345,
  subaccountAddr: "subaccount_address",
});
```

### 过失和竞选奖励

```typescript
// Create a vault
await writeDex.createVault({
  // Asset metadata object address (for example USDC metadata), not a Move type tag
  contributionAssetType: writeDex.config.deployment.usdc,
  vaultName: "Basis Trade",
  vaultDescription: "Example strategy",
  vaultSocialLinks: [],
  vaultShareSymbol: "BASIS",
  feeBps: 0,
  feeIntervalS: 0,
  contributionLockupDurationS: 0,
  initialFunding: 0,
  acceptsContributions: false,
  delegateToCreator: false,
});

// Contribute to and redeem from a vault
await writeDex.depositToVault({
  vaultAddress: "0x...vault",
  amount: 1000000,
  subaccountAddr: "0x...subaccount",
});

await writeDex.withdrawFromVault({
  vaultAddress: "0x...vault",
  shares: 1000000,
});

// Build transactions for custom signing flows
await writeDex.buildCreateVaultTx({
  contributionAssetType: writeDex.config.deployment.usdc,
  vaultName: "Basis Trade",
  vaultDescription: "Example strategy",
  vaultSocialLinks: [],
  vaultShareSymbol: "BASIS",
  feeBps: 0,
  feeIntervalS: 0,
  contributionLockupDurationS: 0,
  initialFunding: 0,
  acceptsContributions: false,
  delegateToCreator: false,
  signerAddress: account.accountAddress,
});

await writeDex.buildActivateVaultTx({
  vaultAddress: "0x...vault",
  signerAddress: account.accountAddress,
});

await writeDex.buildDepositToVaultTx({
  vaultAddress: "0x...vault",
  amount: 1000000,
  signerAddress: account.accountAddress,
});

await writeDex.buildDelegateDexActionsToTx({
  vaultAddress: "0x...vault",
  accountToDelegateTo: "0x...delegate",
  signerAddress: account.accountAddress,
});

// Claim a campaign reward by numeric campaign ID
await writeDex.claimCampaignReward(42);
```

### 会话账户

您可以使用会话账户覆盖特定交易的默认账户 :

```typescript
import { TimeInForce } from "@decibeltrade/sdk";
import { Ed25519Account } from "@aptos-labs/ts-sdk";

const sessionAccount = Ed25519Account.generate();
const market = await readDex.markets.getByName("BTC-USD");
if (!market) throw new Error("Market not found");

const amountToChainUnits = (amount: number, decimals: number) =>
  Math.floor(amount * 10 ** decimals);

await writeDex.placeOrder({
  marketName: "BTC-USD",
  price: amountToChainUnits(45_000, market.px_decimals),
  size: amountToChainUnits(1, market.sz_decimals),
  isBuy: true,
  timeInForce: TimeInForce.GoodTillCanceled,
  isReduceOnly: false,
  accountOverride: sessionAccount,
});
```

### 处理错误

所有写入操作返回交易结果 。 对于顺序放置,您得到一个结构化的结果:

```typescript
type PlaceOrderResult =
  | {
      success: true;
      orderId: string | undefined;
      transactionHash: string;
    }
  | {
      success: false;
      error: string;
    };

const result = await writeDex.placeOrder({
  // ... order parameters
});

if (result.success) {
  console.log("Order placed successfully:", result.orderId);
  console.log("Transaction:", result.transactionHash);
} else {
  console.error("Order failed:", result.error);
}
```

## 常数和常数

### 生效时间

```typescript
export const TimeInForce = {
  GoodTillCanceled: 0,
  PostOnly: 1,
  ImmediateOrCancel: 2,
} as const;
```

### 烛台间距

```typescript
export enum CandlestickInterval {
  MINUTE_1 = "1m",
  MINUTE_5 = "5m",
  MINUTE_15 = "15m",
  HOUR_1 = "1h",
  HOUR_4 = "4h",
  DAY_1 = "1d",
}
```

## 公用事业

### 地址公用事业

```typescript
import { getPrimarySubaccountAddr, getMarketAddr } from "@decibeltrade/sdk";

// Get primary subaccount address for an account
const subaccountAddr = getPrimarySubaccountAddr(
  "account_address",
  sdkConfig.compatVersion,
  sdkConfig.deployment.package,
);

// Get market address from name
const marketAddr = getMarketAddr("BTC-USD", "perp_engine_global_address");
```

## 网页订阅

所有支持实时更新的已读操作返回一个未订阅的函数 :

```typescript
// Subscribe to multiple streams
const unsubscribeDepth = readDex.marketDepth.subscribeByName("BTC-USD", 1, handleDepth);
const unsubscribePrices = readDex.marketPrices.subscribeByName("BTC-USD", handlePrices);
const unsubscribeOrders = readDex.userOpenOrders.subscribeByAddr("subaccount", handleOrders);

// Clean up subscriptions
function cleanup() {
  unsubscribeDepth();
  unsubscribePrices();
  unsubscribeOrders();
}

// Handle errors
const readDex = new DecibelReadDex(TESTNET_CONFIG, {
  onWsError: (error) => {
    console.error("WebSocket error:", error);
  },
  // Fired (once per method per instance) when a trading-api read fails and is
  // rebuilt from on-chain views
  onChainFallback: ({ method, error }) => {
    console.warn(`${method} fell back to chain views:`, error);
  },
});

// The SDK reconnects and resubscribes automatically. Streaming-only topics get
// no replay of events missed during an outage — re-seed their state on:
const unregister = readDex.onWsReconnect(() => {
  // re-fetch WS-seeded state over HTTP
});
```

## 类型脚本

SDK与Zod schemas完全打入,用于运行时间验证. 为更好的发展经验而进口的类型:

```typescript
import type {
  DecibelConfig,
  PerpMarket,
  UserPosition,
  MarketDepth,
  CandlestickData,
  AccountOverview,
  PlaceOrderResult,
} from "@decibeltrade/sdk";
```

## 最佳做法

1.  **连接管理**: 在可能的情况下重新使用 SDK 实例来维护 WebSocket 连接.
    
2.  **处理错误**: 总是将 SDK 的电话包装在试捕区块中,并妥善处理出错.
    
3.  **订阅清理**: 总是调用未订阅的函数来防止内存出漏.
    
4.  **限制费率**:在频繁提出请求时注意API的费率限制.
    
5.  **账户安全**:从不披露客户端代码中的私钥. 使用环境变量或安全密钥管理.
    
6.  **精确度**:注意物价和尺寸的数字精确度. SDK在内部处理小数精度.
    

## 完整的交易瓶示例

```typescript
import { DecibelReadDex, DecibelWriteDex, TESTNET_CONFIG, TimeInForce } from "@decibeltrade/sdk";
import { Ed25519Account, Ed25519PrivateKey } from "@aptos-labs/ts-sdk";

class TradingBot {
  private readDex: DecibelReadDex;
  private writeDex: DecibelWriteDex;
  private subaccountAddr: string;

  constructor(privateKey: string, subaccountAddr: string) {
    this.readDex = new DecibelReadDex(TESTNET_CONFIG, {
      nodeApiKey: process.env.APTOS_NODE_API_KEY,
    });

    const account = new Ed25519Account({
      privateKey: new Ed25519PrivateKey(privateKey),
    });
    this.writeDex = new DecibelWriteDex(TESTNET_CONFIG, account, {
      nodeApiKey: process.env.APTOS_NODE_API_KEY,
    });
    this.subaccountAddr = subaccountAddr;
  }

  async start() {
    // Subscribe to market data
    this.readDex.marketPrices.subscribeByName("BTC-USD", this.handlePriceUpdate.bind(this));
    this.readDex.marketDepth.subscribeByName("BTC-USD", 1, this.handleDepthUpdate.bind(this));

    // Subscribe to account updates
    this.readDex.userPositions.subscribeByAddr(
      this.subaccountAddr,
      this.handlePositionUpdate.bind(this),
    );
  }

  private async handlePriceUpdate(priceData: any) {
    // Implement your trading logic here
    console.log("Price update:", priceData);
  }

  private async handleDepthUpdate(depthData: any) {
    // Analyze order book for trading opportunities
    console.log("Depth update:", depthData);
  }

  private async handlePositionUpdate(positionData: any) {
    // Monitor positions and manage risk
    console.log("Position update:", positionData);
  }

  async placeMarketBuyOrder(size: number) {
    try {
      const result = await this.writeDex.placeOrder({
        marketName: "BTC-USD",
        price: 0, // Market order (implementation may vary)
        size,
        isBuy: true,
        timeInForce: TimeInForce.ImmediateOrCancel,
        isReduceOnly: false,
        subaccountAddr: this.subaccountAddr,
      });

      if (result.success) {
        console.log(`Market buy order placed: ${result.orderId}`);
      } else {
        console.error(`Order failed: ${result.error}`);
      }
    } catch (error) {
      console.error("Error placing order:", error);
    }
  }
}

// Usage
const bot = new TradingBot("your-private-key", "your-subaccount-address");
bot.start();
```

## 智能合同交易

对于需要直接访问Decibel智能合同的开发者,本节展示了如何使用Aptos SDK直接构建和提交交易.

### 核心交易基础设施

#### 基础交易管理器

```typescript
import {
  Account,
  AccountAddress,
  AccountAuthenticator,
  Aptos,
  AptosConfig,
  CommittedTransactionResponse,
  InputGenerateTransactionPayloadData,
  MoveString,
  Network,
  PendingTransactionResponse,
  SimpleTransaction,
  createObjectAddress,
} from "@aptos-labs/ts-sdk";

class DecibelTransactionManager {
  private aptos: Aptos;
  private config: DecibelConfig;
  private skipSimulate: boolean;

  constructor(
    config: DecibelConfig,
    private account: Account,
    options?: {
      skipSimulate?: boolean;
      nodeApiKey?: string;
    },
  ) {
    this.config = config;
    this.skipSimulate = options?.skipSimulate ?? false;

    const aptosConfig = new AptosConfig({
      network: config.network,
      fullnode: config.fullnodeUrl,
      clientConfig: { API_KEY: options?.nodeApiKey },
    });
    this.aptos = new Aptos(aptosConfig);
  }

  private async getSimulatedTransaction(
    payload: InputGenerateTransactionPayloadData,
    sender: AccountAddress,
  ): Promise<SimpleTransaction> {
    const transaction = await this.aptos.transaction.build.simple({
      sender,
      data: payload,
    });

    const [simulationResult] = await this.aptos.transaction.simulate.simple({
      transaction,
      options: {
        estimateMaxGasAmount: true,
        estimateGasUnitPrice: true,
      },
    });

    if (!simulationResult?.max_gas_amount || !simulationResult?.gas_unit_price) {
      throw new Error("Transaction simulation failed - no gas estimates returned");
    }

    return await this.aptos.transaction.build.simple({
      sender,
      data: payload,
      options: {
        maxGasAmount: Number(simulationResult.max_gas_amount),
        gasUnitPrice: Number(simulationResult.gas_unit_price),
      },
    });
  }

  async sendTransaction(
    payload: InputGenerateTransactionPayloadData,
    accountOverride?: Account,
  ): Promise<CommittedTransactionResponse> {
    const signer = accountOverride ?? this.account;
    const sender = signer.accountAddress;

    let transaction: SimpleTransaction;

    if (!this.skipSimulate) {
      transaction = await this.getSimulatedTransaction(payload, sender);
    } else {
      transaction = await this.aptos.transaction.build.simple({
        sender,
        data: payload,
      });
    }

    const senderAuthenticator = this.aptos.transaction.sign({
      signer,
      transaction,
    });

    const pendingTransaction = await this.aptos.transaction.submit.simple({
      transaction,
      senderAuthenticator,
    });
    return await this.aptos.waitForTransaction({
      transactionHash: pendingTransaction.hash,
    });
  }
}
```

### 工具函数

```typescript
/**
 * Get market address from market name
 */
function getMarketAddress(marketName: string, perpEngineGlobalAddr: string): AccountAddress {
  const marketNameBytes = new MoveString(marketName).bcsToBytes();
  return createObjectAddress(AccountAddress.fromString(perpEngineGlobalAddr), marketNameBytes);
}

/**
 * Get primary subaccount address for a user account
 */
function getPrimarySubaccountAddress(userAddress: AccountAddress): string {
  // TODO update
  const seed = new TextEncoder().encode("primary_account");
  return createObjectAddress(userAddress, seed).toString();
}

/**
 * Extract order ID from transaction events
 */
function extractOrderIdFromTransaction(
  txResponse: CommittedTransactionResponse,
  subaccountAddr: string,
): string | null {
  try {
    if ("events" in txResponse && Array.isArray(txResponse.events)) {
      for (const event of txResponse.events) {
        if (event.type.includes("::market_types::OrderEvent")) {
          const orderEvent = event.data as any;
          if (orderEvent.user === subaccountAddr) {
            return orderEvent.order_id;
          }
        }
      }
    }
    return null;
  } catch (error) {
    console.error("Error extracting order ID:", error);
    return null;
  }
}
```

### 账户管理交易

#### 创建子账户

```typescript
async function createSubaccount(
  transactionManager: DecibelTransactionManager,
  config: DecibelConfig,
): Promise<CommittedTransactionResponse> {
  return await transactionManager.sendTransaction({
    function: `${config.deployment.package}::dex_accounts::create_new_subaccount`,
    typeArguments: [],
    functionArguments: [],
  });
}
```

#### 担保

```typescript
async function depositCollateral(
  transactionManager: DecibelTransactionManager,
  config: DecibelConfig,
  amount: number,
  subaccountAddr: string,
): Promise<CommittedTransactionResponse> {
  return await transactionManager.sendTransaction({
    function: `${config.deployment.package}::dex_accounts::deposit_to_subaccount_at`,
    typeArguments: [],
    functionArguments: [subaccountAddr, config.deployment.usdc, amount],
  });
}
```

#### 撤销担保

```typescript
async function withdrawCollateral(
  transactionManager: DecibelTransactionManager,
  config: DecibelConfig,
  amount: number,
  subaccountAddr?: string,
): Promise<CommittedTransactionResponse> {
  const subaccount =
    subaccountAddr ?? getPrimarySubaccountAddress(transactionManager.account.accountAddress);

  return await transactionManager.sendTransaction({
    function: `${config.deployment.package}::dex_accounts::withdraw_from_cross_collateral`,
    typeArguments: [],
    functionArguments: [subaccount, config.deployment.usdc, amount],
  });
}
```

#### 配置市场设置

```typescript
async function configureMarketSettings(
  transactionManager: DecibelTransactionManager,
  config: DecibelConfig,
  marketAddr: string,
  subaccountAddr: string,
  isCross: boolean,
  userLeverage: number,
): Promise<CommittedTransactionResponse> {
  return await transactionManager.sendTransaction({
    function: `${config.deployment.package}::dex_accounts::configure_user_settings_for_market`,
    typeArguments: [],
    functionArguments: [subaccountAddr, marketAddr, isCross, userLeverage],
  });
}
```

### 命令管理交易

#### 位置顺序

```typescript
type PlaceOrderResult =
  | {
      success: true;
      orderId: string | undefined;
      transactionHash: string;
    }
  | {
      success: false;
      error: string;
    };

async function placeOrder(
  transactionManager: DecibelTransactionManager,
  config: DecibelConfig,
  params: {
    marketName: string;
    price: number;
    size: number;
    isBuy: boolean;
    timeInForce: number;
    isReduceOnly: boolean;
    clientOrderId?: string;
    stopPrice?: number;
    tpTriggerPrice?: number;
    tpLimitPrice?: number;
    slTriggerPrice?: number;
    slLimitPrice?: number;
    builderAddr?: string;
    builderFee?: number;
    subaccountAddr?: string;
    accountOverride?: Account;
  },
): Promise<PlaceOrderResult> {
  try {
    const marketAddr = getMarketAddress(params.marketName, config.deployment.perpEngineGlobal);
    const subaccountAddr =
      params.subaccountAddr ??
      getPrimarySubaccountAddress(transactionManager.account.accountAddress);

    const txResponse = await transactionManager.sendTransaction(
      {
        function: `${config.deployment.package}::dex_accounts_entry::place_order_to_subaccount`,
        typeArguments: [],
        functionArguments: [
          subaccountAddr,
          marketAddr.toString(),
          params.price,
          params.size,
          params.isBuy,
          params.timeInForce,
          params.isReduceOnly,
          params.clientOrderId,
          params.stopPrice,
          params.tpTriggerPrice,
          params.tpLimitPrice,
          params.slTriggerPrice,
          params.slLimitPrice,
          params.builderAddr,
          params.builderFee,
        ],
      },
      params.accountOverride,
    );

    const orderId = extractOrderIdFromTransaction(txResponse, subaccountAddr);

    return {
      success: true,
      orderId: orderId || undefined,
      transactionHash: txResponse.hash,
    };
  } catch (error) {
    return {
      success: false,
      error: error instanceof Error ? error.message : "Unknown error",
    };
  }
}
```

#### 取消顺序

```typescript
async function cancelOrder(
  transactionManager: DecibelTransactionManager,
  config: DecibelConfig,
  params: {
    orderId: number;
    marketName?: string;
    marketAddr?: string;
    subaccountAddr?: string;
    accountOverride?: Account;
  },
): Promise<CommittedTransactionResponse> {
  const marketAddr =
    params.marketAddr ??
    (params.marketName
      ? getMarketAddress(params.marketName, config.deployment.perpEngineGlobal).toString()
      : "");

  if (!marketAddr) {
    throw new Error("Either marketName or marketAddr must be provided");
  }

  const subaccountAddr =
    params.subaccountAddr ?? getPrimarySubaccountAddress(transactionManager.account.accountAddress);

  return await transactionManager.sendTransaction(
    {
      function: `${config.deployment.package}::dex_accounts::cancel_order_to_subaccount`,
      typeArguments: [],
      functionArguments: [subaccountAddr, params.orderId, marketAddr],
    },
    params.accountOverride,
  );
}
```

#### 位置 TWAP 顺序

```typescript
async function placeTwapOrder(
  transactionManager: DecibelTransactionManager,
  config: DecibelConfig,
  params: {
    marketName: string;
    size: number;
    isBuy: boolean;
    isReduceOnly: boolean;
    twapFrequencySeconds: number;
    twapDurationSeconds: number;
    subaccountAddr?: string;
    accountOverride?: Account;
  },
): Promise<CommittedTransactionResponse> {
  const marketAddr = getMarketAddress(params.marketName, config.deployment.perpEngineGlobal);
  const subaccountAddr =
    params.subaccountAddr ?? getPrimarySubaccountAddress(transactionManager.account.accountAddress);

  return await transactionManager.sendTransaction(
    {
      function: `${config.deployment.package}::dex_accounts::place_twap_order_to_subaccount`,
      typeArguments: [],
      functionArguments: [
        subaccountAddr,
        marketAddr.toString(),
        params.size,
        params.isBuy,
        params.isReduceOnly,
        params.twapFrequencySeconds,
        params.twapDurationSeconds,
      ],
    },
    params.accountOverride,
  );
}
```

### 职位管理交易

#### 放置 TP/ SL 顺序

```typescript
async function placeTpSlOrderForPosition(
  transactionManager: DecibelTransactionManager,
  config: DecibelConfig,
  params: {
    marketAddr: string;
    tpTriggerPrice?: number;
    tpLimitPrice?: number;
    tpSize?: number;
    slTriggerPrice?: number;
    slLimitPrice?: number;
    slSize?: number;
    subaccountAddr?: string;
    accountOverride?: Account;
  },
): Promise<CommittedTransactionResponse> {
  const subaccountAddr =
    params.subaccountAddr ?? getPrimarySubaccountAddress(transactionManager.account.accountAddress);

  return await transactionManager.sendTransaction(
    {
      function: `${config.deployment.package}::dex_accounts::place_tp_sl_order_for_position`,
      typeArguments: [],
      functionArguments: [
        subaccountAddr,
        params.marketAddr,
        params.tpTriggerPrice,
        params.tpLimitPrice,
        params.tpSize,
        params.slTriggerPrice,
        params.slLimitPrice,
        params.slSize,
      ],
    },
    params.accountOverride,
  );
}
```

### 贸易代表团

#### 代表贸易

```typescript
async function delegateTradingToForSubaccount(
  transactionManager: DecibelTransactionManager,
  config: DecibelConfig,
  params: {
    accountToDelegateTo: string;
    subaccountAddr?: string;
  },
): Promise<CommittedTransactionResponse> {
  const subaccountAddr =
    params.subaccountAddr ?? getPrimarySubaccountAddress(transactionManager.account.accountAddress);

  return await transactionManager.sendTransaction({
    function: `${config.deployment.package}::dex_accounts::delegate_trading_to_for_subaccount`,
    typeArguments: [],
    functionArguments: [subaccountAddr, params.accountToDelegateTo],
  });
}
```

#### 撤销代表团

```typescript
async function revokeDelegation(
  transactionManager: DecibelTransactionManager,
  config: DecibelConfig,
  params: {
    accountToRevoke: string;
    subaccountAddr?: string;
  },
): Promise<CommittedTransactionResponse> {
  const subaccountAddr =
    params.subaccountAddr ?? getPrimarySubaccountAddress(transactionManager.account.accountAddress);

  return await transactionManager.sendTransaction({
    function: `${config.deployment.package}::dex_accounts::revoke_delegation`,
    typeArguments: [],
    functionArguments: [subaccountAddr, params.accountToRevoke],
  });
}
```

### 完整工作示例

```typescript
import { Account } from "@aptos-labs/ts-sdk";

async function basicTradingExample() {
  const privateKey = "your-private-key-here";
  const account = Account.fromPrivateKey({ privateKey });
  const transactionManager = new DecibelTransactionManager(TESTNET_CONFIG, account, {
    skipSimulate: false,
  });

  try {
    // Create a subaccount
    console.log("Creating subaccount...");
    const createTx = await createSubaccount(transactionManager, TESTNET_CONFIG);
    console.log("Subaccount created:", createTx.hash);

    // Get the primary subaccount address
    const subaccountAddr = getPrimarySubaccountAddress(account.accountAddress);
    console.log("Primary subaccount address:", subaccountAddr);

    // Deposit collateral (1000 USDC = 1000000000 if 6 decimals)
    console.log("Depositing collateral...");
    const depositTx = await depositCollateral(
      transactionManager,
      TESTNET_CONFIG,
      1000000000,
      subaccountAddr,
    );
    console.log("Deposit successful:", depositTx.hash);

    // Configure market settings for BTC-USD
    const btcMarketAddr = getMarketAddress("BTC-USD", TESTNET_CONFIG.deployment.perpEngineGlobal);
    console.log("Configuring market settings...");
    const configTx = await configureMarketSettings(
      transactionManager,
      TESTNET_CONFIG,
      btcMarketAddr.toString(),
      subaccountAddr,
      true, // Use cross-margin
      1000, // 10x leverage (1000 basis points)
    );
    console.log("Market configured:", configTx.hash);

    // Place a limit buy order for 0.1 BTC at $45,000
    console.log("Placing buy order...");
    const orderResult = await placeOrder(transactionManager, TESTNET_CONFIG, {
      marketName: "BTC-USD",
      price: 45000,
      size: 0.1,
      isBuy: true,
      timeInForce: TimeInForce.GoodTillCanceled,
      isReduceOnly: false,
      subaccountAddr,
    });

    if (orderResult.success) {
      console.log("Order placed successfully!");
      console.log("Order ID:", orderResult.orderId);
      console.log("Transaction:", orderResult.transactionHash);

      // Cancel the order
      if (orderResult.orderId) {
        console.log("Canceling order...");
        const cancelTx = await cancelOrder(transactionManager, TESTNET_CONFIG, {
          orderId: parseInt(orderResult.orderId),
          marketName: "BTC-USD",
          subaccountAddr,
        });
        console.log("Order canceled:", cancelTx.hash);
      }
    } else {
      console.error("Order failed:", orderResult.error);
    }
  } catch (error) {
    console.error("Error in trading example:", error);
  }
}
```

### 最佳做法

1.  **处理错误**: 总是在试捕区块中包接交易呼叫,并适当处理不同类型的错误.
    
2.  **天然气管理**: 使用 `skipSimulate: false` 用于生产中的气体估算。 为复杂的交易设定适当的气体限制.
    
3.  **子账户管理**: 使用主子账户进行简单的使用。 为不同的策略创建单独的子账户. 总是在交易前验证子账户地址.
    
4.  **市场地址处理**:缓存市场地址以避免重复计算. 在生成地址之前验证市场名称正确 .
    
5.  **订单管理**: 存储后取消的订单ID. 使用客户端命令ID来方便跟踪. 实施适当的订单状态监测.
    

## 资源

-   📚 [完整文档](https://docs.decibel.trade/) - 完成API和交易文件
-   🔌 [(原始内容存档于2013-10-12) (英语). REST API](https://docs.decibel.trade/api-reference/rest/overview) - REST API参考
-   🔌 [WebSocket API 服务器](https://docs.decibel.trade/api-reference/websocket/overview) - WebSocket API 参考文献
-   💬 [解析器](https://discord.gg/decibel) - 加入我们的社区争取支持
-   🌐 [交易平台](https://app.decibel.trade/) - 进入Decibel交易平台

## 常见问题

### @decibeltrade/sdk 是什么？

用于与Decibel互动的TypeScript SDK,这是一款由Aptos所建的全链上交易引擎\.

### 如何安装 @decibeltrade/sdk？

在项目目录运行 npm install @decibeltrade/sdk，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：zod（^3\.25\.62）、@types/ws（^8\.18\.0）、@aptos-labs/ts-sdk（^7\.1\.0）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

### @decibeltrade/sdk 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @decibeltrade/sdk 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @decibeltrade/sdk 可以商用吗？

@decibeltrade/sdk 使用 未声明 许可。package\.json 没有声明许可证。没有许可证的代码默认保留全部权利，商用前请联系作者或查看仓库中的 LICENSE 文件。以上为概括，不构成法律意见，请以许可原文为准。

### @decibeltrade/sdk 的下载量有多少？

根据 npm 官方下载统计，@decibeltrade/sdk 在 2026/10/12 – 2026/11/10 这 30 天内被下载 5,849 次，日均约 195 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @decibeltrade/sdk 还在维护吗？

最新版本 0\.8\.2 发布于 2026/09/18（1 个月前）；至今共发布 30 个版本，其中过去 12 个月发布了 30 个；首次发布于 2025/11/30。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

