如何使用prepareContcmd输出发送区块链续期交易并解决pactCode报错?
解决Pact续期交易签名与发送问题
错误原因分析
你遇到的TypeError: pactCode must be a string: undefined错误,本质是请求格式不符合Pact API要求:
- 续期交易不需要手动添加
pactCode字段,prepareContCmd生成的cmd已经包含所有必要的交易编码信息 - 你的签名结构不完整,缺少
publicKey字段,导致API解析请求时触发异常提示
正确的续期交易流程与代码修正
核心步骤
- 生成续期命令框架:用
prepareContCmd构造包含续期逻辑的待签名命令 - 签名命令:对
cmd字段进行签名,确保签名结构包含publicKey和sig - 发送交易:将带签名的完整命令直接传递给
local(测试)或send(上链)端点
修正后的完整代码
const Pact = require('pact-lang-api'); const NETWORK_ID = "mainnet01"; const CHAIN_ID = "8"; const API_HOST = `https://api.chainweb.com/chainweb/0.0/${NETWORK_ID}/chain/${CHAIN_ID}/pact`; // 交易参数 const keyPairs = { publicKey: '4aab9f08f1bd86c3ce007a9a87225ef061c09e7062efa622e2fd704c24514cfa', secretKey: 'secret-key' }; const step = 1; const rollback = false; const envData = null; const seller = "k:79464b986676c7b39f2202b09fcbbaf324c677c43122c62de76edaf9f0ca10bd"; const buyer = "k:4aab9f08f1bd86c3ce007a9a87225ef061c09e7062efa622e2fd704c24514cfa"; const amount = 1.0; const price = 1000.0; const pactId = "FdFn_GVF4f5IEOcsx8gvmWbQghMbY65rpwcfSdStgag"; const saleId = "n7Erm5Gcij3ITgOF3vXUww8j6MZgIGRSSeU0uCYcmKg"; const sender = "k:4aab9f08f1bd86c3ce007a9a87225ef061c09e7062efa622e2fd704c24514cfa"; const chainId = "8"; const gasPrice = 0.0000001; const gasLimit = 10000; const creationTime = Math.floor(new Date().getTime() / 1000); const ttl = 28800; const meta = Pact.lang.mkMeta(sender, chainId, gasPrice, gasLimit, creationTime, ttl); // 获取SPV证明(仅跨链续期需要,同链可省略或传null) async function getProof() { const cmd1 = { requestKey: pactId, targetChainId: CHAIN_ID, }; return Pact.fetch.spv(cmd1, API_HOST); } async function main() { // 若为同链续期,可直接将proof设为null const proof = await getProof(); // 构造续期命令 const contCommand = Pact.api.prepareContCmd( { publicKey: keyPairs.publicKey, clist: [ { name: "marmalade.ledger.BUY", args: [ "t:KNl_38B4fqeJd2ijPghc_ihD-5viRvqLcV10MZEIwsA", buyer, seller, amount, { int: 99999999 }, saleId, ], }, { name: "coin.TRANSFER", args: [buyer, seller, price], }, { name: "coin.GAS", args: [] } ] }, new Date().toISOString(), proof, // 传入SPV证明,同链传null pactId, rollback, step, envData, meta, NETWORK_ID ); // 签名命令:确保签名包含publicKey和sig const signedCmd = Pact.crypto.sign(contCommand.cmd, keyPairs); contCommand.sigs = [ { publicKey: keyPairs.publicKey, sig: signedCmd.sig } ]; // 发送到local端点测试,如需上链改用Pact.fetch.send try { const response = await Pact.fetch.local(contCommand, API_HOST); console.log("交易响应:", response); } catch (error) { console.error("发送交易失败:", error); } } main();
关键修正点
- 完整签名结构:签名后的
sigs数组必须包含publicKey和sig两个字段,这是Pact API的强制要求 - SPV证明传递:如果是跨链续期,必须将获取到的SPV证明传入
prepareContCmd的第3个参数;同链续期可传null - 移除多余的pactCode字段:续期交易不需要手动添加
pactCode,prepareContCmd生成的cmd已经是完整的编码交易内容
切换到send端点上链
若要将交易发送到主链,只需将Pact.fetch.local替换为Pact.fetch.send,两者接受的参数格式完全一致:
const response = await Pact.fetch.send(contCommand, API_HOST);
内容的提问来源于stack exchange,提问作者Nexion21
相关产品推荐
相关产品推荐

