为链创建 txwrapper

⚠️ Update Notice:

Please read Substrate to Polkadot SDK page first.


创建 txwrapper 包将扩展链用户的离线签名选项。 这对于需要使用隔离设备(例如)促进交易签名、构建和/或解码的安全意识用户非常重要。 这包括(但不限于)托管人、交易所和冷存储用户。

在为自己的链构建 txwrapper 之前,请查看 txwrapper-examples

确保您理解 Polkadot 示例,并查看最终用户应使用的 txwrapper-core 方法(请参阅 decodeconstruct.{signingPayload, signedTx, txHash})。 您的包将重新导出这些方法,因此请务必了解您将创建的公共 API。

目标

构建链的 txwrapper 包的公共 API。

用例

方便现有 txwrapper 用户轻松集成新的 txwrapper。

步骤

1. 使用 txwrapper-template 创建一个仓库

txwrapper-template 目录复制到您的工作仓库中。

该模板提供了几乎可以发布到 NPM 的 typescript 包的基础知识。导出显示了一些与使用至少 balancesproxyutility pallets 的基于 FRAME 的链相关的有用方法。

请注意,txwrapper-core\ 在顶层重新导出,以便用户可以访问其工具。

2. 更新 package.json

修改以下字段以反映您的链信息:

  • name
  • author
  • description
  • repository
  • bugs
  • homepage
  • private(标记为 false)

此外,添加以下字段以授予发布权限:

  "publishConfig": {
    "access": "public"
  },

3. 选择要重新导出的相关方法

您需要选择您希望 txwrapper 公开的 pallet 方法。 建议选择可能由离线存储的密钥签名的那些方法。

如果您只需要 Substrate 或 ORML pallet 的方法,请查看 txwrapper-substratetxwrapper-orml 以查看这些方法是否已定义。

4. 创建 getRegistry 方法

您的 txwrapper 需要导出 getRegistry 方法,以便用户可以使用最新的链类型获取 Polkadot-js TypeRegistry

通过一些小的修改,下面的 foo 示例可以应用于与 Polkadot-js 类型兼容的任何基于 FRAME 的链:

// src/index.ts

import { typesBundleForPolkadot } from '@foo-network/type-definitions';
import { OverrideBundleType } from '@polkadot/types/types';
import {
  getRegistryBase,
  GetRegistryOptsCore,
  getSpecTypes,
  TypeRegistry,
} from '@substrate/txwrapper-core';

// 为了方便用户,我们可以为他们提供硬编码的链属性,
// 因为这些属性很少改变。
/**
 * txwrapper-foo 支持的网络的 `ChainProperties`。这些通常由 `system_properties` 调用返回,
 * 但由于它们变化不大,因此硬编码它们是相当安全的。
 */
const KNOWN_CHAIN_PROPERTIES = {
  foo: {
    ss58Format: 3,
    tokenDecimals: 18,
    tokenSymbol: 'FOO',
  },
  bar: {
    ss58Format: 42,
    tokenDecimals: 18,
    tokenSymbol: 'FOO',
  },
};

// 我们覆盖 `GetRegistryOptsCore` 的 `specName` 属性以获得更窄的类型特异性,
// 有望为用户创造更好的体验。
/**
 * `getRegistry` 函数的选项。
 */
export interface GetRegistryOpts extends GetRegistryOptsCore {
  specName: keyof typeof KNOWN_CHAIN_PROPERTIES;
}

/**
 * 获取 txwrapper-foo 支持的网络的类型注册表。
 *
 * @param GetRegistryOptions 当前运行时的 specName、chainName、specVersion 和 metadataRpc
 */
export function getRegistry({
  specName,
  chainName,
  specVersion,
  metadataRpc,
  properties,
}: GetRegistryOpts): TypeRegistry {
  const registry = new TypeRegistry();
  registry.setKnownTypes({
    // 如果您的类型不是以 `OverrideBundleType` 格式打包的,则可以
    // 使用 `RegisteredTypes` 支持的任何格式指定类型:
    // https://github.com/polkadot-js/api/blob/4ff9b51af2c49294c676cc80abc6476565c70b11/packages/types/src/types/registry.ts#L59
    typesBundle: (typesBundleForPolkadot as unknown) as OverrideBundleType,
  });

  return getRegistryBase({
    chainProperties: properties || KNOWN_CHAIN_PROPERTIES[specName],
    specTypes: getSpecTypes(registry, chainName, specName, specVersion),
    metadataRpc,
  });
}

并添加相关的导出:

// src/methods/currencies/index.ts

// 导出方法,有效地在 `currencies` 命名空间下可用
export * from "./transfer";
// src/methods

// 导出 `methods` 中的所有内容,包括 `currencies` 命名空间,使其能够
// 通过 `methods.currencies.transfer` 访问该方法
export * as methods from "./methods";

5. 创建一个可工作的示例

一个好的示例可以减轻用户的摩擦并减少维护人员的工作量。 创建一个端到端示例,以便用户清楚地了解为您的链生成离线交易的完整流程。

  1. template-example.ts 重命名为适合您链的名称,并更新文件中标记为 TODO 的所有部分。
  2. 更新示例/README.md 中标记为 TODO 的部分。
  3. 确保您可以使用链的开发节点运行该示例。

6. 发布您的包

一旦您确保版本控制有意义并且包在本地工作后,请参考本指南了解如何将您的包发布到 NPM

示例

资源