@1money/protocol-ts-sdk

中文文档
3.1.1发布于 2026/10/15MITTypeScriptESM + CJS零依赖构建来源已验证近 30 天下载 3157

1Money协议网络的 sdk

中文使用文档
文档目录21 节
  1. 快开始
  2. 安装
  3. 初始化 API 客户端
  4. 配置自定义 HTTP 页眉
  5. 获取当前检查站编号
  6. 按号码叫检查站
  7. 光盘N
  8. 处理错误
  9. API 方法
  10. 链式 API
  11. 账户 API
  12. 托肯斯 API
  13. 交易 API
  14. 工具函数
  15. 计算交易散列
  16. 随笔地址
  17. 转换为十六进制
  18. 获取多西格账户地址
  19. 签名信件( 过期 )
  20. 从 2. x 移到 3. 0
  21. 许可证

@ 1 钱/ protocol- ts- sdk

1Money Logo

1货币网络协议的TS-SDK

Build Status NPM downloads npm version install size license

快开始

安装

npm i -S @1money/protocol-ts-sdk axios viem @ethereumjs/rlp
# or
yarn add @1money/protocol-ts-sdk axios viem @ethereumjs/rlp
# or
pnpm i @1money/protocol-ts-sdk axios viem @ethereumjs/rlp

初始化 API 客户端

import { api } from '@1money/protocol-ts-sdk';

// Initialize with default settings (mainnet)
const apiClient = api();

// Or specify testnet network
const testnetClient = api({ network: 'testnet' });

// You can also set a custom timeout (in milliseconds)
const apiClient = api({
  network: 'testnet',
  timeout: 5000 // 5 seconds
});

配置自定义 HTTP 页眉

您可以设置所有 API 请求中包含的自定义 HTTP 信头 :

import { setInitConfig } from '@1money/protocol-ts-sdk/client';

// Set custom headers for all requests
setInitConfig({
  headers: {
    'Authorization': 'Bearer your-token',
    'X-Custom-Header': 'custom-value'
  }
});

// You can also combine with other configuration options
setInitConfig({
  baseURL: 'https://api.custom-domain.com',
  timeout: 10000,
  headers: {
    'Authorization': 'Bearer your-token',
    'X-API-Key': 'your-api-key'
  }
});

说明:自定义头被自动与轴默认头合并,确保您的自定义头和库默认的安全头同时包含在所有请求中.

获取当前检查站编号

const number = await apiClient.checkpoints.getNumber()
  .success(response => {
    console.log('number', response.number);
    return response.number;
  })
  .error(err => {
    console.error('Error:', err);
    // return a default value
    return 0;
  });

// do something with the number
// ...

按号码叫检查站

const checkpoint = await apiClient.checkpoints.getByNumber(1)
  .success(response => {
    console.log('checkpoint', response);
  });

光盘N

<script src="https://unpkg.com/@1money/protocol-ts-sdk@latest/umd/1money-protocol-ts-sdk.min.js"></script>

<script>
  const apiClient = window.$1money.api({
    network: 'testnet'
  });

  async function getNumber () {
    const res = await apiClient.checkpoints.getNumber();
    console.log('res: ', res);
  }

  getNumber();
</script>

处理错误

读取返回一个可连锁的类似承诺的包装; v2 写出一个简单的承诺 . 每读(apiClient.<module>.get*, (中文(简体) ), apiClient.<module>.estimateFee(等等)和 每个 legacyV1.* 写入返回类似承诺的对象 .success(), (中文(简体) ), .timeout(), (中文(简体) ), .error() 财务报告和审定财务报表 .rest() 处理器,如下所示。 这个 本土 v2 写法( e)apiClient.tokens.issueToken, (中文(简体) ), apiClient.transactions.payment, (中文(简体) ), 和其余部分 TransactionBuilder → authorize - 提交管道) 简单 async 函数并返回本地 Promise —— 说 await 他们在一个 try/catch 而不是连锁 .success()/.error(); 参见写入示例 下级 API 方法 见下文.

v2 写入结果

V2 写入解析 { hash } 当节点承认交易时. 否则它就会产生一个错误。 分会 instanceof数字 :

