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

Polkadot.js调用signAndSend传入signer参数触发编译错误

问题背景
  • 开发环境为Next.js框架,基于Polkadot.js实现前端交互逻辑
  • 实现目标:对接浏览器钱包扩展获取账户,调用signAndSend方法发起已部署合约的交易
  • 异常表现:代码编译阶段抛出TypeScript类型不匹配错误

业务代码片段

const injector = await web3FromSource(performingAccount.meta.source);
const keyring = new Keyring({ type: 'sr25519' });
//    const accountKeyring = keyring.addFromUri('//Alice');
const accountKeyring = keyring.addFromAddress(performingAccount.address);

const flip = await contract.tx.flip({ value: 0, gasLimit: -1 });
flip.signAndSend(accountKeyring,{signer:injector.signer},(result) => {
  if (result.status.isInBlock) {
    setResult("in a block");
  } else if (result.status.isFinalized) {
    setResult("finalized");
  }
});

编译报错信息

(property) signer?: Signer | undefined
Type 'import("/Users/shin.takahashi/develop/substrate/flipper_frontend/fillper_frontend/node_modules/@polkadot/rpc-core/node_modules/@polkadot/types/types/extrinsic").Signer' is not assignable to type 'import("/Users/shin.takahashi/develop/substrate/flipper_frontend/fillper_frontend/node_modules/@polkadot/api-contract/node_modules/@polkadot/types/types/extrinsic").Signer'.
  Types of property 'update' are incompatible.
    Type '((id: number, status: H256 | ISubmittableResult) => void) | undefined' is not assignable to type '((id: number, status: ISubmittableResult | H256) => void) | undefined'.
      Type '(id: number, status: H256 | ISubmittableResult) => void' is not assignable to type '(id: number, status: ISubmittableResult | H256) => void'.
        Types of parameters 'status' and 'status' are incompatible.
          Type 'ISubmittableResult | H256' is not assignable to type 'H256 | ISubmittableResult'.
            Type 'ISubmittableResult' is not assignable to type 'H256 | ISubmittableResult'.
              Type 'import("/Users/shin.takahashi/develop/substrate/flipper_frontend/fillper_frontend/node_modules/@polkadot/api-contract/node_modules/@polkadot/types/types/extrinsic").ISubmittableResult' is not assignable to type 'import("/Users/shin.takahashi/develop/substrate/flipper_frontend/fillper_frontend/node_modules/@polkadot/rpc-core/node_modules/@polkadot/types/types/extrinsic").ISubmittableResult'.
                Types of property 'dispatchError' are incompatible.
                  Type 'import("/Users/shin.takahashi/develop/substrate/flipper_frontend/fillper_frontend/node_modules/@polkadot/api-contract/node_modules/@polkadot/types/interfaces/system/types").DispatchError | undefined' is not assignable to type 'import("/Users/shin.takahashi/develop/substrate/flipper_frontend/fillper_frontend/node_modules/@polkadot/rpc-core/node_modules/@polkadot/types/interfaces/system/types").DispatchError | undefined'.
                    Property '#private' is missing in type 'import("/Users/shin.takahashi/develop/substrate/flipper_frontend/fillper_frontend/node_modules/@polkadot/api-contract/node_modules/@polkadot/types/interfaces/system/types").DispatchError' but required in type 'import("/Users/shin.takahashi/develop/substrate/flipper_frontend/fillper_frontend/node_modules/@polkadot/rpc-core/node_modules/@polkadot/types/interfaces/system/types").DispatchError'.ts(2322)
Enum.d.ts(27, 5): '#private' is declared here.
submittable.d.ts(17, 5): The expected type comes from property 'signer' which is declared here on type 'Partial<SignerOptions>'
错误产生原因
  1. 核心原因:Polkadot生态依赖版本不一致,存在多份类型副本
    从报错路径可以看出,项目中@polkadot/rpc-core和@polkadot/api-contract两个包各自在自身的node_modules目录下嵌套依赖了不同版本的@polkadot/types包。TypeScript会将不同文件路径下的同名类型判定为完全独立、不兼容的类型,哪怕两个类型的结构逻辑完全一致;报错中提到的#private私有属性缺失,就是不同版本的DispatchError类定义存在差异导致的典型表现。
  2. 代码写法存在逻辑问题
    对接浏览器钱包扩展签名的场景下,签名动作由钱包侧完成,不需要本地通过Keyring构造密钥对实例。通过keyring.addFromAddress生成的密钥对不包含私钥,本身也无法完成本地签名操作。
修复方案
  • 统一所有@polkadot/开头的依赖版本,确保@polkadot/api、@polkadot/api-contract、@polkadot/extension-dapp、@polkadot/keyring等相关包使用完全一致的版本号,禁止出现跨版本混用。
  • 删除项目下的node_modules目录和对应包管理器的锁文件(package-lock.json/yarn.lock/pnpm-lock.yaml),重新执行依赖安装命令,让包管理器将公共依赖提升到顶层目录,消除多版本@polkadot/types的重复副本。
  • 修正签名逻辑,移除冗余的Keyring构造代码,直接将钱包账户地址作为signAndSend的第一个参数传入即可,修正后的参考代码如下:
const injector = await web3FromSource(performingAccount.meta.source);
const flip = await contract.tx.flip({ value: 0, gasLimit: -1 });
flip.signAndSend(
  performingAccount.address,
  { signer: injector.signer },
  (result) => {
    if (result.status.isInBlock) {
      setResult("in a block");
    } else if (result.status.isFinalized) {
      setResult("finalized");
    }
  }
);

内容的提问来源于stack exchange,提问作者s.Takahashi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 10:27:40