如何在Node.js中使用bitcoinjs-lib签名MagicEden生成的PSBT?
在Node.js中签名MagicEden生成的Ordinals PSBT
两种可行签名方案
方案一:模拟网页流程,通过Unisat浏览器扩展签名
MagicEden网页端依赖Unisat扩展完成签名,这套流程只能在浏览器环境实现,核心是调用扩展注入的全局API:
// 先检查Unisat扩展是否已安装 if (!window.unisat) { throw new Error("请安装Unisat钱包扩展"); } // 请求用户授权钱包账户 const authorizedAddress = await window.unisat.requestAccounts(); console.log("已授权地址:", authorizedAddress[0]); // 传入未签名PSBT的Base64字符串,调用扩展签名 const signedPsbtBase64 = await window.unisat.signPsbt(unsignedBase64); // 直接通过扩展广播签名后的PSBT const txid = await window.unisat.pushPsbt(signedPsbtBase64); console.log("交易广播完成,TxID:", txid);
注:此代码仅能在浏览器页面运行,纯Node.js环境无法直接调用Unisat扩展的API。
方案二:Node.js环境使用本地私钥签名
如果要在纯Node.js环境完成签名,需持有对应地址的私钥(务必做好私钥安全防护,禁止硬编码或泄露),步骤如下:
import { Psbt, ECPair, networks } from 'bitcoinjs-lib'; // 选择对应网络,测试网替换为networks.testnet const network = networks.bitcoin; // 加载未签名PSBT const psbt = Psbt.fromBase64(unsignedBase64, { network }); // 从WIF格式私钥生成密钥对 const privateKeyWif = "你的私钥WIF字符串"; const keyPair = ECPair.fromWIF(privateKeyWif, network); // 遍历输入,对匹配当前密钥地址的输入签名 psbt.data.inputs.forEach((input, index) => { const currentAddress = keyPair.getAddress(); if (input.witnessUtxo?.address === currentAddress || input.nonWitnessUtxo?.address === currentAddress) { psbt.signInput(index, keyPair); } }); // 验证签名有效性(可选但推荐) const isSignatureValid = psbt.validateSignaturesOfAllInputs(); if (!isSignatureValid) { throw new Error("签名验证失败"); } // 最终化PSBT并提取可广播的交易Hex psbt.finalizeAllInputs(); const signedTxHex = psbt.extractTransaction().toHex(); console.log("签名完成,交易Hex:", signedTxHex); // 后续可通过比特币节点或第三方API广播该Hex
注意:确保私钥对应的地址与PSBT中需要签名的输入地址完全匹配;Ordinals铭文存储在输出脚本中,bitcoinjs-lib处理标准PSBT时不会破坏其结构。
方案差异说明
- 浏览器扩展签名:依赖用户手动确认交易,私钥由用户自行保管,适合面向普通用户的应用场景
- 本地私钥签名:无需用户交互,但需要直接持有私钥,仅适合测试或个人可控脚本,必须严格保障私钥安全
内容的提问来源于stack exchange,提问作者Taha Daboussi
相关产品推荐
相关产品推荐

