我在项目中面临 Chainlink 的挑战,特别是从 Chainlink 消费者合约调用 API 时交易失败和日志擦除。
问题:使用Chainlink调用API时交易会还原,擦除所有日志并妨碍调试。
具体问题: GET API 调用成功,但 POST 方法(支付 API)返回错误请求。
错误消息:“InternalServerErrorException:执行已恢复(未知的自定义错误)(action =“estimateGas”)”。
文档差距: 关于通过 Chainlink 函数发出 POST 请求的指导不充分。
寻求解决这些问题的建议,特别是执行 POST API 调用和保留日志以进行调试。
下面的代码片段是我发起交易的地方
**../requestSource.js**
const apiResponse = await Functions.makeHttpRequest({
url: 'http://localhost:4000/payment/transfer',
method: 'POST',
data: {
jobProposalId: args[0],
amount: args[1],
milestoneOrder: args[2],
},
});
console.log(JSON.stringify(apiResponse));
if (apiResponse.error) {
throw Error(apiResponse.error);
}
const { data } = apiResponse;
return Functions.encodeString(data);
const source = readFileSync(
path.join(__dirname, '../requestSource.js'),
).toString();
const args = ['65ad521cfa8f23xxxxxxx', '375', '1'];
const response = await simulateScript({
source: source,
args: args,
bytesArgs: [], // bytesArgs - arguments can be encoded off-chain to bytes.
secrets: {}, // no secrets in this example
});
使用 POST 请求模拟此操作会引发 BadRequest。
即使模拟响应成功与否,合约方法调用也会失败并出现错误 -
"InternalServerErrorException: execution reverted (unknown custom error) (action="estimateGas")"
const tx = await contract.markMilestoneCompleted(
updateContractDto.contractAddress,
updateContractDto.milestoneId,
subscriptionId,
donId,
source,
args,
gasLimit,
);
await tx.wait();
预期行为是标记里程碑已完成,更新合同并启动付款,不应返回任何错误。
从错误消息来看,问题出在与已部署合约的交互上。它似乎与estimateGas中的CALL_EXCEPTION有关,但很难确认,因为Chainlink没有返回完整的错误消息。
如果是estimateGas中的CALL_EXCEPTION,请参阅this以获取解决方案。
Chainlink 社区预言机在这里。
正如 Frank 提到的,使用 Chainlink Functions 的要求之一是你的后端 API 必须是幂等的;换句话说,您需要接受多次调用目标 API,并且每次都需要返回相同的结果。
在这种情况下,使用 Chainlink 函数的另一种方法是使用 Chainlink 的 Any API(即直接请求)请求模式,您的请求将仅通过单个 Chainlink 预言机,从而确保您的 API 调用仅发生一次。虽然使用单个 Chainlink 预言机有明显的缺点(即,您需要相信预言机公司不会操纵您的数据),但有许多信誉良好的预言机在分布于多个数据中心和区域的高度冗余基础设施上运行其预言机。这将消除您自己运行任何额外基础设施来监控区块链状态/发布您的请求的需要。
如果您有兴趣寻找信誉良好的 Chainlink 预言机来满足此类请求,您可以 A) 加入 Chainlink 官方 Discord 服务器并将您的要求发布到 #operator-requests,或者 B) 使用已知的网站用于自助服务方法的 Chainlink 预言机(我们在 LinkWell Nodes 提供文档和代码示例,用于从您的智能合约发起单个 HTTP POST 请求,包括相关的预言机地址和作业 ID)。
希望对您有所帮助,如果您有任何疑问,请告诉我!