@ bnbagent/ sdk (英语)
用于在BNB链上构建链上AI代理的TypeScript工具包:ERC-8004身份,ERC-8183代理商务协议(escrow + valuation + 乐观的争议政策),x402微支付,钱包(本地密钥+可插接执行器),以及支持核心(付费主,非ce管理,tx调.
这是参考文献的分层端口 Python SDK 键盘 - 相同的协议语义,相同的链上部署,平庸的TypeScript API. 见 ARCHITECTURE.md ;此 README 覆盖 TypeScript 特定的表面和快速启动.
安装
pnpm add @bnbagent/sdk
# or
npm install @bnbagent/sdk
需要节点.js >= 20. 一揽子措施既包括无害环境管理,也包括无害环境管理import)和通用JS(英语:require) 构建加 TypeScript 类型.
软件包布局
公共API被分成一个小 第1级 桶(最需要的几个名称)和 第二级 子路径导出( 每个协议模块的全表面) :
// Tier 1 - the essentials
import { ERC8183Client, EVMWalletProvider, JobStatus } from "@bnbagent/sdk";
// Tier 2 - full module surface, imported by subpath
import {
ERC8183JobOps,
fundedJobWatcher,
CommerceClient,
} from "@bnbagent/sdk/erc8183";
import { ERC8004Agent, AgentURIGenerator } from "@bnbagent/sdk/erc8004";
import { X402Signer, SessionBudgetTracker } from "@bnbagent/sdk/x402";
import {
LocalStorageProvider,
IPFSStorageProvider,
} from "@bnbagent/sdk/storage";
import {
LocalExecutor,
UnsupportedWalletOperation,
} from "@bnbagent/sdk/wallets";
import { SigningPolicy, check } from "@bnbagent/sdk/signing";
import { getAddress, BNB_CHAIN_ADDRESSES } from "@bnbagent/sdk/networks";
import { SlidingWindowLimiter, RateLimitExceeded } from "@bnbagent/sdk/utils";
可用的子路径 : ./erc8004, (中文(简体) ), ./erc8183, (中文(简体) ), ./x402, (中文(简体) ), ./storage, (中文(简体) ), ./wallets, (中文(简体) ), ./signing, (中文(简体) ), ./networks, (中文(简体) ), ./utils。 。 。 .
TypeScript 签名检查器支持嵌入 EIP-712 结构
依赖性图有一个明确的根. 支持结构阵列;
模糊、断开和循环的多结构图被拒绝。 这样可以
明确选择使用许可2 PermitWitnessTransferFrom 请求
公共钱包 API. 一般初级类型/领域允许列表、否定列表和
有效性检查仍在运行:嵌入式签名不会给予新的支付许可.
每个方案,单个或多结构,在签署前都经过验证:
字段名称必须是固态标识符,字段类型必须是 EIP-712 原子
类型(无) uint编号 :int 或宣布为结构,可选作为数组,以及
计划限于256个地块,4096个田地,深度64和
256个特征识别符。 提出侵权问题 PolicyViolation 签字前.
明确允许许可领域和主要类型不是支付预算.
通用的 SDK 政策不标注 Percess2 证人计划、支出者、 符号
金额、收款人或 deadline 范围。 信任的付款整合必须
在调用钱包前验证这些值; 从不转发未信任的原始
仅在许可列表中添加许可后输入数据.
快速启动
两个片段都假设一个有资金的钱包打开 bsc-testnet (从 BNB 链水龙头和一个 .env 人均居住人数 环境变量 下表所列。 打电话 loadEnv() 一次在开始点加载 .env编号 :.env.local (SDK从不为你做这个——看它对于优先规则的指针).
(a) 客户方工作周期
客户创造了工作,约束了链上争议政策,资金代管,一旦供应商提交,就解决了工作(没有例外:它只是拉动了政策的判决并在链上应用).
import {
loadEnv,
EVMWalletProvider,
ERC8183Client,
JobStatus,
} from "@bnbagent/sdk";
loadEnv(); // opt-in .env / .env.local loading
const wallet = new EVMWalletProvider({
password: process.env.WALLET_PASSWORD!,
// First run only - the SDK encrypts it to ~/.bnbagent/wallets/<address>.json
// and subsequent runs only need the password.
privateKey: process.env.PRIVATE_KEY,
});
const client = await ERC8183Client.create({
walletProvider: wallet,
network: "bsc-testnet",
});
const decimals = await client.tokenDecimals();
const budget = 1n * 10n ** BigInt(decimals); // 1 token
// expiredAt must clear (disputeWindow + a safety buffer) or createJob()
// throws - a job whose deadline is too close can never be submitted.
const disputeWindow = await client.policy.disputeWindow();
const expiredAt = BigInt(Math.floor(Date.now() / 1000)) + disputeWindow + 600n; // +10 min slack
const { jobId } = await client.createJob({
provider: process.env.PROVIDER_ADDRESS!,
expiredAt,
description: "ERC-8183 demo: summarize this week's BSC ecosystem news",
});
console.log(`[client] createJob jobId=${jobId}`);
// Bind the OptimisticPolicy so settle() has a verdict source.
await client.registerJob(jobId!);
// Escrow the budget - auto-approves the payment token if the allowance is short.
// Zero price: for a free job either party calls `setBudget(jobId, 0n)`,
// then `fund(jobId, 0n)` moves no tokens and skips the ERC-20 approve
// entirely. See examples/client/zeroPrice.ts.
await client.fund(jobId!, budget);
console.log("[client] fund OK (Open -> Funded)");
// ... provider calls jobOps.submitResult() / client.submit() here (see below) ...
// After the dispute window elapses with no rejection, settle() finalizes
// the job as COMPLETED (or REJECTED if the policy recorded a reject vote).
await client.settle(jobId!);
const job = await client.getJob(jobId!);
console.log(`[client] settle -> ${JobStatus[job.status]}`);
(b) 提供商收入循环
为其地址供资的工作岗位进行无头供应商代理投票,并提交每个职位的交付品. ERC8183JobOps 处理核查(状况、任务、到期、预算水平)和可交付上传; fundedJobWatcher 是一个免签的投票圈 - 只有 探测器 由资助的工作,因此,召回决定怎么办(包括授权在其他地方签字).
import { EVMWalletProvider } from "@bnbagent/sdk";
import { ERC8183JobOps, fundedJobWatcher } from "@bnbagent/sdk/erc8183";
import { LocalStorageProvider } from "@bnbagent/sdk/storage";
const wallet = new EVMWalletProvider({
password: process.env.WALLET_PASSWORD!,
});
const jobOps = await ERC8183JobOps.create({
walletProvider: wallet,
network: "bsc-testnet",
storageProvider: new LocalStorageProvider(".agent-data"),
servicePrice: 1n * 10n ** 18n, // reject jobs budgeted below 1 token (18 decimals)
agentUrl: process.env.ERC8183_AGENT_URL, // public base URL, used as a deliverable-URL fallback
});
await fundedJobWatcher(
jobOps,
async (job) => {
const jobId = job.jobId as number;
console.log(`[earn-loop] job ${jobId} funded, budget=${job.budget}`);
const result = await jobOps.submitResult(
jobId,
`computed result for job ${jobId}`,
{ model: "my-model-v1" },
);
if (!result.success) {
console.error(`[earn-loop] submit(${jobId}) failed: ${result.error}`);
// Returning { retry: true } asks the watcher to re-validate and
// re-fire this job on the next tick (only for transient failures).
return { retry: result.retryable === true };
}
console.log(`[earn-loop] submitted ${jobId}, tx=${result.txHash}`);
},
{ interval: 30 }, // seconds between polls
);
钱包提供者
每个协议客户端通过 WalletProvider 接合 - 交换提供者, 保存协议代码 :
EVMWalletProvider | TWAKProvider | AltanaWalletProvider | TurnkeyWalletProvider | |
|---|---|---|---|---|
| 监护 | 本地密钥, 磁盘上的 Keystore V3 | twak 语录 密钥托( e)~/.twak+ OS 密钥链;密钥从未进入此进程 | EIP -7702 钱包 ======= 阿尔塔纳能力参考 覆盖中继和会话模式 | 键生成 + 持有 总钥匙AWS Nitro飞地, 永远不要离开; 代理只持有一个本地的 P-256 API 密钥, 每个请求都印出 |
| 能力 | sign.message/transaction/typed_data, (中文(简体) ), calls.arbitrary, (中文(简体) ), paymaster.sponsor | sign.message, (中文(简体) ), broadcast.self, (中文(简体) ), intents.erc8004, (中文(简体) ), intents.erc8183 (没有原始签名,没有) x402.pay 直至 requestExact 已存在) | broadcast.self, (中文(简体) ), calls.arbitrary, (中文(简体) ), intents.erc8004, (中文(简体) ), intents.erc8183 (+ 数) x402.pay 在会话模式下) | sign.message/transaction/typed_data, (中文(简体) ), calls.arbitrary, (中文(简体) ), paymaster.sponsor (与EVM相同,远程签名) |
| 代理封装 | SigningPolicy (进行中) | 固定命令菜单 + 程序外保管; twak 自己的 --max-payment 硬盖 | 链上会话密钥: 呼叫白名单 + 花盖 + 过期, 在一个 tx 可撤销 | SigningPolicy (正在处理,预开票)+ Twitchey的服务器侧政策引擎—— root API 密钥完全绕过服务器层; 生产需要非根端 API 用户 + 明确的 ALLOW 策略 |
| 天然气 | 自付或由大型燃料公司赞助 | 主网由twak自动赞助; SDK 转发其支付者为 --paymaster-url 所以赞助的测试网写作 | 中继前置气体,从钱包中回收(MegaFuel不涉及) | 自我付费或MegaFuel赞助(广播总是SDK自己的RPC;Twitchey管理的广播是供应商从未使用过的付费节目) |
| ERC-8183 引号签名 | EIP-191 通过 walletProvider | - 说吧 | ERC-1271通过 sessionQuoteSigner(); 代理中未设置行政主管ERA或通用信件签名权限 | EIP-191 通过 walletProvider (每引出1个帐单签名) |
| x402 付款额 | X402Signer | 授权 TwakX402Payer (单位:千美元)makeX402Payer(),五分引号预查) | 会话密钥付款人( E)makeX402Payer(), SDK QQ 0.4.0)在一次性管理员设置后: approveX402SignatureChecker + 边框 setPermit2Allowance· ; 收到 在钱包工作很好 | X402Signer ——工程,但0.10. (PAYG)以1 req/s的签名使得高频购买不经济;销售商/低频签名是甜点 |
| 额外安装 | - 说吧 | npm i @trustwallet/cli ( node_modules/.bin/twak 自动解析) | pnpm add @altananetwork/sdk (可选对等点,GPL-3.0-或-后,懒入) | pnpm add @turnkey/sdk-server @turnkey/viem (可选对等者,懒入) |
转钥匙快速启动( 远程飞地签名; 每一份成功签名都是开具账单的 —— 免费25级/ 每月1次请求/ 秒, 现收现付0. 10美元签名) :
import { TurnkeyWalletProvider } from "@bnbagent/sdk/wallets";
// env: TURNKEY_API_PUBLIC_KEY / TURNKEY_API_PRIVATE_KEY / TURNKEY_ORG_ID /
// TURNKEY_SIGN_WITH (the wallet account's 0x ADDRESS, not a wallet id)
const wallet = TurnkeyWalletProvider.fromEnv({ expectedChainId: 97 });
const jobs = await ERC8183Client.create({
walletProvider: wallet,
network: "bsc-testnet",
});
提供商是一个纯粹的签名人: ERC-8004/8183 写到骑行默认 LocalExecutor, x402 车次 X402Signer,而MegaFuel付费人之路则没有改变(与 gasPrice=0 (原始内容存档于2018-10-25). legistic signment. 所有SDK侧卫士 SigningPolicy,则 expectedChainId pin, 输入验证—— 运行 在此之前 aPI的电话,所以拒绝永远不会花费配额。 里面有一个卖家怪胎 signTypedData数字 : @turnkey/viem ^ 0.14.34 无声地将EIP-712域名序列化为: {} 当 types 对象缺少明确 EIP712Domain 条目,因此提供者总是注入(否则签名会约束一个空域). 实时验证 : TURNKEY_E2E=1 pnpm run e2e:turnkey (5个计费签名;见 examples/turnkey/e2e.ts) (中文(简体) ).
会话快速启动(一次行政补助,代理与会话一起运行):
import {
AltanaWalletProvider,
defaultAgentPermissions,
serializeSession,
} from "@bnbagent/sdk/wallets";
import { getAddress as getDeployment } from "@bnbagent/sdk/networks";
const { paymentToken, commerceProxy } = getDeployment(56);
// admin side - grant a scoped session (~$0.50-equiv BNB registration fee)
const admin = new AltanaWalletProvider({
privateKey: process.env.PRIVATE_KEY!,
});
const session = await admin.grantSession({
permissions: defaultAgentPermissions({
chainId: 56,
tokenSpend: { limit: 10n ** 18n },
}),
expiry: Math.floor(Date.now() / 1000) + 86_400,
});
// Session keys cannot approve tokens. Provision a bounded Commerce allowance
// from the admin side, no higher than the session token cap; zero on revoke.
await admin.setErc8183Allowance(paymentToken, commerceProxy, 10n ** 18n);
writeFileSync(".session.json", serializeSession(session), { mode: 0o600 }); // byte-exact - required
// agent side - ALTANA_SESSION_FILE=.session.json
const wallet = await AltanaWalletProvider.sessionFromEnv();
const jobs = await ERC8183Client.create({
walletProvider: wallet,
network: "bsc-mainnet",
});
同一会话可以通过狭义的 sessionQuoteSigner() 缝合。 代理商仍然没有行政主管,也没有获得通用 sign.message 能力。 见 Altana 引用签名示例 用于信任的检查器设置和接受区块核查.
谈判报价默认为最多900秒的SDK寿命(当钱包/会话提前到期时会被进一步缩短). 供应方 ERC8183JobOps 默认需要有效签名的引号,并在索引中验证 JobFunded 在工作或提交之前设置块。 购买者编辑、删除签名、延迟供资和供应商/链/商不匹配是永久性的 quote_invalid 拒绝. allowUnsignedJobs: true 是预签名工作的明显不安全兼容模式.
@altananetwork/sdk 0.5.0增加了供应商暴露的三个表面: network: "bnb-testnet" 预设(Altana的官方链-97堆), balances({ tokens }) (当地+ERC-20读取; raw 是链上价值转移的使用, display 是销售商SDK的人力格式化——销售商行为通过现在,以及 电子会议 - 说吧 grantSession({ register: false }) 跳过 ~ 0. 50 元 KeyStore 注册( 执行不变; 密钥对注册阅读者来说只是不可见的 ) verify_authorization和 registerSessionKey(session) 将 1 升级为后期注册, 仅限 .
见 阿尔塔纳能力参考 用于支持的地表和安全边界. examples/altana/ 包含收费表、x402会话支付器设置和测试网E2E.
赞助接力倒置
对于本地的EVM签名,担保交易散列必须在SDK信任它之前被链条所看到. 如果主要RPC从未看到散列,SDK会要求来自不同起源的回落RPC. 只有当至少有两个来源同意不进行中继交易时,才允许同一种非自付;两个来源同意它的存在抑制倒计时,并且每个较弱或相冲突的结果都未能与 RelaySubmissionUnverifiedError自定义 BNBAGENT_FALLBACK_RPC_URLS 继续支持,但共享来源的条目算作一个来源。 自定义端点构成运营商信任边界的一部分:选择独立运行的源头,因为运营商提供的法定人数可以授权倒置. BNBAGENT_USE_PAYMASTER=0 启动时要自给时禁用赞助 .
EVMWalletProvider 不保留其构造密码。 通过密码
明确改为 exportKeystore(password)电话 destroy() 本地时
签名完成 。 活的私钥必然仍在过程中
内存至此; 使用远程或范围化的钱包后端用于更高值
部署.
环境变量
这些都不是自动读取的 - 呼叫 loadEnv() (从) @bnbagent/sdk)在您的入场点加载 .env.local 接下来 .env,或者设置,但您的部署通常会注入环境变量。 见 .env.example 用于权威的、充分评论的引用.
| 变量 | 用于 | 页:1 |
|---|---|---|
NETWORK | resolveNetwork | 预设名称 : bsc-testnet (违约)或 bsc-mainnet。 。 。 . |
RPC_URL 编号 : RPC_URL_<NETWORK> | resolveNetwork | 覆盖预设的RPC端点;每个网络 var 胜出. |
WALLET_PASSWORD | EVMWalletProvider | 需要EVM后端 。 加密/解密本地 Keystore V3 文件; TWAK 未使用. |
PRIVATE_KEY | EVMWalletProvider | EVM后端, 仅先运行 - 导入后加密为磁盘; 删除后端 . |
WALLET_ADDRESS | EVMWalletProvider | 区分在有多个时要装入的键盘 . |
WALLET_KIND | ERC8183Config.fromEnv | evm (违约)或 twakTWAK拥有其监护权,不使用 PRIVATE_KEY编号 :WALLET_PASSWORD。 。 。 . |
ERC8183_COMMERCE_ADDRESS | getErc8183Config | 覆盖代理商内核地址(仅海关部署). |
ERC8183_ROUTER_ADDRESS | getErc8183Config | 覆盖评价员鲁特地址. |
ERC8183_POLICY_ADDRESS | getErc8183Config | 覆盖优化政策地址. |
ERC8183_SERVICE_PRICE | ERC8183Config 编号 : ERC8183JobOps | 最低工作预算(草签单位) 提供者接受. |
ERC8183_AGENT_URL | ERC8183JobOps | 代理的公用基址;倒置可交付-URL主机. |
ERC8183_FUNDED_POLL_INTERVAL | 代理服务器示例 | 受资助工作扫描的投票间隔( 秒) . |
ERC8183_MAX_RESPONSE_BYTES 编号 : ERC8183_MAX_METADATA_BYTES | ERC8183JobOps.submitResult | 可实现的上传大小盖. |
ERC8004_REGISTRY_ADDRESS | getErc8004Config | 覆盖身份登记地址. |
ALTANA_SESSION | AltanaWalletProvider.sessionFromEnv | 序列化的 Altana session JSON(包含会话密钥 - 处理为秘密). 胜过文件变体. |
ALTANA_SESSION_FILE | AltanaWalletProvider.sessionFromEnv | 持有序列会话的文件路径( mode 0600) . |
STORAGE_LOCAL_PATH | LocalStorageProvider.fromEnv | 本地存储的基础目录 . |
STORAGE_API_KEY | IPFSStorageProvider.fromEnv | 要求与Pinata兼容的JWT. |
STORAGE_API_URL 编号 : STORAGE_GATEWAY_URL | IPFSStorageProvider | 可选的自定义指针端点/网关 . |
BNBAGENT_MIN_GAS_PRICE_WEI | minGasPriceWei | 全球气价下限覆盖所有链条. |
BNBAGENT_RECEIPT_TIMEOUT | getDefaultReceiptTimeout | 默认收件等待, 秒. |
BNBAGENT_USE_PAYMASTER | resolveNetwork | 1 部队赞助, 0 自付,而未设置则继承网络预设. |
BNBAGENT_RELAY_UNSEEN_TIMEOUT | getRelayUnseenTimeout | 二. 在进行倒置处理之前,未见的赞助散列物可能仍然看不见; 0 禁用提前中止. |
BNBAGENT_FALLBACK_RPC_URLS | 中继验证器 | 逗号分隔的 RPC 端点用于确认继电器还原的散列是否未见; 覆盖内置的 BSC 端点列表 。 一个决定性的结果需要两种不同的URL起源. |
与 Python SDK 对等
此软件包镜像 python/bnbagent 模块- for-module - 相同的合同地址, 相同的协议 invariants, 相同的env var名. 协议级别的细节(ERC-8183状态机器、谈判握手、x402支付流量、签名政策威胁模型、钱包能力模型),见 ARCHITECTURE.md 和 Python 软件包 README.md 文件在 python/bnbagent/*/README.md - 那些文件是协议的参考文献,不是Python的特有文献, 并同样适用于这里.