@ 1 钱/ protocol- ts- sdk
1货币网络协议的TS-SDK
快开始
安装
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 | 怎么办 |
|---|---|---|
TransactionSubmissionError | false | 节点在录取前拒绝了请求. 纠正原因( :err.action, (中文(简体) ), err.status, (中文(简体) ), err.errorCode然后再次发送. |
TransactionLockedError | true | 节点持有这个确切的交易. 重新发送相同的 authorized 直到其收据出现. |
TransactionOutcomeUnknownError | 'unknown' | SDK不能说 抬头看 err.transactionHash 并重发 authorized 直到你知道这个州. |
TransactionHashMismatchError | true | 节点承认交易,但返回了不同的散列. 别再寄了. |
在锁定之后,在任何非交易中,不得为同一目的签署新交易
未知结果: 支付可以执行两次 。 重订 不变 签名
交易总是安全的:它有相同的散列,所以最多一个副本执行.
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比较整个字符串. |
action | fix_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);
}
}
对于可连锁包装器,总是执行两个处理器进行适当的错误管理:
.success():处理成功的API响应.timeout(): 具体处理超时出错.error(): 处理所有其他类型的错误.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 和节点相同执行 :
| 外地 | 马克斯 | 允许字符 |
|---|---|---|
type | 128 字节 | 仅限URL安全(RFC 3986 无保留 + gen-delims + sub-delims +) %(中文(简体) ) |
format | 64 字节 | 只有 URL 安全, 同一集 |
data | 256 字节 | 除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(...)(和 每个其它操作)返回 aPreparedTxV2而不是旧的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或者说1v2 表面; 遗留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。 。 。 .
许可证
麻省理工学院