JavaScript SDK
仓库中有两个客户端库:
| 库 | 位置 | 适用场景 |
|---|---|---|
dApp SDK(NeuroChain) | neurochain-web/src/sdk/neurochain.js | 你的页面持有用户的密钥(或你在针对自己的钱包编写脚本) |
Signer SDK(NeuroSigner) | packages/neurochain-signer-sdk | 你的 dApp 运行在其他站点上,用户在弹出窗口中用自己的 NeuroChain 钱包签名 |
两者都尚未发布到 npm;请从仓库复制模块或构建该包。
dApp SDK
一个没有依赖的 ES 模块。读取使用普通的 fetch(浏览器或 Node 18+);写入使用与钱包相同的加密 WASM 以 ML-DSA-65 签名,因此节点会接受这些签名。
import { NeuroChain, OP_TARGETS, toRaw } from './neurochain.js'
const nc = new NeuroChain({ gateway: 'http://localhost:3000' })| 选项 | 默认值 | 含义 |
|---|---|---|
gateway | http://localhost:3000 | gateway 基础 URL |
crypto | — | 已初始化的加密 WASM 模块 |
cryptoLoader | 加载 ../wasm/neuro_wasm_crypto.js | 返回已初始化模块的异步函数 |
金额
你传入的每个 value 和 amount 都是人类可读的 NRO('1.5'、2、'0.000021')。SDK 用 toRaw() 把它换算为整数 uNRO,因此你签名的金额与发送的金额始终一致。显示时请使用 API 返回的 *_human 字段。
读取
| 方法 | 调用 | 返回 |
|---|---|---|
networkStatus() | GET /api/v1/network/status | 高度、分片、验证者 |
shards() | GET /api/v1/shards | 各分片高度 |
account(addr) | GET /api/v1/accounts/:addr | balance、balance_human、nonce、… |
balance(addr) | 通过 account | { raw, human, nonce } |
nextNonce(addr) | 通过 account | 已确认 nonce + 1 |
validators() | GET /api/v1/validators | 带质押和指标的验证者列表 |
blocks({ limit, offset }) | GET /api/v1/blocks | 最新区块 |
block(height) | GET /api/v1/blocks/:height | 单个区块 |
tx(hash) | GET /api/v1/transactions/:hash | 单笔交易 |
contract(addr) / contracts({ limit, offset }) | GET /api/v1/contracts… | 合约元数据 |
gasEstimate() | GET /api/v1/gas/estimate | base_fee 和估算值 |
contractQuery(addr, fn, args) | POST /api/v1/contracts/:addr/call,带 dry_run: true | 解析后的返回值;无交易,不消耗 gas |
钱包
const wallet = await nc.walletFromMnemonic('<24 个单词>')
wallet.address // neuro:<15 hex>.human
wallet.publicKey // ML-DSA-65 公钥,hex私有 seed 保存在钱包对象内部,绝不会作为属性暴露。
写入
// 转账
await nc.transfer({ wallet, to: 'neuro:<地址>.human', value: '1.5', gasPrice })
// 任意交易,可选携带调用数据
await nc.sendTransaction({ wallet, to, value, data, gasPrice })
// 合约调用——JSON 调用数据 { function, args }
await nc.contractCall({ wallet, address: 'neuro:<10 hex>.app', fn: 'transfer', args: { … }, value, gasPrice })
// 部署——发往 neuro:system.deploy 的交易
await nc.deployContract({ wallet, bytecodeHex, name, description, template, initArgs, gasPrice })每次写入都会读取下一个 nonce,对 nc-tx-v2|from|to|value|nonce 签名,并发送到 POST /api/v1/transactions。
设置 gas 价格
SDK 默认 gasPrice: 1(部署:5)。节点会拒绝价格低于当前基础费用的交易,而基础费用会随负载上升。请先读取它,再显式传入 gasPrice:
const { base_fee } = await nc.gasEstimate()
const gasPrice = Math.ceil(base_fee * 1.5)签名操作
质押、名称注册和其他系统操作针对系统目标签名,nonce 为毫秒级时间戳(参见钱包 → 签名操作):
const op = nc.signOp(wallet, OP_TARGETS.name, 0) // { signature, public_key, nonce }
// 把 op 合并进端点的请求体OP_TARGETS 包含 stake(neuro:system.stake)和 name(neuro:system.name)。
已知问题
当前 SDK 的已知问题
- 非零金额的转账会失败。
sendTransaction/transfer把value作为 JSON 字符串发送;节点只读取数字,并以Missing from/to/value拒绝请求。金额为 0 的调用和部署不受影响。变通办法——用数字值签名并发送:jsconst nonce = await nc.nextNonce(wallet.address) const value = Number(toRaw('1.5')) // uNRO,数字类型 const sig = wallet.sign(to, value, nonce) await fetch(GATEWAY + '/api/v1/transactions', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ from: wallet.address, to, value, nonce, gas_price, ...sig }) }) - 当合约的回复不是干净的 JSON 时,
contractQuery返回原始字符串——NRC-20 的回复以 NUL 字节结尾,因此你会得到字符串'{"ok":true,"value":…}';去掉\u0000后再解析。 stake()把金额换算为 uNRO 两次后才签名,因此节点会拒绝该签名。在修复之前,请自行构造请求:{ address, amount: toRaw(amount), ...nc.signOp(wallet, OP_TARGETS.stake, amount) },发送到/api/v1/staking/stake。staking(addr)请求的是/api/v1/staking/:addr,gateway 并不提供该路径;请使用GET /api/v1/staking/info/:address。contractCall会在调用 JSON 中添加caller字段。合约会忽略它——身份来自宿主——因此无害。
加密模块
签名需要 neuro_wasm_crypto——钱包的 WASM 构建(neurochain-web/src/wasm/neuro_wasm_crypto.js 和 neuro_wasm_crypto_bg.wasm)。它必须导出 nc_keypair_from_words、nc_tx_message 和 nc_sign。如果你的页面从其他位置提供它,请传入加载器:
const nc = new NeuroChain({
gateway: 'http://localhost:3000',
cryptoLoader: async () => {
const mod = await import('/wasm/neuro_wasm_crypto.js')
await mod.default()
return mod
},
})没有该模块时,读取照常可用,而每次写入都会抛出异常。
Signer SDK
适用于位于其他源(交易所、游戏)、且不得看到用户助记词的 dApp。用户的 NeuroChain Web 应用在弹出窗口中打开,用户批准后,签名通过 postMessage 返回。
import { NeuroSigner } from 'neurochain-signer-sdk'
const signer = new NeuroSigner({
signerUrl: 'http://localhost:8080/signer', // 钱包应用的 /signer 页面
allowedOrigins: ['http://localhost:8080'],
})
// 必须直接在点击处理函数中运行,否则浏览器会拦截弹出窗口
button.onclick = async () => {
const { address, publicKey } = await signer.connect()
const { signature, nonce } = await signer.signOperation({
to: 'neuro:system.dex',
value: 1000000, // uNRO
})
}| 方法 | 返回 |
|---|---|
connect() | { address, publicKey } |
signOperation({ to, value, actor? }) | { signature, publicKey, nonce }——针对 actor(默认:已连接的地址)的签名操作 |
isConnected()、getAddress()、getPublicKey() | 连接状态 |
close() | 关闭弹出窗口并断开连接 |
错误带有 code:POPUP_BLOCKED、CONNECTION_TIMEOUT、SIGNATURE_REJECTED、INVALID_ORIGIN、NOT_CONNECTED。遇到 POPUP_BLOCKED 时,向用户显示签名页面的直接链接。
只接受来自 allowedOrigins 的消息;请把它设置为你的钱包应用的源。