React应用中调用Functions.makeHTTPrequest及fetch API,传入executeRequest合约
React中调用Chainlink Functions并传入组件字符串到智能合约的实现方案
1. 将React组件转为字符串并调用Functions.makeHTTPRequest
步骤拆解
- 组件转字符串:使用ReactDOMServer的
renderToStaticMarkup(生成纯静态HTML)或renderToString(带React内部标识),把组件转为字符串格式 - 构造Chainlink HTTP请求:按照Chainlink Functions规范,用
Functions.makeHTTPRequest封装请求参数,将组件字符串作为请求体或参数传入 - 调用合约
executeRequest:通过ethers.js/wagmi连接合约,将编码后的请求数据和组件字符串传入合约函数
代码示例
import ReactDOMServer from 'react-dom/server'; import { Functions } from '@chainlink/functions-toolkit'; import { ethers } from 'ethers'; import FunctionConsumerABI from './FunctionConsumerABI.json'; // 目标React组件 const MyComponent = () => ( <div> <h1>Chainlink Functions Demo</h1> <p>生成时间: {new Date().toLocaleString()}</p> </div> ); const executeChainlinkRequest = async () => { // 1. 组件转HTML字符串 const componentString = ReactDOMServer.renderToStaticMarkup(<MyComponent />); // 2. 构造Chainlink HTTP请求 const httpRequest = Functions.makeHTTPRequest({ url: 'https://your-api-endpoint.com', method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ component: componentString }) }); // 3. 编码Chainlink请求数据 const requestData = Functions.encodeRequestData( [httpRequest], [], // 无需加密密钥则传空数组 100000 // 回调函数gas限制 ); // 4. 调用智能合约executeRequest const provider = new ethers.BrowserProvider(window.ethereum); const signer = await provider.getSigner(); const contract = new ethers.Contract('0xYourContractAddress', FunctionConsumerABI, signer); const tx = await contract.executeRequest(requestData, componentString); await tx.wait(); console.log('交易已上链:', tx.hash); };
2. React中发起POST请求并传入字符串到executeRequest
如果不需要通过Chainlink Functions转发HTTP请求,直接在React中发起POST请求后将结果/组件字符串传入合约:
代码示例
import ReactDOMServer from 'react-dom/server'; import { ethers } from 'ethers'; import FunctionConsumerABI from './FunctionConsumerABI.json'; const MyComponent = () => ( <div className="custom-component"> <h2>自定义业务组件</h2> <p>待传入合约的内容</p> </div> ); const postAndCallContract = async () => { // 组件转字符串 const componentString = ReactDOMServer.renderToStaticMarkup(<MyComponent />); // 发起POST请求 const postRes = await fetch('https://your-api.com/submit', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ componentHtml: componentString }) }); const apiResult = await postRes.json(); // 调用合约executeRequest const provider = new ethers.BrowserProvider(window.ethereum); const signer = await provider.getSigner(); const contract = new ethers.Contract('0xYourContractAddress', FunctionConsumerABI, signer); // 假设合约executeRequest接收两个字符串参数:API返回结果、组件字符串 const tx = await contract.executeRequest(JSON.stringify(apiResult), componentString); await tx.wait(); };
3. 基于fetch API实现完整流程(调用API+传入组件字符串到合约)
结合fetch调用第三方API,将组件字符串传给API处理后,再将结果和组件字符串一并传入合约:
代码示例
import React from 'react'; import ReactDOMServer from 'react-dom/server'; import { ethers } from 'ethers'; import FunctionConsumerABI from './FunctionConsumerABI.json'; // 业务组件 const BusinessComponent = () => ( <div> <h3>用户业务内容</h3> <p>ID: {Math.random().toString(36).slice(2, 10)}</p> </div> ); const fullFlowExecute = async () => { try { // 1. 组件转字符串 const componentStr = ReactDOMServer.renderToStaticMarkup(<BusinessComponent />); // 2. fetch调用API,传入组件字符串 const fetchRes = await fetch('https://your-service-api.com/process', { method: 'POST', headers: { 'Content-Type': 'application/json', // 如有需要添加API鉴权头 // 'Authorization': 'Bearer YOUR_API_TOKEN' }, body: JSON.stringify({ sourceHtml: componentStr, timestamp: Date.now() }) }); if (!fetchRes.ok) throw new Error(`API请求失败: ${fetchRes.status}`); const processedData = await fetchRes.json(); // 3. 调用合约executeRequest const provider = new ethers.BrowserProvider(window.ethereum); const signer = await provider.getSigner(); const contract = new ethers.Contract('0xYourContractAddress', FunctionConsumerABI, signer); const tx = await contract.executeRequest( JSON.stringify(processedData), componentStr, { gasLimit: 300000 } // 根据实际需求设置gas限额 ); await tx.wait(); console.log('交易确认,哈希:', tx.hash); } catch (err) { console.error('流程执行出错:', err); } }; // 页面触发按钮 export default function App() { return ( <div style={{ padding: '20px' }}> <button onClick={fullFlowExecute} style={{ padding: '10px 20px' }}> 执行完整流程 </button> </div> ); }
关键注意事项
- 字符串大小限制:Solidity中字符串存储有gas成本,过长的HTML字符串可能导致交易失败,建议用
html-minifier等工具压缩后再传入 - 合约参数匹配:确保
FunctionConsumer.sol的executeRequest函数参数类型与传入值一致,例如Solidity中用string类型接收字符串参数 - Chainlink配置:若使用Chainlink Functions,需提前配置好Functions订阅,确保请求参数符合Chainlink的规范要求
内容的提问来源于stack exchange,提问作者Kenil shah
相关产品推荐
相关产品推荐