丢弃submitted怎么办
TransactionSubmissionErrorfalse节点在录取前拒绝了请求. 纠正原因( :err.action, (中文(简体) ), err.status, (中文(简体) ), err.errorCode然后再次发送.
TransactionLockedErrortrue节点持有这个确切的交易. 重新发送相同的 authorized 直到其收据出现.
TransactionOutcomeUnknownError'unknown'SDK不能说 抬头看 err.transactionHash 并重发 authorized 直到你知道这个州.
TransactionHashMismatchErrortrue节点承认交易,但返回了不同的散列. 别再寄了.

在锁定之后,在任何非交易中,不得为同一目的签署新交易 未知结果: 支付可以执行两次 。 重订 不变 签名 交易总是安全的:它有相同的散列,所以最多一个副本执行. apiClient.transactions.settle(authorized) 重新发送相同的签名字节并用收件解决; 发送新书写方式 apiClient.transactions.submitAndSettle(authorized) 在一个电话中同时进行(见 src/api/transactions/README.md) (中文(简体) ). SDK决定由 action 节点错误体的成员; 在没有节点的节点上, a 422 business_transaction_failed (单位:千美元) 408 未知,但一些固定文本除外 被释放的节点: "已经飞行"的意思是锁定, 拒绝 已签名字节( 例如一个错误的签名或一个错误的链条 id) 表示拒绝 。 见 skills/1money-protocol-sdk/references/client-and-errors.md 全部规则.

问题细节

API 错误合同的节点发送一个 RFC 9457 (韩语) aPI 错误( 不在 /api/health, (中文(简体) ), /api/status 或者说 /metrics) (中文(简体) ). SDK将其分析为 err.problem (类型) ApiProblem每张 ParsedError (单位:千美元) 值为 .error() 得到一个被拒绝的诺言 TransactionSubmissionError, (中文(简体) ), TransactionLockedError 财务报告和审定财务报表 TransactionOutcomeUnknownError {\fn黑体\fs22\bord1\shad0\3ahbe\4ah00\fscx67\fscy66\2chffffff\3ch808080}一个单一的呈文 {\fn黑体\fs22\bord1\shad0\3ahbe\4ah00\fscx67\fscy66\2chffffff\3ch808080}你觉得呢. err.problem 实值 undefined 何时 身体没有弦 type,例如,在更古老的节点上;写入错误保留 err.action 财务报告和审定财务报表 err.problemType 以及那些错误 settle 掷出 最后没有尸体 HTTP 401 不是一个 ParsedError: 默认客户端的登录 规则将生体传递给 .login()或者用它来决定承诺 那个身体 type 财务报告和审定财务报表 action 作为普通成员,但没有 problem。 。 。 .

成员含义
type问题类型 URI, https://developer.1moneynetwork.com/problem/<identifier>,或 about:blank比较整个字符串.
actionfix_request, (中文(简体) ), retry_later, (中文(简体) ), in_progress, (中文(简体) ), check_status 或者说 use_other_node。 。 。 . undefined 当身体没有动作或SDK不知道时:在呈文中,视作为 check_status。 。 。 .
instance请求身份, urn:uuid:<id>当您向节点操作员报告一个问题时引用它.
title, (中文(简体) ), status该类型简略和HTTP状态.
members发送类型中输入的成员( 例如) tx_hash, (中文(简体) ), nonce, (中文(简体) ), path) (中文(简体) ). 一个成员可能在更古老的节点失踪. txHash 财务报告和审定财务报表 retryAfterSecs 读取两个常见的.

决定: type 财务报告和审定财务报表 action,没有打开 message 或者说 title:他们的文本可以更改. 404不一定是"缺席":节点不服务的路径给定 route_not_found。 。 。 .

import type { ParsedError } from '@1money/protocol-ts-sdk';

const TRANSACTION_NOT_FOUND =
  'https://developer.1moneynetwork.com/problem/transaction_not_found';

try {
  await apiClient.transactions.getByHash(hash);
} catch (err) {
  const { problem } = err as ParsedError;
  if (problem?.type === TRANSACTION_NOT_FOUND) {
    // Not found yet. Look it up again later.
  } else {
    console.error(problem?.instance, err);
  }
}

对于可连锁包装器,总是执行两个处理器进行适当的错误管理:

  1. .success():处理成功的API响应
  2. .timeout(): 具体处理超时出错
  3. .error(): 处理所有其他类型的错误
  4. .rest(): 在上述任何处理者完成后运行的最后处理器
import { api } from '@1money/protocol-ts-sdk';

const apiClient = api();

apiClient.someMethod()
  .success(response => {
    // Handle successful response
  })
  .timeout(err => {
    // Handle timeout case
  })
  .error(err => {
    // Handle other errors
  });

你用得着 rest 来处理所有其他错误:

apiClient.someMethod()
  .success(response => {
    // Handle successful response
  })
  .rest(err => {
    // Handle other cases
  });

自动/等待

您也可以使用 async/ 等待处理响应 :

import { api } from '@1money/protocol-ts-sdk';

const apiClient = api();

try {
  const response = await apiClient.someMethod();
  console.log('Response:', response);
} catch (err) {
  console.error('Error:', err);
}

答应

您也可以使用标准 promise 处理响应:

import { api } from '@1money/protocol-ts-sdk';

const apiClient = api();

apiClient.someMethod()
  .then(response => {
    console.log('Response:', response);
  })
  .catch(err => {
    console.error('Error:', err);
  });

API 方法

下面的每个文字都遵循同样的 本土 v2 形状 : prepare 签字 文摘 • authorize - 提交结果 AuthorizedTxV2。见 从 2. x 移到 3. 0 财务报告和审定财务报表 skills/1money-protocol-sdk/references/transactions.md 为整个管道, 每个建筑工的田地和遗产 LegacyV1TransactionBuilder 编号 : api().<module>.legacyV1.* 路径.

链式 API

获取链式标识

apiClient.chain.getChainId()
  .success(response => {
    console.log('Current chain id:', response.chain_id);
  })
  .error(err => {
    console.error('Error:', err);
  });

账户 API

获取账户 Nonce

const address = '0x9E1E9688A44D058fF181Ed64ddFAFbBE5CC74ff3';
apiClient.accounts.getNonce(address)
  .success(response => {
    console.log('Account nonce:', response);
  })
  .error(err => {
    console.error('Error:', err);
  });

获取关联的托肯账户

const address = '0x9E1E9688A44D058fF181Ed64ddFAFbBE5CC74ff3';
const token = '0x2cd8999Be299373D7881f4aDD11510030ad1412F';
apiClient.accounts.getTokenAccount(address, token)
  .success(response => {
    console.log('Associated token account:', response);
  })
  .error(err => {
    console.error('Error:', err);
  });

创建多西格账户

createMultisig 实值 v2 仅 没有 legacyV1 窗体和无 accounts.legacyV1 名称空间.

import {
  TransactionBuilder,
  createPrivateKeySigner,
  deriveMultisigAddress
} from '@1money/protocol-ts-sdk';

// Your private key (DO NOT share or commit your private key)
const privateKey = process.env.ONE_MONEY_PRIVATE_KEY as `0x${string}`;
const creatorAddress = '0x9E1E9688A44D058fF181Ed64ddFAFbBE5CC74ff3';

// 33-byte SEC1-compressed public keys. 2-20 signers; a weight is a u8
// (1-255) and the threshold must not exceed the total signer weight.
const signers = [
  { public_key: '0x02...', weight: 1 },
  { public_key: '0x03...', weight: 1 }
];
const threshold = 2;

