5
3

More than 3 years have passed since last update.

TypeChainを使ってタイプセーフなdappsフロントエンド👼

Last updated at Posted at 2019-12-20

まずはこちらをご覧ください(web3-jsのtsライブラリより)

web3.js/packages/web3-eth-contract/types/index.d.ts
export class Contract {
  // 中略

  methods: any;

  // 中略
}

ばかな、、、anyだと。。。

ということで今回は型付けが超絶貧弱な web3-jsethereum-ts/TypeChain というライブラリを使って型を付けていきます。

Blockchain Advent Calendar 記事どうしようどうしようと迷い続けて最終的に超ニッチな所に行き着きましたwすいません。

使っているもの

  • web3: 1.x系
  • typechain-target-web3-v1: 1.0.4
  • typechain: 1.0.3

TypeChainとは?

ethereum-ts というグループ(開発者一人)が作っているSolidityから生成したコントラクトに型を付けてくれるライブラリのようです。

現在495スターで開発者一人でこれは素晴らしい。

使ってみる

truflleやethers.jsなどにも対応しているようですが、今回はフロントではweb3-jsを使っている想定で進めます。
また、コントラクトはtruffleを使って開発している想定です

インストール

$ cd /path/to/truffle-dapps-root
$ npm install --save-dev typechain
$ npm install --save-dev typechain-target-web3-v1

コントラクトの型定義ファイルをビルド

$ cd /path/to/truffle-dapps-root
$ npx npx typechain --target web3-v1  './build/**/*.json'
$ cd ./types/web3-v1-contracts
=> コントラクトの型定義ファイルができている

フロントエンドアプリで使用

次は上で作った型定義ファイルをフロントエンドアプリに持っていき読み込ませましょう。
キャストが必要ですが、これで web3-js の Contract タイプに対して自作のコントラクトの型をつけることができます。

例として使用するコントラクト

MyContract.sol
contract MyContract {
  uint256 value;

  function setValue(uint256 _value) external {
    value = _value;
  }

  function getValue() external view returns (uint256) {
    return value;
  }
}

ビルドされた型定義ファイル

MyContract.d.ts
export class MyContract extends Contract {
  constructor(
    jsonInterface: any[],
    address?: string,
    options?: ContractOptions
  );
  clone(): MyContract;
  methods: {
    setValue(_value: number | string): TransactionObject<void>;

    getValue(): TransactionObject<string>;
  };
  events: {
    allEvents: (
      options?: EventOptions,
      cb?: Callback<EventLog>
    ) => EventEmitter;
  };
}

フロントエンドアプリ

import { MyContract } from './path/to/MyContract'; // 生成した型定義ファイル

const createMyContract: MyContract = () => {
  // apiについては
  return new web3.eth.Contract(abi, address) as MyContract;
);

// methodsに対して型が付与されている!!!
createMyContract().methods.setValue(10).send({
  from: window.web3.eth.defaultAccount,
});

createMyContract().methods.setValue(10).send({
  from: window.web3.eth.defaultAccount,
});

createMyContract().methods.setValue().call();

タイプセーフなdappsライフを

型というものは素晴らしいものですね。
npmにパッケージとしてリリースして常に最新のビルドしたものを見ているようにしたり、シンボリックリンクでファイルを共有したり、すこし運用に工夫は必要ですが、これでdappsフロントエンドアプリのバグが減りそうです。

では良いお年を〜

5
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
3