Hyperledger Fabric链码通过API对接前端报错修复及API开发问询
错误原因总述
你遇到的两类报错核心都是没有遵循Hyperledger Fabric链码的标准调用逻辑,直接在后端API服务中导入链码源码本地执行导致的:
- 链码是运行在Peer节点的Docker容器中的,本地API服务没有权限也没有办法直接生成链码执行所需的
ctx(交易上下文)对象,也不能直接调用链码内的方法。
报错1:Cannot read property 'putState' of undefined 修复方案
这个错误的触发原因分两种场景对应修复:
- 如果你是在链码开发调试阶段触发的错误:检查你写的链码函数是不是没有把
ctx作为第一个入参,或者调用链码函数的时候漏传了ctx参数,注意链码的所有事务函数第一个参数必须是上下文对象。 - 如果你是在API服务中调用链码时触发的错误:停止直接调用链码源码的逻辑,改用Fabric Node.js SDK通过网关调用链码。
报错2:CreateAsset is not a function 修复方案
这个错误的触发原因对应两种修复逻辑:
- 如果你是在链码开发阶段触发的错误:检查链码源码最后是不是用
module.exports = AssetTransfer导出的链码类,有没有正确实例化,注意示例链码的CreateAsset是类的实例方法,不是静态方法,不能直接用类名调用。 - 如果你是在API服务调用阶段触发的错误:同样属于直接本地调用链码导致的问题,改为用SDK调用链码的
CreateAsset事务函数即可解决。
可行的API开发方案
采用后端API + Fabric Node.js SDK 网关调用的标准架构,步骤如下:
- 先启动你的Fabric测试网络,部署好asset-basic-transfer链码,记录通道名、链码名。
- 在你的后端API项目中安装
fabric-network、fabric-ca-client依赖。 - 从测试网络中拷贝连接配置文件(通常是
connection-org1.json)、用户身份证书(admin或者注册的普通用户的wallet文件)到API项目中。 - 封装链码调用工具函数,示例代码如下:
const { Gateway, Wallets } = require('fabric-network'); const path = require('path'); const fs = require('fs'); async function invokeChaincode(funcName, args) { // 加载连接配置 const ccpPath = path.resolve(__dirname, 'config', 'connection-org1.json'); const ccp = JSON.parse(fs.readFileSync(ccpPath, 'utf8')); // 加载钱包 const walletPath = path.join(process.cwd(), 'wallet'); const wallet = await Wallets.newFileSystemWallet(walletPath); // 连接网关 const gateway = new Gateway(); await gateway.connect(ccp, { wallet, identity: 'admin', discovery: { enabled: true, asLocalhost: true } }); // 获取通道和链码对象 const network = await gateway.getNetwork('mychannel'); const contract = network.getContract('basic'); // 调用链码函数:查询用evaluateTransaction,写入操作用submitTransaction let result; if (funcName === 'ReadAsset' || funcName === 'GetAllAssets') { result = await contract.evaluateTransaction(funcName, ...args); } else { result = await contract.submitTransaction(funcName, ...args); } await gateway.disconnect(); return result.toString(); }
- 在你的API接口中调用上面的工具函数即可,比如创建资产的express接口示例:
app.post('/api/assets', async (req, res) => { try { const { id, color, size, owner, appraisedValue } = req.body; const result = await invokeChaincode('CreateAsset', [id, color, size, owner, appraisedValue]); res.status(200).json({ success: true, data: result }); } catch (err) { res.status(500).json({ success: false, error: err.message }); } });
内容的提问来源于stack exchange,提问作者harshav129
相关产品推荐
相关产品推荐