// The node never echoes the new account's address, so compute it first --
// this is the same value the node derives at execution.
const multisigAddress = deriveMultisigAddress(signers, threshold);

// Get chain id and current nonce
const { chain_id } = await apiClient.chain.getChainId();
const { nonce } = await apiClient.accounts.getNonce(creatorAddress);

const prepared = TransactionBuilder.createMultisig({
  chain_id,
  nonce,
  signers,
  threshold
});

const signature = await createPrivateKeySigner(privateKey).signDigest(prepared.signingHash);
const authorized = prepared.authorize(signature);

// v2 write: returns a plain Promise -- await it in a try/catch.
try {
  const response = await apiClient.accounts.createMultisig(authorized);
  console.log('Multisig', multisigAddress, 'created in tx', response.hash);
} catch (err) {
  console.error('Error:', err);
}

见 获取多西格账户地址 页:1 由自己决定.

托肯斯 API

获取 Token 元数据

const tokenAddress = '0x2cd8999Be299373D7881f4aDD11510030ad1412F';
apiClient.tokens.getTokenMetadata(tokenAddress)
  .success(response => {
    console.log('Token metadata:', response);
  })
  .error(err => {
    console.error('Error:', err);
  });

发行新托肯

import {
  TransactionBuilder,
  createPrivateKeySigner
} from '@1money/protocol-ts-sdk';

// Your private key (DO NOT share or commit your private key)
const privateKey = process.env.ONE_MONEY_PRIVATE_KEY as `0x${string}`;
const masterAuthority = '0x9E1E9688A44D058fF181Ed64ddFAFbBE5CC74ff3';

// Get chain id and current nonce
const { chain_id } = await apiClient.chain.getChainId();
const { nonce } = await apiClient.accounts.getNonce(masterAuthority);

// Prepare (validates fields, computes the digest to sign).
const prepared = TransactionBuilder.tokenIssue({
  chain_id,
  nonce,
  symbol: 'MTK',
  name: 'My Token',
  decimals: 18,
  master_authority: masterAuthority,
  is_private: true,
  clawback_enabled: true
});

// Sign the digest, then authorize it into a plain-JSON request.
const signature = await createPrivateKeySigner(privateKey).signDigest(prepared.signingHash);
const authorized = prepared.authorize(signature);

// v2 write: submitAuthorized returns a plain Promise, not the chainable
// wrapper -- await it in a try/catch.
try {
  const response = await apiClient.tokens.issueToken(authorized);
  console.log('Token issued:', response.token, 'in tx', response.hash);
} catch (err) {
  console.error('Error:', err);
}

薄荷图案

import {
  TransactionBuilder,
  createPrivateKeySigner
} from '@1money/protocol-ts-sdk';

// Your private key (DO NOT share or commit your private key)
const privateKey = process.env.ONE_MONEY_PRIVATE_KEY as `0x${string}`;
const mintAuthority = '0x9E1E9688A44D058fF181Ed64ddFAFbBE5CC74ff3';

// Get chain id and current nonce
const { chain_id } = await apiClient.chain.getChainId();
const { nonce } = await apiClient.accounts.getNonce(mintAuthority);

const prepared = TransactionBuilder.tokenMint({
  chain_id,
  nonce,
  recipient: '0xa128999be299373d7881f4add11510030ad13512',
  value: '1000000000000000000',
  token: '0x2cd8999Be299373D7881f4aDD11510030ad1412F'
});

const signature = await createPrivateKeySigner(privateKey).signDigest(prepared.signingHash);
const authorized = prepared.authorize(signature);

// v2 write: returns a plain Promise -- await it in a try/catch.
try {
  const response = await apiClient.tokens.mintToken(authorized);
  console.log('Mint transaction hash:', response.hash);
} catch (err) {
  console.error('Error:', err);
}

签名人一定是签名人的 master_authority 或持有所赋予的薄荷 权力——见 格兰特·托肯管理局授予 (a) 允许使用薄荷,以抵减每薄荷的有限津贴 主权威是没有干扰的.

管理托肯黑名单/白名单

import {
  TransactionBuilder,
  createPrivateKeySigner
} from '@1money/protocol-ts-sdk';
import { ManageListAction } from '@1money/protocol-ts-sdk/api';

// Your private key (DO NOT share or commit your private key)
const privateKey = process.env.ONE_MONEY_PRIVATE_KEY as `0x${string}`;
const operatorAddress = '0x9E1E9688A44D058fF181Ed64ddFAFbBE5CC74ff3';

// Get chain id and current nonce
const { chain_id } = await apiClient.chain.getChainId();
const { nonce } = await apiClient.accounts.getNonce(operatorAddress);

// tokenBlacklist and tokenWhitelist are distinct v2 operations (distinct
// signing hashes) — build the one you intend to submit, they are not
// interchangeable the way the pre-3.0 tokenManageList builder was.
const prepared = TransactionBuilder.tokenBlacklist({
  chain_id,
  nonce,
  action: ManageListAction.Add,
  address: operatorAddress,
  token: '0x2cd8999Be299373D7881f4aDD11510030ad1412F'
});

const signature = await createPrivateKeySigner(privateKey).signDigest(prepared.signingHash);
const authorized = prepared.authorize(signature);

// v2 write: returns a plain Promise -- await it in a try/catch.
try {
  const response = await apiClient.tokens.manageBlacklist(authorized);
  console.log('Blacklist update transaction hash:', response.hash);
} catch (err) {
  console.error('Error:', err);
}

白名单是相同的形状结束到结束——将建设者和 提交方法,并在您实际打算提交的方法上签名:

const prepared = TransactionBuilder.tokenWhitelist({
  chain_id,
  nonce,
  action: ManageListAction.Add,
  address: '0xa128999be299373d7881f4add11510030ad13512',
  token: '0x2cd8999Be299373D7881f4aDD11510030ad1412F'
});

