use-typescript-sdk

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Use TypeScript SDK Skill

使用TypeScript SDK技能

Core Rules

核心规则

SDK Setup

SDK配置

  1. ALWAYS use
    @aptos-labs/ts-sdk
    (the current official SDK, NOT the deprecated
    aptos
    package)
  2. ALWAYS create a singleton
    Aptos
    client
    and export it from a shared module (e.g.,
    lib/aptos.ts
    )
  3. ALWAYS configure the network via
    AptosConfig
    with environment variables
  4. ALWAYS use
    Network.TESTNET
    as the default for development (NOT devnet, which resets frequently)
  1. 必须使用
    @aptos-labs/ts-sdk
    (这是当前官方SDK,不要使用已弃用的
    aptos
    包)
  2. 必须创建单例
    Aptos
    客户端
    并从公共模块导出(例如
    lib/aptos.ts
  3. 必须通过
    AptosConfig
    结合环境变量配置网络
  4. 开发环境必须默认使用
    Network.TESTNET
    (不要使用会频繁重置的devnet)

Balance & Queries

余额与查询

  1. ALWAYS use
    aptos.getBalance()
    for APT balance queries (NOT the deprecated
    getAccountCoinAmount
    or
    getAccountAPTAmount
    )
  1. 查询APT余额必须使用
    aptos.getBalance()
    (不要使用已弃用的
    getAccountCoinAmount
    getAccountAPTAmount

Transactions

交易相关

  1. ALWAYS call
    waitForTransaction
    after submitting any transaction
  2. ALWAYS simulate transactions before submitting for critical or high-value operations
  3. ALWAYS wrap blockchain calls in try/catch with specific error handling
  4. ALWAYS use the build-sign-submit pattern:
    transaction.build.simple()
    then
    signAndSubmitTransaction()
  1. 提交任何交易后必须调用
    waitForTransaction
  2. 关键或高价值操作提交前必须先模拟交易
  3. 所有区块链调用必须用try/catch包裹并做针对性错误处理
  4. 必须使用构建-签名-提交模式:先调用
    transaction.build.simple()
    再调用
    signAndSubmitTransaction()

Security

安全规则

  1. NEVER hardcode private keys in source code or frontend bundles
  2. NEVER expose private keys in client-side code or logs
  3. NEVER store private keys in environment variables accessible to the browser (use
    VITE_
    prefix only for public config)
  4. ALWAYS load private keys from environment variables in server-side scripts only, using
    process.env
  1. 绝对不要在源代码或前端产物中硬编码私钥
  2. 绝对不要在客户端代码或日志中暴露私钥
  3. 绝对不要在浏览器可访问的环境变量中存储私钥(仅公开配置可以用
    VITE_
    前缀)
  4. 仅可在服务端脚本中通过
    process.env
    从环境变量加载私钥

Type Safety

类型安全

  1. ALWAYS use
    bigint
    for u128 and u256 values (JavaScript
    number
    loses precision)
  2. ALWAYS pass
    Object<T>
    references
    as address strings in
    functionArguments
  3. ALWAYS use typed entry/view function wrappers instead of raw string-based calls in production code
  1. u128和u256类型的值必须使用
    bigint
    (JavaScript的
    number
    会丢失精度)
  2. functionArguments
    中必须将
    Object<T>
    引用作为地址字符串传递
  3. 生产环境必须使用带类型的入口/视图函数封装,而非原始的字符串调用

Wallet Adapter

钱包适配器

  1. ALWAYS use
    @aptos-labs/wallet-adapter-react
    for frontend wallet integration
  2. ALWAYS wrap your app with
    AptosWalletAdapterProvider
  3. ALWAYS use
    useWallet()
    hook
    to access wallet functions in React components
  1. 前端钱包集成必须使用
    @aptos-labs/wallet-adapter-react
  2. 必须用
    AptosWalletAdapterProvider
    包裹你的应用
  3. React组件中必须使用
    useWallet()
    hook访问钱包功能

Quick Workflow

快速工作流

  1. Install SDK ->
    npm install @aptos-labs/ts-sdk
  2. Create client -> Singleton
    Aptos
    instance in
    lib/aptos.ts
  3. Read data -> Use
    aptos.view()
    for on-chain reads
  4. Write data -> Use
    aptos.transaction.build.simple()
    +
    aptos.signAndSubmitTransaction()
  5. Connect wallet -> Use
    @aptos-labs/wallet-adapter-react
    for frontend dApps
  6. Handle errors -> Wrap all calls in try/catch with error-type checks
  1. 安装SDK ->
    npm install @aptos-labs/ts-sdk
  2. 创建客户端 -> 在
    lib/aptos.ts
    中创建单例
    Aptos
    实例
  3. 读取数据 -> 使用
    aptos.view()
    读取链上数据
  4. 写入数据 -> 使用
    aptos.transaction.build.simple()
    +
    aptos.signAndSubmitTransaction()
  5. 连接钱包 -> 前端dApp使用
    @aptos-labs/wallet-adapter-react
  6. 错误处理 -> 所有调用用try/catch包裹并做错误类型检查

Key Example: Client Setup

核心示例:客户端配置

typescript
// lib/aptos.ts - Singleton client (create once, import everywhere)
import { Aptos, AptosConfig, Network } from "@aptos-labs/ts-sdk";

function getNetwork(): Network {
  const network = import.meta.env.VITE_APP_NETWORK;
  switch (network) {
    case "mainnet":
      return Network.MAINNET;
    case "testnet":
      return Network.TESTNET;
    case "devnet":
      return Network.DEVNET;
    default:
      return Network.TESTNET;
  }
}

const config = new AptosConfig({ network: getNetwork() });
export const aptos = new Aptos(config);

export const MODULE_ADDRESS = import.meta.env.VITE_MODULE_ADDRESS;
typescript
// lib/aptos.ts - 单例客户端(创建一次,全局导入)
import { Aptos, AptosConfig, Network } from "@aptos-labs/ts-sdk";

function getNetwork(): Network {
  const network = import.meta.env.VITE_APP_NETWORK;
  switch (network) {
    case "mainnet":
      return Network.MAINNET;
    case "testnet":
      return Network.TESTNET;
    case "devnet":
      return Network.DEVNET;
    default:
      return Network.TESTNET;
  }
}

const config = new AptosConfig({ network: getNetwork() });
export const aptos = new Aptos(config);

export const MODULE_ADDRESS = import.meta.env.VITE_MODULE_ADDRESS;

Key Example: View Functions (Read)

核心示例:视图函数(读操作)

typescript
// view-functions/getCount.ts
import { aptos, MODULE_ADDRESS } from "../lib/aptos";

export async function getCount(accountAddress: string): Promise<number> {
  const result = await aptos.view({
    payload: {
      function: `${MODULE_ADDRESS}::counter::get_count`,
      functionArguments: [accountAddress]
    }
  });
  return Number(result[0]);
}

// With type arguments
export async function getCoinBalance(accountAddress: string, coinType: string): Promise<bigint> {
  const result = await aptos.view({
    payload: {
      function: "0x1::coin::balance",
      typeArguments: [coinType],
      functionArguments: [accountAddress]
    }
  });
  return BigInt(result[0] as string);
}

// Multiple return values
// Move: public fun get_listing(addr): (address, u64, bool)
export async function getListing(nftAddress: string): Promise<{ seller: string; price: number; isActive: boolean }> {
  const [seller, price, isActive] = await aptos.view({
    payload: {
      function: `${MODULE_ADDRESS}::marketplace::get_listing`,
      functionArguments: [nftAddress]
    }
  });
  return {
    seller: seller as string,
    price: Number(price),
    isActive: isActive as boolean
  };
}
typescript
// view-functions/getCount.ts
import { aptos, MODULE_ADDRESS } from "../lib/aptos";

export async function getCount(accountAddress: string): Promise<number> {
  const result = await aptos.view({
    payload: {
      function: `${MODULE_ADDRESS}::counter::get_count`,
      functionArguments: [accountAddress]
    }
  });
  return Number(result[0]);
}

// 带类型参数的示例
export async function getCoinBalance(accountAddress: string, coinType: string): Promise<bigint> {
  const result = await aptos.view({
    payload: {
      function: "0x1::coin::balance",
      typeArguments: [coinType],
      functionArguments: [accountAddress]
    }
  });
  return BigInt(result[0] as string);
}

// 多返回值示例
// Move代码: public fun get_listing(addr): (address, u64, bool)
export async function getListing(nftAddress: string): Promise<{ seller: string; price: number; isActive: boolean }> {
  const [seller, price, isActive] = await aptos.view({
    payload: {
      function: `${MODULE_ADDRESS}::marketplace::get_listing`,
      functionArguments: [nftAddress]
    }
  });
  return {
    seller: seller as string,
    price: Number(price),
    isActive: isActive as boolean
  };
}

Key Example: Entry Functions (Write) - Server/Script

核心示例:入口函数(写操作)- 服务端/脚本

typescript
import { Account, Aptos, AptosConfig, Network } from "@aptos-labs/ts-sdk";

const config = new AptosConfig({ network: Network.TESTNET });
const aptos = new Aptos(config);

// Build transaction
const transaction = await aptos.transaction.build.simple({
  sender: account.accountAddress,
  data: {
    function: `${MODULE_ADDRESS}::counter::increment`,
    functionArguments: []
  }
});

// Sign and submit
const pendingTx = await aptos.signAndSubmitTransaction({
  signer: account,
  transaction
});

// ALWAYS wait for confirmation
const committedTx = await aptos.waitForTransaction({
  transactionHash: pendingTx.hash
});

console.log("Success:", committedTx.success);
typescript
import { Account, Aptos, AptosConfig, Network } from "@aptos-labs/ts-sdk";

const config = new AptosConfig({ network: Network.TESTNET });
const aptos = new Aptos(config);

// 构建交易
const transaction = await aptos.transaction.build.simple({
  sender: account.accountAddress,
  data: {
    function: `${MODULE_ADDRESS}::counter::increment`,
    functionArguments: []
  }
});

// 签名并提交
const pendingTx = await aptos.signAndSubmitTransaction({
  signer: account,
  transaction
});

// 必须等待交易确认
const committedTx = await aptos.waitForTransaction({
  transactionHash: pendingTx.hash
});

console.log("Success:", committedTx.success);

Key Example: Entry Functions (Write) - Frontend with Wallet

核心示例:入口函数(写操作)- 前端结合钱包

typescript
// entry-functions/increment.ts
import { InputTransactionData } from "@aptos-labs/wallet-adapter-react";
import { MODULE_ADDRESS } from "../lib/aptos";

export function buildIncrementPayload(): InputTransactionData {
  return {
    data: {
      function: `${MODULE_ADDRESS}::counter::increment`,
      functionArguments: [],
    },
  };
}

// Component usage
import { useWallet } from "@aptos-labs/wallet-adapter-react";
import { aptos } from "../lib/aptos";
import { buildIncrementPayload } from "../entry-functions/increment";

function IncrementButton() {
  const { signAndSubmitTransaction } = useWallet();

  const handleClick = async () => {
    try {
      const response = await signAndSubmitTransaction(
        buildIncrementPayload(),
      );
      await aptos.waitForTransaction({
        transactionHash: response.hash,
      });
    } catch (error) {
      console.error("Transaction failed:", error);
    }
  };

  return <button onClick={handleClick}>Increment</button>;
}
typescript
// entry-functions/increment.ts
import { InputTransactionData } from "@aptos-labs/wallet-adapter-react";
import { MODULE_ADDRESS } from "../lib/aptos";

export function buildIncrementPayload(): InputTransactionData {
  return {
    data: {
      function: `${MODULE_ADDRESS}::counter::increment`,
      functionArguments: [],
    },
  };
}

// 组件中使用
import { useWallet } from "@aptos-labs/wallet-adapter-react";
import { aptos } from "../lib/aptos";
import { buildIncrementPayload } from "../entry-functions/increment";

function IncrementButton() {
  const { signAndSubmitTransaction } = useWallet();

  const handleClick = async () => {
    try {
      const response = await signAndSubmitTransaction(
        buildIncrementPayload(),
      );
      await aptos.waitForTransaction({
        transactionHash: response.hash,
      });
    } catch (error) {
      console.error("Transaction failed:", error);
    }
  };

  return <button onClick={handleClick}>Increment</button>;
}

Key Example: Wallet Adapter Setup

核心示例:钱包适配器配置

typescript
// main.tsx or App.tsx
import { AptosWalletAdapterProvider } from "@aptos-labs/wallet-adapter-react";
import { Network } from "@aptos-labs/ts-sdk";

function App() {
  return (
    <AptosWalletAdapterProvider
      autoConnect={true}
      dappConfig={{
        network: Network.TESTNET,
      }}
      onError={(error) => console.error("Wallet error:", error)}
    >
      <YourApp />
    </AptosWalletAdapterProvider>
  );
}

// In any child component
import { useWallet } from "@aptos-labs/wallet-adapter-react";

function WalletInfo() {
  const { account, connected, connect, disconnect, wallet, wallets } =
    useWallet();

  if (!connected) {
    return (
      <div>
        {wallets.map((w) => (
          <button key={w.name} onClick={() => connect(w.name)}>
            Connect {w.name}
          </button>
        ))}
      </div>
    );
  }

  return (
    <div>
      <p>Connected: {account?.address}</p>
      <p>Wallet: {wallet?.name}</p>
      <button onClick={disconnect}>Disconnect</button>
    </div>
  );
}
typescript
// main.tsx 或 App.tsx
import { AptosWalletAdapterProvider } from "@aptos-labs/wallet-adapter-react";
import { Network } from "@aptos-labs/ts-sdk";

function App() {
  return (
    <AptosWalletAdapterProvider
      autoConnect={true}
      dappConfig={{
        network: Network.TESTNET,
      }}
      onError={(error) => console.error("Wallet error:", error)}
    >
      <YourApp />
    </AptosWalletAdapterProvider>
  );
}

// 任意子组件中使用
import { useWallet } from "@aptos-labs/wallet-adapter-react";

function WalletInfo() {
  const { account, connected, connect, disconnect, wallet, wallets } =
    useWallet();

  if (!connected) {
    return (
      <div>
        {wallets.map((w) => (
          <button key={w.name} onClick={() => connect(w.name)}>
            Connect {w.name}
          </button>
        ))}
      </div>
    );
  }

  return (
    <div>
      <p>Connected: {account?.address}</p>
      <p>Wallet: {wallet?.name}</p>
      <button onClick={disconnect}>Disconnect</button>
    </div>
  );
}

Key Example: Sponsored Transactions (Fee Payer)

核心示例:赞助交易(代付Gas)

typescript
import { Account, Aptos, AptosConfig, Network } from "@aptos-labs/ts-sdk";

const aptos = new Aptos(new AptosConfig({ network: Network.TESTNET }));

// 1. Build with fee payer flag
const transaction = await aptos.transaction.build.simple({
  sender: sender.accountAddress,
  withFeePayer: true,
  data: {
    function: `${MODULE_ADDRESS}::counter::increment`,
    functionArguments: []
  }
});

// 2. Sender signs
const senderAuth = aptos.transaction.sign({
  signer: sender,
  transaction
});

// 3. Fee payer signs (different method!)
const feePayerAuth = aptos.transaction.signAsFeePayer({
  signer: feePayer,
  transaction
});

// 4. Submit with both signatures
const pendingTx = await aptos.transaction.submit.simple({
  transaction,
  senderAuthenticator: senderAuth,
  feePayerAuthenticator: feePayerAuth
});

await aptos.waitForTransaction({ transactionHash: pendingTx.hash });
typescript
import { Account, Aptos, AptosConfig, Network } from "@aptos-labs/ts-sdk";

const aptos = new Aptos(new AptosConfig({ network: Network.TESTNET }));

// 1. 构建交易时开启代付标识
const transaction = await aptos.transaction.build.simple({
  sender: sender.accountAddress,
  withFeePayer: true,
  data: {
    function: `${MODULE_ADDRESS}::counter::increment`,
    functionArguments: []
  }
});

// 2. 发送方签名
const senderAuth = aptos.transaction.sign({
  signer: sender,
  transaction
});

// 3. Gas代付方签名(使用不同的签名方法!)
const feePayerAuth = aptos.transaction.signAsFeePayer({
  signer: feePayer,
  transaction
});

// 4. 携带两个签名提交交易
const pendingTx = await aptos.transaction.submit.simple({
  transaction,
  senderAuthenticator: senderAuth,
  feePayerAuthenticator: feePayerAuth
});

await aptos.waitForTransaction({ transactionHash: pendingTx.hash });

Key Example: Multi-Agent Transactions

核心示例:多代理交易

typescript
// 1. Build multi-agent transaction
const transaction = await aptos.transaction.build.multiAgent({
  sender: alice.accountAddress,
  secondarySignerAddresses: [bob.accountAddress],
  data: {
    function: `${MODULE_ADDRESS}::escrow::exchange`,
    functionArguments: [itemAddress, paymentAmount]
  }
});

// 2. Each agent signs
const aliceAuth = aptos.transaction.sign({
  signer: alice,
  transaction
});
const bobAuth = aptos.transaction.sign({
  signer: bob,
  transaction
});

// 3. Submit with all signatures
const pendingTx = await aptos.transaction.submit.multiAgent({
  transaction,
  senderAuthenticator: aliceAuth,
  additionalSignersAuthenticators: [bobAuth]
});

await aptos.waitForTransaction({ transactionHash: pendingTx.hash });
typescript
// 1. 构建多代理交易
const transaction = await aptos.transaction.build.multiAgent({
  sender: alice.accountAddress,
  secondarySignerAddresses: [bob.accountAddress],
  data: {
    function: `${MODULE_ADDRESS}::escrow::exchange`,
    functionArguments: [itemAddress, paymentAmount]
  }
});

// 2. 每个代理分别签名
const aliceAuth = aptos.transaction.sign({
  signer: alice,
  transaction
});
const bobAuth = aptos.transaction.sign({
  signer: bob,
  transaction
});

// 3. 携带所有签名提交交易
const pendingTx = await aptos.transaction.submit.multiAgent({
  transaction,
  senderAuthenticator: aliceAuth,
  additionalSignersAuthenticators: [bobAuth]
});

await aptos.waitForTransaction({ transactionHash: pendingTx.hash });

Type Mappings: Move to TypeScript

类型映射:Move 到 TypeScript

Move TypeTypeScript TypeExample
u8
number
255
u16
number
65535
u32
number
4294967295
u64
number | bigint
1000000
u128
bigint
BigInt("340282366920938463463374607431768211455")
u256
bigint
BigInt("...")
i8
number
-128
(Move 2.3+)
i16
number
-32768
(Move 2.3+)
i32
number
-2147483648
(Move 2.3+)
i64
number | bigint
Use
bigint
for large values (Move 2.3+)
i128
bigint
BigInt("-170141183460469231731687303715884105728")
i256
bigint
BigInt("...")
(Move 2.3+)
bool
boolean
true
address
string
"0x1"
String
string
"hello"
vector<u8>
Uint8Array | string
new Uint8Array([1,2,3])
or hex string
vector<T>
T[]
[1, 2, 3]
for
vector<u64>
Object<T>
string
Object address as hex string
Option<T>
T | null
Value or
null
Move 类型TypeScript 类型示例
u8
number
255
u16
number
65535
u32
number
4294967295
u64
number | bigint
1000000
u128
bigint
BigInt("340282366920938463463374607431768211455")
u256
bigint
BigInt("...")
i8
number
-128
(Move 2.3+)
i16
number
-32768
(Move 2.3+)
i32
number
-2147483648
(Move 2.3+)
i64
number | bigint
大数值请使用
bigint
(Move 2.3+)
i128
bigint
BigInt("-170141183460469231731687303715884105728")
i256
bigint
BigInt("...")
(Move 2.3+)
bool
boolean
true
address
string
"0x1"
String
string
"hello"
vector<u8>
Uint8Array | string
new Uint8Array([1,2,3])
或十六进制字符串
vector<T>
T[]
vector<u64>
对应
[1, 2, 3]
Object<T>
string
十六进制格式的对象地址
Option<T>
T | null
值或
null

Transaction Simulation

交易模拟

typescript
// Build transaction
const transaction = await aptos.transaction.build.simple({
  sender: account.accountAddress,
  data: {
    function: `${MODULE_ADDRESS}::counter::increment`,
    functionArguments: []
  }
});

// Simulate to check for errors and estimate gas
const [simResult] = await aptos.transaction.simulate.simple({
  signerPublicKey: account.publicKey,
  transaction
});

if (!simResult.success) {
  throw new Error(`Simulation failed: ${simResult.vm_status}`);
}

console.log("Gas estimate:", simResult.gas_used);
typescript
// 构建交易
const transaction = await aptos.transaction.build.simple({
  sender: account.accountAddress,
  data: {
    function: `${MODULE_ADDRESS}::counter::increment`,
    functionArguments: []
  }
});

// 模拟交易检查错误并估算Gas
const [simResult] = await aptos.transaction.simulate.simple({
  signerPublicKey: account.publicKey,
  transaction
});

if (!simResult.success) {
  throw new Error(`Simulation failed: ${simResult.vm_status}`);
}

console.log("Gas estimate:", simResult.gas_used);

Gas Profiling

Gas分析

typescript
// Profile gas usage of a transaction (useful for optimization)
const gasProfile = await aptos.gasProfile({
  sender: account.accountAddress,
  data: {
    function: `${MODULE_ADDRESS}::module::function_name`,
    functionArguments: []
  }
});

console.log("Gas profile:", gasProfile);
typescript
// 分析交易的Gas使用情况(适合优化场景)
const gasProfile = await aptos.gasProfile({
  sender: account.accountAddress,
  data: {
    function: `${MODULE_ADDRESS}::module::function_name`,
    functionArguments: []
  }
});

console.log("Gas profile:", gasProfile);

Anti-patterns

反模式

  1. NEVER use the deprecated
    aptos
    npm package
    - use
    @aptos-labs/ts-sdk
    instead
  2. NEVER skip
    waitForTransaction
    after submitting - transaction may not be committed yet
  3. NEVER hardcode module addresses - use environment variables (
    VITE_MODULE_ADDRESS
    )
  4. NEVER use
    number
    for u128/u256 values
    - JavaScript loses precision above 2^53; use
    bigint
  5. NEVER create multiple
    Aptos
    client instances
    - create one singleton and share it
  6. NEVER ignore transaction simulation results for high-value operations
  7. NEVER hardcode network selection - use environment-based configuration
  8. NEVER store private keys in browser-accessible env vars (e.g.,
    VITE_PRIVATE_KEY
    )
  9. NEVER use
    Account.generate()
    in frontend code
    for real users - use wallet adapter instead
  10. NEVER use raw
    aptos.signAndSubmitTransaction
    in React
    - use the wallet adapter's
    signAndSubmitTransaction
  11. NEVER use
    scriptComposer
    - it was removed in v6.0; use batch transactions or separate calls instead
  12. NEVER use
    getAccountCoinAmount
    or
    getAccountAPTAmount
    - deprecated; use
    getBalance()
    instead
  1. 绝对不要使用已弃用的
    aptos
    npm包
    - 请使用
    @aptos-labs/ts-sdk
  2. 提交交易后绝对不要跳过
    waitForTransaction
    - 此时交易可能还未上链确认
  3. 绝对不要硬编码模块地址 - 请使用环境变量(
    VITE_MODULE_ADDRESS
  4. u128/u256类型的值绝对不要用
    number
    - JavaScript在2^53以上会丢失精度,请使用
    bigint
  5. 绝对不要创建多个
    Aptos
    客户端实例
    - 创建一个单例全局复用即可
  6. 高价值操作绝对不要忽略交易模拟结果
  7. 绝对不要硬编码网络选择 - 请使用基于环境变量的配置
  8. 绝对不要在浏览器可访问的环境变量中存储私钥(例如
    VITE_PRIVATE_KEY
  9. 前端代码中绝对不要为真实用户使用
    Account.generate()
    - 请使用钱包适配器
  10. React中绝对不要直接使用原生的
    aptos.signAndSubmitTransaction
    - 请使用钱包适配器提供的
    signAndSubmitTransaction
  11. 绝对不要使用
    scriptComposer
    - v6.0已移除该功能,请使用批量交易或单独调用替代
  12. 绝对不要使用
    getAccountCoinAmount
    getAccountAPTAmount
    - 已弃用,请使用
    getBalance()
    替代

Edge Cases to Handle

需要处理的边缘案例

ScenarioCheckAction
Resource not found
error.message.includes("RESOURCE_NOT_FOUND")
Return default value or null
Module not deployed
error.message.includes("MODULE_NOT_FOUND")
Show "contract not deployed" message
Function not found
error.message.includes("FUNCTION_NOT_FOUND")
Check function name and module address
Move abort
error.message.includes("ABORTED")
Parse abort code, map to user-friendly error
Out of gas
error.message.includes("OUT_OF_GAS")
Increase
maxGasAmount
and retry
Sequence number error
error.message.includes("SEQUENCE_NUMBER")
Retry after fetching fresh sequence number
Network timeout
error.message.includes("timeout")
Retry with exponential backoff
Account does not exist
error.message.includes("ACCOUNT_NOT_FOUND")
Fund account or prompt user to create one
Insufficient balance
error.message.includes("INSUFFICIENT_BALANCE")
Show balance and required amount
User rejected in walletWallet-specific rejection errorShow "transaction cancelled" message
场景检查条件处理方案
资源不存在
error.message.includes("RESOURCE_NOT_FOUND")
返回默认值或null
模块未部署
error.message.includes("MODULE_NOT_FOUND")
展示「合约未部署」提示
函数不存在
error.message.includes("FUNCTION_NOT_FOUND")
检查函数名和模块地址
Move执行终止
error.message.includes("ABORTED")
解析终止码,转换为用户友好的错误提示
Gas不足
error.message.includes("OUT_OF_GAS")
提高
maxGasAmount
后重试
序列号错误
error.message.includes("SEQUENCE_NUMBER")
获取最新序列号后重试
网络超时
error.message.includes("timeout")
指数退避重试
账户不存在
error.message.includes("ACCOUNT_NOT_FOUND")
为账户注资或提示用户创建账户
余额不足
error.message.includes("INSUFFICIENT_BALANCE")
展示当前余额和所需金额
用户在钱包中拒绝交易钱包专属的拒绝错误展示「交易已取消」提示

Error Handling Pattern

错误处理模式

typescript
async function submitTransaction(
  aptos: Aptos,
  signer: Account,
  payload: InputGenerateTransactionPayloadData
): Promise<string> {
  try {
    const transaction = await aptos.transaction.build.simple({
      sender: signer.accountAddress,
      data: payload
    });

    const pendingTx = await aptos.signAndSubmitTransaction({
      signer,
      transaction
    });

    const committed = await aptos.waitForTransaction({
      transactionHash: pendingTx.hash
    });

    if (!committed.success) {
      throw new Error(`Transaction failed: ${committed.vm_status}`);
    }

    return pendingTx.hash;
  } catch (error) {
    if (error instanceof Error) {
      if (error.message.includes("RESOURCE_NOT_FOUND")) {
        throw new Error("Resource does not exist at the specified address");
      }
      if (error.message.includes("MODULE_NOT_FOUND")) {
        throw new Error("Contract is not deployed at the specified address");
      }
      if (error.message.includes("ABORTED")) {
        const match = error.message.match(/code: (\d+)/);
        const code = match ? match[1] : "unknown";
        throw new Error(`Contract error (code ${code})`);
      }
    }
    throw error;
  }
}
typescript
async function submitTransaction(
  aptos: Aptos,
  signer: Account,
  payload: InputGenerateTransactionPayloadData
): Promise<string> {
  try {
    const transaction = await aptos.transaction.build.simple({
      sender: signer.accountAddress,
      data: payload
    });

    const pendingTx = await aptos.signAndSubmitTransaction({
      signer,
      transaction
    });

    const committed = await aptos.waitForTransaction({
      transactionHash: pendingTx.hash
    });

    if (!committed.success) {
      throw new Error(`Transaction failed: ${committed.vm_status}`);
    }

    return pendingTx.hash;
  } catch (error) {
    if (error instanceof Error) {
      if (error.message.includes("RESOURCE_NOT_FOUND")) {
        throw new Error("Resource does not exist at the specified address");
      }
      if (error.message.includes("MODULE_NOT_FOUND")) {
        throw new Error("Contract is not deployed at the specified address");
      }
      if (error.message.includes("ABORTED")) {
        const match = error.message.match(/code: (\d+)/);
        const code = match ? match[1] : "unknown";
        throw new Error(`Contract error (code ${code})`);
      }
    }
    throw error;
  }
}

File Organization Pattern

文件组织模式

src/
  lib/
    aptos.ts                    # Singleton Aptos client + MODULE_ADDRESS
  view-functions/
    getCount.ts                 # One file per view function
    getListing.ts
  entry-functions/
    increment.ts                # One file per entry function
    createListing.ts
  hooks/
    useCounter.ts               # React hooks wrapping view functions
    useListing.ts
  components/
    WalletProvider.tsx           # AptosWalletAdapterProvider wrapper
    IncrementButton.tsx          # Components calling entry functions
src/
  lib/
    aptos.ts                    # 单例Aptos客户端 + MODULE_ADDRESS
  view-functions/
    getCount.ts                 # 每个视图函数单独一个文件
    getListing.ts
  entry-functions/
    increment.ts                # 每个入口函数单独一个文件
    createListing.ts
  hooks/
    useCounter.ts               # 封装视图函数的React hooks
    useListing.ts
  components/
    WalletProvider.tsx           # AptosWalletAdapterProvider封装
    IncrementButton.tsx          # 调用入口函数的组件

SDK Version Notes (v5.2+ / v6.0)

SDK版本说明(v5.2+ / v6.0)

Balance Queries (v5.1+)

余额查询(v5.1+)

typescript
// CORRECT (v5.1+)
const balance = await aptos.getBalance({
  accountAddress: account.accountAddress
});
// Returns bigint in octas (1 APT = 100_000_000 octas)

// DEPRECATED - do NOT use
// await aptos.getAccountCoinAmount(...)
// await aptos.getAccountAPTAmount(...)
typescript
// 正确写法(v5.1+)
const balance = await aptos.getBalance({
  accountAddress: account.accountAddress
});
// 返回以octas为单位的bigint(1 APT = 100_000_000 octas)

// 已弃用 - 请勿使用
// await aptos.getAccountCoinAmount(...)
// await aptos.getAccountAPTAmount(...)

AIP-80 Private Key Format (v2.0+)

AIP-80私钥格式(v2.0+)

Ed25519 and Secp256k1 private keys now use an AIP-80 prefixed format when serialized with
toString()
:
typescript
const key = new Ed25519PrivateKey("0x...");
key.toString(); // Returns AIP-80 prefixed format, NOT raw hex
Ed25519和Secp256k1私钥通过
toString()
序列化时现在使用AIP-80前缀格式:
typescript
const key = new Ed25519PrivateKey("0x...");
key.toString(); // 返回带AIP-80前缀的格式,而非原始十六进制

AccountAddress Parsing (v1.32+)

AccountAddress解析(v1.32+)

AccountAddress.fromString()
now only accepts SHORT format (60-64 hex chars) by default. Use
AccountAddress.from()
for flexible parsing:
typescript
// CORRECT
const addr = AccountAddress.from("0x1"); // Accepts any format
const addr2 = AccountAddress.fromString("0x000000000000000000000000000000000000000000000000000000000000001"); // SHORT format only

// MAY FAIL in v1.32+
// AccountAddress.fromString("0x1") -- too short for SHORT format
AccountAddress.fromString()
现在默认仅接受短格式(60-64位十六进制字符)。如需灵活解析请使用
AccountAddress.from()
typescript
// 正确写法
const addr = AccountAddress.from("0x1"); // 支持任意格式
const addr2 = AccountAddress.fromString("0x000000000000000000000000000000000000000000000000000000000000001"); // 仅支持短格式

// v1.32+可能报错
// AccountAddress.fromString("0x1") -- 短格式要求下长度不足

Fungible Asset Transfers (v1.39+)

同质化资产转账(v1.39+)

typescript
// Transfer between FA stores directly
await aptos.transferFungibleAssetBetweenStores({
  sender: account,
  fungibleAssetMetadataAddress: metadataAddr,
  senderStoreAddress: fromStore,
  recipientStoreAddress: toStore,
  amount: 1000n
});
typescript
// 直接在FA存储之间转账
await aptos.transferFungibleAssetBetweenStores({
  sender: account,
  fungibleAssetMetadataAddress: metadataAddr,
  senderStoreAddress: fromStore,
  recipientStoreAddress: toStore,
  amount: 1000n
});

Bun Runtime Compatibility

Bun运行时兼容

When using Bun instead of Node.js, disable HTTP/2 in the client config:
typescript
const config = new AptosConfig({
  network: Network.TESTNET,
  clientConfig: { http2: false }
});
使用Bun替代Node.js时,请在客户端配置中关闭HTTP/2:
typescript
const config = new AptosConfig({
  network: Network.TESTNET,
  clientConfig: { http2: false }
});

Account Abstraction (v1.34+, AIP-104)

账户抽象(v1.34+, AIP-104)

The
aptos.abstraction
namespace provides APIs for custom authentication:
typescript
// Check if AA is enabled for an account
const isEnabled = await aptos.abstraction.isAccountAbstractionEnabled({
  accountAddress: "0x...",
  authenticationFunction: `${MODULE_ADDRESS}::auth::authenticate`
});

// Enable AA on an account
const enableTxn = await aptos.abstraction.enableAccountAbstractionTransaction({
  accountAddress: account.accountAddress,
  authenticationFunction: `${MODULE_ADDRESS}::auth::authenticate`
});

// Disable AA
const disableTxn = await aptos.abstraction.disableAccountAbstractionTransaction({
  accountAddress: account.accountAddress,
  authenticationFunction: `${MODULE_ADDRESS}::auth::authenticate`
});

// Use AbstractedAccount for signing with custom auth logic
import { AbstractedAccount } from "@aptos-labs/ts-sdk";
aptos.abstraction
命名空间提供自定义认证相关的API:
typescript
// 检查账户是否开启了AA
const isEnabled = await aptos.abstraction.isAccountAbstractionEnabled({
  accountAddress: "0x...",
  authenticationFunction: `${MODULE_ADDRESS}::auth::authenticate`
});

// 为账户开启AA
const enableTxn = await aptos.abstraction.enableAccountAbstractionTransaction({
  accountAddress: account.accountAddress,
  authenticationFunction: `${MODULE_ADDRESS}::auth::authenticate`
});

// 关闭AA
const disableTxn = await aptos.abstraction.disableAccountAbstractionTransaction({
  accountAddress: account.accountAddress,
  authenticationFunction: `${MODULE_ADDRESS}::auth::authenticate`
});

// 使用AbstractedAccount结合自定义认证逻辑签名
import { AbstractedAccount } from "@aptos-labs/ts-sdk";

References

参考资料

Detailed Patterns (references/ folder):
  • references/wallet-adapter.md
    - Wallet adapter setup and patterns
  • references/transaction-patterns.md
    - Advanced transaction patterns (sponsored, multi-agent, simulation)
  • references/type-mappings.md
    - Complete Move-to-TypeScript type reference
Pattern Documentation (patterns/ folder):
  • ../../../patterns/fullstack/TYPESCRIPT_SDK.md
    - Complete SDK API reference
Official Documentation:
Related Skills:
  • write-contracts
    - Write the Move contracts that this SDK interacts with
  • deploy-contracts
    - Deploy contracts before calling them from TypeScript
  • scaffold-project
    - Bootstrap a fullstack project with SDK already configured
详细模式说明(references/ 文件夹):
  • references/wallet-adapter.md
    - 钱包适配器配置与模式
  • references/transaction-patterns.md
    - 高级交易模式(赞助交易、多代理交易、模拟)
  • references/type-mappings.md
    - 完整的Move到TypeScript类型参考
模式文档(patterns/ 文件夹):
  • ../../../patterns/fullstack/TYPESCRIPT_SDK.md
    - 完整的SDK API参考
官方文档:
相关技能:
  • write-contracts
    - 编写本SDK交互的Move合约
  • deploy-contracts
    - 在TypeScript调用合约前先部署合约
  • scaffold-project
    - 初始化已经配置好SDK的全栈项目