You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript根据含函数名参数的字典动态构造函数并挂载调用

实现方案

不需要拼接函数字符串再用eval/new Function()做动态生成,这种方式存在注入风险且作用域处理容易出问题,直接用JavaScript动态属性挂载+闭包转发的方式实现即可,天然支持async/await,完全适配ethers的合约调用逻辑。

单函数挂载基础逻辑

针对你提到的{function_name, arguments}结构的配置,直接给目标实例挂载对应名称的异步方法即可:

/**
 * 给目标实例动态挂载方法
 * @param {Object} config 函数配置,包含function_name和arguments字段
 * @param {Object} target 要挂载方法的实例对象
 * @param {Function} executor 方法实际执行的底层逻辑
 */
function attachMethod(config, target, executor) {
  const { function_name, arguments: argDefine } = config
  target[function_name] = async function(...args) {
    // 可按需加参数校验
    if (args.length !== argDefine.length) {
      throw new Error(`方法 ${function_name} 预期入参数量为${argDefine.length},实际传入${args.length}`)
    }
    return executor.call(this, function_name, ...args)
  }
}

挂载的方法默认是async类型,既支持await调用,也支持.then()链式调用,完全匹配ContractFunction的类型定义。

ethers合约场景批量挂载实现

你已经完成ABI解析的前提下,只需要过滤ABI中type=function的条目,提取函数名、入参定义后批量挂载即可,完整可运行示例:

const { ethers } = require("ethers");

// 示例Greeter合约ABI
const abi = [
  {
    "inputs": [{"internalType": "string","name": "_greeting","type": "string"}],
    "stateMutability": "nonpayable",
    "type": "constructor"
  },
  {
    "inputs": [],
    "name": "greet",
    "outputs": [{"internalType": "string","name": "","type": "string"}],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [{"internalType": "string","name": "_greeting","type": "string"}],
    "name": "setGreeting",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  }
];

// 初始化合约实例,替换为实际的合约地址、signer/provider
const contract = new ethers.Contract("0x_合约地址", abi, signer);

// 批量挂载所有合约方法
function bindAllContractMethods(contractInstance) {
  // 这里替换为你自己的ABI解析逻辑,输出格式为{function_name: 方法名, arguments: 入参名列表}的数组
  const parsedMethods = abi
    .filter(item => item.type === "function")
    .map(item => ({
      function_name: item.name,
      arguments: item.inputs.map(i => i.name)
    }));

  parsedMethods.forEach(config => {
    attachMethod(
      config,
      contractInstance,
      // 调用转发到ethers原生的contract.functions下的对应方法
      (method, ...callArgs) => contractInstance.functions[method](...callArgs)
    );
  });
}

// 执行挂载
bindAllContractMethods(contract);

// 调用测试
async function demo() {
  // 等价于contract.functions.greet()
  const greeting = await contract.greet();
  console.log("当前greeting值:", greeting);

  // 等价于contract.functions.setGreeting("新问候内容")
  const tx = await contract.setGreeting("新问候内容");
  await tx.wait(); // 等待交易确认
  console.log("setGreeting交易已上链");
}

demo();

扩展说明

  • 挂载逻辑不侵入ethers原生合约实例,只是做了一层调用转发,不会和原生API冲突
  • 可直接在闭包内扩展参数类型校验、调用日志、错误捕获等自定义逻辑,不需要修改底层调用代码
  • 所有挂载的方法返回值都是Promise,完全符合ethers合约方法的调用约定

内容的提问来源于stack exchange,提问作者JAGADEESH

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 05:09:20