const signature = await createPrivateKeySigner(privateKey).signDigest(prepared.signingHash);
const response = await apiClient.tokens.manageWhitelist(prepared.authorize(signature));

白名单适用于以 is_private: true启用 ManageListAction.Remove 将地址从任何一份名单上删除.

烧掉托肯斯

import {
  TransactionBuilder,
  createPrivateKeySigner
} from '@1money/protocol-ts-sdk';

// Your private key (DO NOT share or commit your private key)
const privateKey = process.env.ONE_MONEY_PRIVATE_KEY as `0x${string}`;
const ownerAddress = '0x9E1E9688A44D058fF181Ed64ddFAFbBE5CC74ff3';

// Get chain id and current nonce
const { chain_id } = await apiClient.chain.getChainId();
const { nonce } = await apiClient.accounts.getNonce(ownerAddress);

const prepared = TransactionBuilder.tokenBurn({
  chain_id,
  nonce,
  value: '1000000000000000000',
  token: '0x2cd8999Be299373D7881f4aDD11510030ad1412F'
});

const signature = await createPrivateKeySigner(privateKey).signDigest(prepared.signingHash);
const authorized = prepared.authorize(signature);

// v2 write: returns a plain Promise -- await it in a try/catch.
try {
  const response = await apiClient.tokens.burnToken(authorized);
  console.log('Burn transaction hash:', response.hash);
} catch (err) {
  console.error('Error:', err);
}

抓回脚趾

import {
  TransactionBuilder,
  createPrivateKeySigner
} from '@1money/protocol-ts-sdk';

// Your private key (DO NOT share or commit your private key)
const privateKey = process.env.ONE_MONEY_PRIVATE_KEY as `0x${string}`;
const clawbackAuthority = '0x9E1E9688A44D058fF181Ed64ddFAFbBE5CC74ff3';

// Get chain id and current nonce
const { chain_id } = await apiClient.chain.getChainId();
const { nonce } = await apiClient.accounts.getNonce(clawbackAuthority);

const prepared = TransactionBuilder.tokenClawback({
  chain_id,
  nonce,
  token: '0x2cd8999Be299373D7881f4aDD11510030ad1412F',
  from: '0xa128999be299373d7881f4add11510030ad13512',
  recipient: clawbackAuthority,
  value: '1000000000000000000'
});

const signature = await createPrivateKeySigner(privateKey).signDigest(prepared.signingHash);
const authorized = prepared.authorize(signature);

// v2 write: returns a plain Promise -- await it in a try/catch.
try {
  const response = await apiClient.tokens.clawbackToken(authorized);
  console.log('Clawback transaction hash:', response.hash);
} catch (err) {
  console.error('Error:', err);
}

Clawback 移动符号出 from 没有那个账户的签名,所以它 只工作于发行的符号 clawback_enabled: true (默认)和 签名者必须是签名者 master_authority 或持有给予的 AuthorityType.Clawback 权力.

格兰特·托肯管理局

import {
  TransactionBuilder,
  createPrivateKeySigner
} from '@1money/protocol-ts-sdk';
import { AuthorityAction, AuthorityType } from '@1money/protocol-ts-sdk/api';

// Your private key (DO NOT share or commit your private key)
const privateKey = process.env.ONE_MONEY_PRIVATE_KEY as `0x${string}`;
const masterAddress = '0x9E1E9688A44D058fF181Ed64ddFAFbBE5CC74ff3';

// Get chain id and current nonce
const { chain_id } = await apiClient.chain.getChainId();
const { nonce } = await apiClient.accounts.getNonce(masterAddress);

const prepared = TransactionBuilder.tokenAuthority({
  chain_id,
  nonce,
  action: AuthorityAction.Grant,
  authority_type: AuthorityType.MasterMint,
  authority_address: '0x9E1E9688A44D058fF181Ed64ddFAFbBE5CC74ff3',
  token: '0x2cd8999Be299373D7881f4aDD11510030ad1412F',
  value: '1000000000000000000000'
});

const signature = await createPrivateKeySigner(privateKey).signDigest(prepared.signingHash);
const authorized = prepared.authorize(signature);

// v2 write: returns a plain Promise -- await it in a try/catch.
try {
  const response = await apiClient.tokens.grantAuthority(authorized);
  console.log('Authority update transaction hash:', response.hash);
} catch (err) {
  console.error('Error:', err);
}

暂停/ 取消暂停托肯

import {
  TransactionBuilder,
  createPrivateKeySigner
} from '@1money/protocol-ts-sdk';
import { PauseAction } from '@1money/protocol-ts-sdk/api';

// Your private key (DO NOT share or commit your private key)
const privateKey = process.env.ONE_MONEY_PRIVATE_KEY as `0x${string}`;
const pauseAuthority = '0x9E1E9688A44D058fF181Ed64ddFAFbBE5CC74ff3';

// Get chain id and current nonce
const { chain_id } = await apiClient.chain.getChainId();
const { nonce } = await apiClient.accounts.getNonce(pauseAuthority);

const prepared = TransactionBuilder.tokenPause({
  chain_id,
  nonce,
  action: PauseAction.Pause, // PauseAction.Unpause to lift it
  token: '0x2cd8999Be299373D7881f4aDD11510030ad1412F'
});

const signature = await createPrivateKeySigner(privateKey).signDigest(prepared.signingHash);
const authorized = prepared.authorize(signature);

// v2 write: returns a plain Promise -- await it in a try/catch.
try {
  const response = await apiClient.tokens.pauseToken(authorized);
  console.log('Pause transaction hash:', response.hash);
} catch (err) {
  console.error('Error:', err);
}

更新托肯元数据

import {
  TransactionBuilder,
  createPrivateKeySigner
} from '@1money/protocol-ts-sdk';

