Как вы, возможно, читали, мы решили использовать Typescript в качестве основного языка для наших проектов в Neufund. Это обеспечивает улучшенную безопасность типов и обеспечивает уверенность в разработке, которая иначе недоступна в Javascript.

Несмотря на то, что Typescript может гарантировать правильность вашего кода, он беспомощен, когда в игру вступают сторонние библиотеки. Для внешних зависимостей, написанных на Javascript, вам необходимо предоставить типизацию, то есть информацию о типах доступных функций и типов. Некоторые библиотеки (особенно написанные на TS) имеют встроенную типизацию. Для других вы можете найти типизацию на npm. Но ситуация становится еще более сложной, когда вы работаете с динамически генерируемыми типами, такими как оболочки смарт-контрактов.

Ад динамической печати

Обычно для взаимодействия со смарт-контрактом в блокчейне Ethereum вы используете Web3js: вы передаете ABI и адрес, вызываете методы и создаете транзакции для данного смарт-контракта. К сожалению, такие динамические интерфейсы, созданные во время выполнения, не могут быть выражены в системе типов Typescript.

Конечно, к тому же с такими обертками сложно работать, нет автозавершения кода, а API не интуитивно понятен.

«Как снова называлась эта функция? Это постоянная функция или мне нужно создать транзакцию? »

Лично я потерял много времени на отладку загадочных сообщений об ошибках, когда просто забыл указать количество газа.

Мы можем сделать лучше, чем это.

Введите TypeChain

TypeChain здесь, чтобы решить все эти проблемы. Он использует предоставленные файлы ABI для создания типизированных оболочек для смарт-контрактов. Он по-прежнему использует Web3js под капотом, но на первый взгляд предоставляет надежный, безопасный по типу API с поддержкой обещаний и многого другого.

Давайте посмотрим на практический пример. Вот наш смарт-контракт:

contract CounterContract {
  uint public counter;
  function DumbContract() public {
    counter = 0;
  }
  function counterWithOffset(uint offset) public constant returns (uint sum) {
    return counter + offset;
  }
  function countup(uint by) public {
    counter += by;
  }
}

Сгенерированная оболочка:

import { BigNumber } from "bignumber.js";
import {
  TypeChainContract,
  promisify,
  ITxParams,
  IPayableTxParams,
  DeferredTransactionWrapper,
} from "./typechain-runtime";
export class DumbContract extends TypechainContract {
  public readonly rawWeb3Contract: any;
  public constructor(web3: any, address: string | BigNumber) {
    const abi = [
      //ABI
    ];
    super(web3, address, abi);
  }
  static async createAndValidate(web3: any, address: string | BigNumber): Promise<DumbContract> {
    const contract = new DumbContract(web3, address);
    const code = await promisify(web3.eth.getCode, [address]);
    if (code === "0x0") {
      throw new Error(`Contract at ${address} doesn't exist!`);
    }
    return contract;
  }
  public get counter(): Promise<BigNumber> {
    return promisify(this.rawWeb3Contract.counter, []);
  }
  public counterWithOffset(offset: BigNumber | number): Promise<BigNumber> {
    return promisify(this.rawWeb3Contract.counterWithOffset, [offset.toString()]);
  }
  public countupTx(by: BigNumber | number): DeferredTransactionWrapper<ITxParams> {
    return new DeferredTransactionWrapper<ITxParams>(this, "countup", [by.toString()]);
  }
}

Вы можете использовать это так:

// create new instance of contract wrapper and assert that contract exists on blockchain (useful during development)
const dumbContract = await DumbContract.createAndValidate(web3, contractAddress);
// call getter
await dumbContract.counter;
// call constant method
await dumbContract.counterWithOffset(2);
// create transaction
await dumbContract.countupTx(2).send({
    from: accounts[0],
    gas: 10000,
});
// you can easily get tx data
await dumbContract.countupTx(2).getData();

Благодаря нашим сгенерированным оболочкам автозавершение кода просто работает, а компилятор Typescript, как и tslint, могут выполнять свою работу по обеспечению безопасности типов (кстати, ознакомьтесь с проектом TypeStrict для достижения максимальной безопасности типов).

Имейте в виду: мы настоятельно не рекомендуем передавать сгенерированные файлы в вашу систему контроля версий! Сделайте TypeChain частью вашего процесса сборки (например, используя обработчик после установки) и не редактируйте сгенерированные файлы напрямую. Когда вы это сделаете, если вы когда-нибудь измените ABI, компилятор Typescript найдет для вас критические изменения. Как это круто? :)

Настройка сгенерированных оболочек

Часто файлы ABI не содержат всей необходимой информации об интерфейсе контракта, и вам необходимо настроить сгенерированные файлы. Здесь действует то же правило: не редактируйте файлы напрямую. Вместо этого расширьте сгенерированный контракт своей - более конкретной - реализацией.

Мы также оцениваем различные, более декларативные способы настройки сгенерированных оболочек, таких как файлы API, которые добавляли бы семантику к файлам ABI. Например, вы можете указать, что данный uint представляет метку времени и должен анализироваться как дата момент.

Мы надеемся на мнение сообщества по мере нашего продвижения вперед. Вот где вы вступаете: помогите нам, предлагая улучшения и оставляя отзывы!

Резюме

TypeChain избавляет программистов от написания большого количества повторяющегося кода и в то же время обеспечивает безопасность типов. При создании нашего приложения с обязательством (которое, кстати, завершение менее чем за неделю) мы использовали ранние версии TypeChain. Он уже зарекомендовал себя как полезный, и теперь мы надеемся, что наши усилия принесут пользу другим командам.

Для получения дополнительной информации перейдите на нашу страницу Github - TypeChain.

Следите за мной в Твиттере, чтобы получать новости, советы и рекомендации относительно блокчейна, машинописного текста и Javascript.

МБР Neufund происходит прямо сейчас! Не упустите шанс стать частью нашей экосистемы. Зайдите на https://commit.neufund.org/.

Кшиштоф Качор - ведущий разработчик блокчейнов в Neufund, платформе по сбору средств, принадлежащей сообществу, соединяющей миры инвестиций в акционерный капитал и блокчейн.

Чтобы узнать больше, посетите страницу МБР Neufund или технический документ для более глубокого нырять. Вопросов? Спросите нас о чем угодно в Twitter и Telegram!