// Your private key (DO NOT share or commit your private key)
const privateKey = process.env.ONE_MONEY_PRIVATE_KEY as `0x${string}`;
const metadataAuthority = '0x9E1E9688A44D058fF181Ed64ddFAFbBE5CC74ff3';

// Get chain id and current nonce
const { chain_id } = await apiClient.chain.getChainId();
const { nonce } = await apiClient.accounts.getNonce(metadataAuthority);

const prepared = TransactionBuilder.tokenMetadata({
  chain_id,
  nonce,
  name: 'My Token',
  uri: 'https://example.com/my-token.json',
  token: '0x2cd8999Be299373D7881f4aDD11510030ad1412F',
  additional_metadata: [{ key: 'category', value: 'stablecoin' }]
});

const signature = await createPrivateKeySigner(privateKey).signDigest(prepared.signingHash);
const authorized = prepared.authorize(signature);

// v2 write: returns a plain Promise -- await it in a try/catch.
try {
  const response = await apiClient.tokens.updateMetadata(authorized);
  console.log('Metadata transaction hash:', response.hash);
} catch (err) {
  console.error('Error:', err);
}

additional_metadata 取代整个清单,而不是合并到其中—— 发送所有你想要的对。 过 [] 来清理它.

桥梁和薄荷

import {
  TransactionBuilder,
  createPrivateKeySigner
} from '@1money/protocol-ts-sdk';

// Your private key (DO NOT share or commit your private key)
const privateKey = process.env.ONE_MONEY_PRIVATE_KEY as `0x${string}`;
const bridgeOperatorAddress = '0x9E1E9688A44D058fF181Ed64ddFAFbBE5CC74ff3';

// Get chain id and current nonce
const { chain_id } = await apiClient.chain.getChainId();
const { nonce } = await apiClient.accounts.getNonce(bridgeOperatorAddress);

const prepared = TransactionBuilder.tokenBridgeAndMint({
  chain_id,
  nonce,
  recipient: '0x6324dAc598f9B637824978eD6b268C896E0c40E0',
  value: '25000000000000000000',
  token: '0x2cd8999Be299373D7881f4aDD11510030ad1412F',
  source_chain_id: 1,
  source_tx_hash: '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef',
  bridge_metadata: 'bridge_from_chain_1'
});

const signature = await createPrivateKeySigner(privateKey).signDigest(prepared.signingHash);
const authorized = prepared.authorize(signature);

// v2 write: returns a plain Promise -- await it in a try/catch.
try {
  const response = await apiClient.tokens.bridgeAndMint(authorized);
  console.log('Bridge and mint transaction hash:', response.hash);
} catch (err) {
  console.error('Error:', err);
}

燃烧和桥梁

import {
  TransactionBuilder,
  createPrivateKeySigner
} from '@1money/protocol-ts-sdk';

// Your private key (DO NOT share or commit your private key)
const privateKey = process.env.ONE_MONEY_PRIVATE_KEY as `0x${string}`;
const senderAddress = '0x6324dAc598f9B637824978eD6b268C896E0c40E0';

// Get chain id and current nonce
const { chain_id } = await apiClient.chain.getChainId();
const { nonce } = await apiClient.accounts.getNonce(senderAddress);

const prepared = TransactionBuilder.tokenBurnAndBridge({
  chain_id,
  nonce,
  sender: senderAddress,
  value: '20000000000000000000',
  token: '0x2cd8999Be299373D7881f4aDD11510030ad1412F',
  destination_chain_id: 1,
  destination_address: '0x1234567890abcdef1234567890abcdef12345678',
  escrow_fee: '1000000000000000000',
  bridge_metadata: 'bridge_to_chain_1',
  bridge_param: '0x'
});

const signature = await createPrivateKeySigner(privateKey).signDigest(prepared.signingHash);
const authorized = prepared.authorize(signature);

// v2 write: returns a plain Promise -- await it in a try/catch.
try {
  const response = await apiClient.tokens.burnAndBridge(authorized);
  console.log('Burn and bridge transaction hash:', response.hash);
} catch (err) {
  console.error('Error:', err);
}

交易 API

获取交易细节

const txHash = '0xf55f9525be94633b56f954d3252d52b8ef42f5fd5f9491b243708471c15cc40c';
apiClient.transactions.getByHash(txHash)
  .success(response => {
    console.log('Transaction details:', response);
  })
  .error(err => {
    console.error('Error:', err);
  });

获取交易收据

const txHash = '0xf55f9525be94633b56f954d3252d52b8ef42f5fd5f9491b243708471c15cc40c';
apiClient.transactions.getReceiptByHash(txHash)
  .success(response => {
    console.log('Transaction receipt:', response);
  })
  .error(err => {
    console.error('Error:', err);
  });

估计交易费

const fromAddress = '0x9E1E9688A44D058fF181Ed64ddFAFbBE5CC74ff3';
const toAddress = '0x6324dAc598f9B637824978eD6b268C896E0c40E0';
const value = '1000000000';
const tokenAddress = '0x2cd8999Be299373D7881f4aDD11510030ad1412F';

apiClient.transactions.estimateFee(fromAddress, toAddress, value, tokenAddress)
  .success(response => {
    console.log('Estimated fee:', response);
  })
  .error(err => {
    console.error('Error:', err);
  });

提交付款交易

import {
  TransactionBuilder,
  createPrivateKeySigner
} from '@1money/protocol-ts-sdk';

// Your private key (DO NOT share or commit your private key)
const privateKey = process.env.ONE_MONEY_PRIVATE_KEY as `0x${string}`;
const senderAddress = '0x9E1E9688A44D058fF181Ed64ddFAFbBE5CC74ff3';

// Get chain id and current nonce
const { chain_id } = await apiClient.chain.getChainId();
const { nonce } = await apiClient.accounts.getNonce(senderAddress);

// Prepare (validates fields, computes the digest to sign). `memo` is always
// sent on the wire; omit the option for the all-empty "no business memo".
const prepared = TransactionBuilder.payment({
  chain_id,
  nonce,
  recipient: '0xa128999be299373d7881f4add11510030ad13512',
  value: '1000000000',
  token: '0x2cd8999Be299373D7881f4aDD11510030ad1412F'
});

// Sign the digest, then authorize it into a plain-JSON request.
const signature = await createPrivateKeySigner(privateKey).signDigest(prepared.signingHash);
const authorized = prepared.authorize(signature); // signature.v must be 0 or 1

// v2 write: returns a plain Promise -- await it in a try/catch.
try {
  const response = await apiClient.transactions.payment(authorized);
  console.log('Payment transaction hash:', response.hash);
} catch (err) {
  console.error('Error:', err);
}

在付款后附上备忘录

每个v2的构建者都会接受一个可选的第二个论点,持有备忘录. 备忘录 实值 签字有效载荷的一部分,所以同样的付款 与不同的备忘录 生成不同的 signingHash 和不同的交易散列 后面贴有信头或注释.

import {
  TransactionBuilder,
  createPrivateKeySigner
} from '@1money/protocol-ts-sdk';

const prepared = TransactionBuilder.payment(
  {
    chain_id,
    nonce,
    recipient: '0xa128999be299373d7881f4add11510030ad13512',
    value: '1000000000',
    token: '0x2cd8999Be299373D7881f4aDD11510030ad1412F'
  },
  {
    memo: {
      type: 'purpose/SALA',
      format: 'text/plain',
      data: 'August salary'
    }
  }
);

// Everything downstream is unchanged -- the memo is already inside the digest.
const signature = await createPrivateKeySigner(privateKey).signDigest(prepared.signingHash);
const response = await apiClient.transactions.payment(prepared.authorize(signature));

字段限制,由 SDK 和节点相同执行 :

外地马克斯允许字符
type128 字节仅限URL安全(RFC 3986 无保留 + gen-delims + sub-delims +) %(中文(简体) )
format64 字节只有 URL 安全, 同一集
data256 字节除NUL、C0/C1控制编码点外的任何UTF-8和代号

限制是 UTF-8 字节长度, 不是字符计数 —— 说 '结算备注' 实值 四个字符,但十二字节。 每个字段都是可选的 备忘以空字符串填充其余部分,省略选项完全发送 { type: '', format: '', data: '' },但仍在签名.

校验为局部并发生 在引用任何签名符之前: 建造者 电话 validateMemo 在计算摘要时, 错误的备忘抛出 而不是花一个签名操作—— 这很重要,当签名者是 由HSM或KMS支持.

import { MemoValidationError } from '@1money/protocol-ts-sdk';

try {
  TransactionBuilder.payment(payload, {
    memo: { type: 'a'.repeat(200), format: '', data: '' }
  });
} catch (err) {
  if (err instanceof MemoValidationError) {
    // 'MEMO_TYPE_TOO_LONG' | 'MEMO_TYPE_INVALID_CHARS' | 'MEMO_FORMAT_TOO_LONG'
    // | 'MEMO_FORMAT_INVALID_CHARS' | 'MEMO_DATA_TOO_LONG'
    // | 'MEMO_DATA_CONTROL_CHARS' | 'MEMO_TOO_LARGE'
    console.error(err.code, err.message);
  }
}

从交易中读取(不是收据),在交易中归还 每个包含备忘的 v2 信封 :

const tx = await apiClient.transactions.getByHash(
  prepared.authorize(signature).transactionHash
);
console.log(tx.memo); // { type: 'purpose/SALA', format: 'text/plain', data: 'August salary' }

同样的选项对每个v2的构建者都起作用—— tokenIssue, (中文(简体) ), tokenMint, (中文(简体) ), tokenBlacklist, (中文(简体) ), batchPayment 其他人都接受了 { memo } 作为 第二次辩论就是这种形式.

提交批次付款

在一桩土生土长的V2交易中,向许多受款人支付一枚地契. batchPayment 实值 v2 仅: SDK 刻意暴露出没有遗留的批量 付款构建者或 transactions.legacyV1.batchPayment,即使一个节点仍然 保留已贬值的 v1 路由 .

import {
  TransactionBuilder,
  calculateBatchPaymentOperationsHash,
  createPrivateKeySigner
} from '@1money/protocol-ts-sdk';

// Your private key (DO NOT share or commit your private key)
const privateKey = process.env.ONE_MONEY_PRIVATE_KEY as `0x${string}`;
const senderAddress = '0x9E1E9688A44D058fF181Ed64ddFAFbBE5CC74ff3';

const token = '0x2cd8999Be299373D7881f4aDD11510030ad1412F';
const operations = [
  { recipient: '0xa128999be299373d7881f4add11510030ad13512', amount: '1000000000' },
  { recipient: '0x6324dAc598f9B637824978eD6b268C896E0c40E0', amount: '2000000000' }
];

// An unsigned, non-binding point-in-time quote. It is not a fee cap and is
// not copied into the payload, signing hash, authorization, or submission.
const quote = await apiClient.transactions.estimateBatchPaymentFee({
  from: senderAddress,
  token,
  operations
});
console.log('Estimated fee:', quote.fee, 'plan:', quote.plan);

// Get chain id and a fresh current nonce.
const { chain_id } = await apiClient.chain.getChainId();
const { nonce } = await apiClient.accounts.getNonce(senderAddress);

// This optional field is a caller choice. If supplied, the builder recomputes
// it and rejects a mismatch locally before any signer is invoked.
const operationsHash = calculateBatchPaymentOperationsHash(operations);

const prepared = TransactionBuilder.batchPayment({
  chain_id,
  nonce,
  token,
  operations,
  created_at: Math.floor(Date.now() / 1000), // unix seconds
  operations_hash: operationsHash,
  batch_id: 'payroll-2026-08'
}, {
  memo: {
    type: 'purpose/SALA',
    format: 'text/plain',
    data: 'payroll-2026-08'
  }
});

const signature = await createPrivateKeySigner(privateKey).signDigest(prepared.signingHash);
const authorized = prepared.authorize(signature);

// v2 write: returns a plain Promise -- await it in a try/catch.
try {
  const response = await apiClient.transactions.batchPayment(authorized);
  // The SDK already checks this case-insensitively before resolving.
  if (
    response.hash.toLowerCase() !==
    authorized.transactionHash.toLowerCase()
  ) {
    throw new Error('SDK already rejects a server/local hash mismatch');
  }
  console.log('Batch payment transaction hash:', response.hash);
} catch (err) {
  console.error('Error:', err);
}

operations 不得为空;每个收款人和金额必须是非零,以及 总和不得超过U256:MAX. operations_hash 可选,但 提供值必须是峡谷 calculateBatchPaymentOperationsHash(operations) 结果或准备失败 当地. batch_id 仅被签名的相关元数据 : 它没有独有性, 分解、一能或重放保证。 交易非ce 仍然保留 交易级重放机制。 每个操作都签名并发送为 没错 { recipient, amount }; 未键入的额外运行时间属性 呼叫者被忽略, 无法到达授权请求 .

批发付款总是会签名和发送完整的备忘录. 选择 memo 实值 有效并发送 { type: '', format: '', data: '' }; 这三个空字符串 仍然是所签署有效载荷的一部分。 过时的客户端 max_fee 字段 不接受。 实际发送者借项是所有操作金额的总和 加收据的实际字符串 fee_used而不是估计 批量赋能, 操作计数和编码大小限制,收费资产是动态节点 治理规则,所以成功的估计不是录取保证.

将返回的散列索引后,阅读其收据(或最终收据)和 使用情况 execution_events 检查接收者:

const receipt = await apiClient.transactions.getReceiptByHash(
  authorized.transactionHash
);

// Batch Payment has no single recipient. This zero address is a sentinel.
console.log(receipt.success_info?.receiver);

for (const event of receipt.execution_events ?? []) {
  if (event.event_type === 'PaymentExecuted') {
    console.log(event.recipient, event.amount);
  }
}

console.log('actual fee:', receipt.fee_used);

对于批付款, success_info.receiver 是零地址监视器,不是 转移目的地; 实际收款人和金额是订购的 PaymentExecuted 事件. batch_info.failure 保留用于转发 兼容性但为 null 在目前生产形状的反应中,不是 终端故障信号。 如果操作失败, 节点会回滚 收款人信贷、汇款人借项和操作员-收费移动在一起;不 从这个规则推断出一个非核故障对象.

为了核实有意退缩的情况,不依赖收据或 错误体作为终端信号:故障可能为收不到或模糊,以及 batch_info.failure 遗 物 null 在目前的行为。 在提交之前, 发送方、每个计划接收方和操作费简表余额 接收者。 提交一次,仅对划界案提出有限度的观察 普通/ 最终化的接收路径, 然后验证每个快照没有变化 。 使用 一个孤立的发送者,所以任何不确定的非ce 或 mempol 状态都不会影响其他 交易.

工具函数

计算交易散列

import { calcTxHash } from '@1money/protocol-ts-sdk';

// Create the payload array
const payload = [
  1212101, // chain_id
  2, // nonce
  '0x0000000000000000000000000000000000000000', // recipient
  1024, // value
  '0x0000000000000000000000000000000000000000', // token
];

// Create the signature object
const signature = {
  r: '0xe9ef6ce7aaeb4656f197b63a96c932ab5e0fd2df0913f6af1c8e7b1879e5ed0a',
  s: '0x68a9cbaa35af5e3d896a2841d19a42dba729380a1c91864403de872578f6f6c3',
  v: 0,
};

// Calculate the transaction hash
const hash = calcTxHash(payload, signature);
console.log('Transaction hash:', hash);

随笔地址

import { deriveTokenAddress } from '@1money/protocol-ts-sdk';

const walletAddress = '0xA634dfba8c7550550817898bC4820cD10888Aac5';
const mintAddress = '0x8E9d1b45293e30EF38564582979195DD16A16E13';

// Derive the token account address
const tokenAddress = deriveTokenAddress(walletAddress, mintAddress);
console.log('Token account address:', tokenAddress);

转换为十六进制

import { toHex } from '@1money/protocol-ts-sdk';

// Convert different types to hex
const boolHex = toHex(true); // '0x1' (minimal hex, not zero-padded)
const numHex = toHex(123); // '0x7b'
const strHex = toHex('hello'); // '0x68656c6c6f'
const arrHex = toHex([1, 2, 3]); // '0x010203'

获取多西格账户地址

计算本地多西格账户的地址 在此之前 创建它 - accounts.createMultisig 仅返回 { hash }从没有地址:

import { deriveMultisigAddress } from '@1money/protocol-ts-sdk';

const address = deriveMultisigAddress(
  [
    { public_key: '0x02...', weight: 1 },
    { public_key: '0x03...', weight: 1 },
  ],
  2 // threshold
); // → '0x…'

签名信件( 过期 )

import { signMessage } from '@1money/protocol-ts-sdk';

// Your private key (DO NOT share or commit your private key)
const privateKey = 'YOUR_PRIVATE_KEY';

// Create the payload array for signing
const payload = [
  1212101, // chain_id
  2, // nonce
  '0x0000000000000000000000000000000000000000', // recipient
  '1000000000000000000', // value (in wei)
  '0x0000000000000000000000000000000000000000', // token
];

// Sign the message
const signature = await signMessage(payload, privateKey);

signMessage 财务报告和审定财务报表 encodePayload 是遗产 @deprecated 帮手 偏爱 TransactionBuilder (或 LegacyV1TransactionBuilder 移民期间 窗口),用于新代码 - 见 从 2. x 移到 3. 0。 。 。 .

从 2. x 移到 3. 0

3.0 使域分隔 本土 v2 签名默认方案 将预-3.0方案移动到明确的命名空间后。 这是破解 更改任何代码调用 TransactionBuilder 直接说.

  • TransactionBuilder 现在意味着v2. TransactionBuilder.payment(...) (和 每个其它操作)返回 a PreparedTxV2而不是旧的 PreparedTx。 。 。 . 它已经没有了 .sign() 编号 : .attachSignature() 编号 : .rlpBytes 编号 : .signatureHash它已经 .signingHash 财务报告和审定财务报表 .authorize(signature) 换句话说.

  • 3:0前计划仍然存在,不变,作为 LegacyV1TransactionBuilder (同样的建筑师名称,相同 .sign()编号 : .attachSignature()编号 :.toRequest() 形状和以前一样) api().<module>.legacyV1.* 提交方法(例如:. client.transactions.legacyV1.payment(...), (中文(简体) ), client.tokens.legacyV1.manageBlacklist(...)) (中文(简体) ). accounts 没有 legacyV1 命名空间,以及 batchPayment 编号 : createMultisig 没有遗产 两者都是 v2 .

  • 写作方法现在采用 AuthorizedTxV2,输出 prepared.authorize(signature),而不是从 signed.toRequest()。 。 。 . AuthorizedTxV2 是一个简单的 JSON 并可以跨越一个进程 边界(在一个地方签名,从另一个地方提交)。 每次打给 authorize 返回一个独立的请求快照; 更改早先的请求, 包括备忘录在内,不得影响以后的授权或仓促执行.

  • 写法现在返回原生 Promise,而不是链式包装. 这是很容易错过的,因为 原文不变 一样 客户端现在有两个调用样式:

    // Read: still the promise wrapper.
    apiClient.tokens.getTokenMetadata(token).success(res => …).error(err => …);
    
    // Write: a plain Promise. Calling .success() on it throws
    // "apiClient.tokens.issueToken(...).success is not a function".
    try {
      const res = await apiClient.tokens.issueToken(authorized);
    } catch (err) { … }
    

    这么说吧 .success()编号 :.error()编号 :.timeout()编号 :.rest() 任何2.x上的链条 写入 电话必须是 await 在一个 try编号 :catch键入脚本标记 编译时间; plain-JavaScript呼叫器只在运行时查找.

  • tokenManageList 不见了. 它分裂成 tokenBlacklist 财务报告和审定财务报表 tokenWhitelist • 不同的业务,有明显的签名散列车,配对 与 tokens.manageBlacklist 编号 : tokens.manageWhitelist 页:1 你个 无法再制造出一个有效载荷并将其提交两个终点.

  • memo 现在总是发送 在v2表面。 每一次行动都带有 电线上的备忘录; 省略 memo 选项发送全空 { type: '', format: '', data: '' } 而不是离开球场 完全没有。 这与3:0前的行为不同,当时没有备忘录 与当前不同的代码路径.

  • 批量支付使用克能克 v2载荷. 被除名者 max_fee 字段 既未签名也未接受; 请求未签名 transactions.estimateBatchPaymentFee({ from, token, operations }) 引用 换句话说 共享 EstimateFee 现在的反应是 fee: string 和可选 plan?: string因此,这也适用于现有的 estimateFee() 电话.

  • 对所有呼叫者都更正接收字段. TransactionReceipt.fee_used 是小数字符串(不是数字),并且 to 改为 recipient。 。 。 . FinalizedTransactionReceipt 扩展此更正的常见收件形状, 因此,最终读取的呼叫者必须做出同样的更新.

  • 签署 v 必须是 0 或者说 1 v2 表面; 遗留 27编号 :28 实值 被拒绝 authorize,没有转换.

遗产没有公布日落日期 /v1 写入表面或用于 LegacyV1TransactionBuilder ——节点不作广告,操作员 运行切换 在他们自己的时间表。 检查 client.status.getNativeWriteStatus() 以查看当前存在的表面 之前取决于其中之一.

见 skills/1money-protocol-sdk/references/transactions.md 全数v2 管道和每个建筑工的田地 skills/1money-protocol-sdk/references/client-and-errors.md 用于新v2 错误代码和 TransactionHashMismatchError。 。 。 .

许可证

麻省理工学院

版本与发布记录

@1money/protocol-ts-sdk 共发布 27 个版本,首次发布于 2025/08/18;过去 12 个月发布了 24 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
3.1.1latest2026/10/1523 天前
3.1.02026/10/1424 天前
3.0.02026/08/142 个月前
2.1.12026/06/264 个月前
2.1.02026/06/224 个月前
2.1.0-beta.1beta2026/06/224 个月前

其他发布通道:alpha → 1.1.2-alpha.7,beta → 2.1.0-beta.1。

关于 @1money/protocol-ts-sdk 的常见问题

@1money/protocol-ts-sdk 是什么?

1Money协议网络的 sdk

如何安装 @1money/protocol-ts-sdk?

在项目目录运行 npm install @1money/protocol-ts-sdk,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:viem(>=2.0.0 <3.0.0)、axios(>=1.15.0 <2.0.0)、@ethereumjs/rlp(>=10.0.0 <11.0.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@1money/protocol-ts-sdk 支持 TypeScript 吗?

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

@1money/protocol-ts-sdk 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@1money/protocol-ts-sdk 可以商用吗?

@1money/protocol-ts-sdk 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@1money/protocol-ts-sdk 的下载量有多少?

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

@1money/protocol-ts-sdk 还在维护吗?

最新版本 3.1.1 发布于 2026/10/15(23 天前);至今共发布 27 个版本,其中过去 12 个月发布了 24 个;首次发布于 2025/08/18。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。