0.6.10 • Published 1 year ago

@hyunggyujang/typechain-polkadot v0.6.10

Weekly downloads
-
License
-
Repository
github
Last release
1 year ago

Typechain-polkadot


Package for generating TypeScript definitions & runtime code for Polkadot smart contracts.


Usage

In your project install this package:

npm i -D @727-ventures/typechain-polkadot

Now you can use it to generate TS definitions & runtime code for Polkadot smart contracts. To use typechain-polkadot.

Note, that ink! contracts generate two files: metadata.json and <contract-name>.contract. You need to provide both of them to typechain-polkadot, and rename metadata.json to <contract-name>.json.

Typechain can be used in two ways:

  • As a CLI tool
  • As a library

CLI tool

After installing the package, you can use it as a CLI tool. To use it, run the following command:

npx @727-ventures/typechain-polkadot --input path/to/abis --output path/to/output

Methods and namespaces used in the typechain, and their description

build-extrinsic

In this namespace you can find all the functions that are related to building extrinsics.

const tx = contract.buildExtrinsic.<methodName>(...args, options);

tx.signAndSend(account, (result) => {
	// Handle result
});

constructors

Used to deploy contracts, using different constructors.

Let's deploy the following contract:

#![cfg_attr(not(feature = "std"), no_std)]
#![feature(min_specialization)]

#[openbrush::contract]
pub mod my_psp22 {

    // imports from openbrush
	use openbrush::contracts::psp22::*;
	use openbrush::traits::Storage;

    #[ink(storage)]
    #[derive(Default, Storage)]
    pub struct Contract {
    	#[storage_field]
		psp22: psp22::Data,
    }

    // Section contains default implementation without any modifications
	impl PSP22 for Contract {}

    impl Contract {
        #[ink(constructor)]
        pub fn new(initial_supply: Balance) -> Self {
            let mut _instance = Self::default();
			_instance._mint_to(_instance.env().caller(), initial_supply).expect("Should mint");
			_instance
        }
    }
}

This contract has a constructor new with one argument initial_supply. To deploy this contract, you need to use the following code:

// Import here Constructors and Contract classes

// Here we are creating an instance of the Constructors class, which is used to deploy contracts,
// Constructors is typechain-generated class that contains all the constructors of the contract
const factory = new Constructors(api, UserAlice);

// You can access to the different constructors using the name of the constructor, here we will use "new"
const {result, address} = await factory.new('10', {});

// Here we are creating an instance of the Contract class, which is used to interact with the deployed contract
contract = new Contract(address, UserAlice, api);

contract

Contract is the main namespace for interacting with contracts. It contains all the functions that are related to contracts.

const contract = new Contract(
		address,
		signer,
		nativeAPI,
)

contract.name() // get the name of the contract

contract.address() // get the address of the contract

contract.abi() // get the abi of the contract

contract.<namespace>.<functionName>(...args, options) // call a function from a namespace
// namespace can be tx, query, events, etc.

contract.withSigner(signer)
// change the signer of the contract in the current context,
// basically it will create a new contract with the new signer

contract.withAddress(address)
// change the address of the contract in the current context,
// basically it will create a new contract with the new address
// useful for proxy contracts

contract.withAPI(api)
// change the api of the contract in the current context
// basically it will create a new contract with the new api

data

Utility file. Contains all info about types. It's used in runtime to parse return values from contracts.

mixed-methods

This namespace contains both tx and query methods.

contract.mixedMethods.<functionName>(...args, options)

query

This namepsace contains all query methods

const result = contract.query.<functionName>(...args, options)

console.log(result.value)

You can also use it to get errors from contracts

try {
	await contract.withSigner(UserBob).query.transfer(UserAlice.address, '10', []);
} catch ({ _err }) {
	console.log(_err);
}
console.log
	{ insufficientBalance: null }

tx-sign-and-send

This namespace is used send transactions.

const result = await contract.tx.<functionName>(...args, options)

Library

You can also use typechain-polkadot as a library. To use it, you need to import it in your code:

import {Typechain} from '@727-ventures/typechain-polkadot/src/types/typechain';
import {testPathPatternToRegExp} from "jest-util";

const typechain = new Typechain();

typechain.loadDefaultPlugins();

typechain.run(
	pathToInput,
	pathToOutput
)

Plugins

Typechain-polkadot uses plugins to generate code. By default, it uses the following plugins:

You can also create your own plugins to add some custom logic to the typechain-polkadot. To do this, you need to create a class that implements the TypechainPlugin interface:

import {TypechainPlugin} from '@727-ventures/typechain-polkadot/src/types/interfaces';
import {Abi} from "@polkadot/api-contract";

/**
 * generates a contract file
 *
 * @param abi - The ABI of the contract
 * @param fileName - The name of the file to write to
 * @param absPathToOutput - The absolute path to the output directory
 * @param absPathToABIs - The absolute path to the ABIs directory
 */
function generate(abi: Abi, fileName: string, absPathToOutput: string, absPathToABIs: string) {
	console.log('Hello World!');
}

export default class HelloWorldPlugin implements TypechainPlugin {

	name: string = 'HelloWorld';
	outputDir: string = 'HelloWorld';

	generate(abi: Abi, fileName: string, absPathToABIs: string, absPathToOutput: string): void {
		generate(abi, fileName, absPathToOutput, absPathToABIs);
	}
}

Then you need to add your plugin to the list of plugins:

typechain.loadPlugins(new MyPlugin());

Or you can load them via cli:

npx @727-ventures/typechain-polkadot --input path/to/abis --output path/to/output --plugins ./plugins-directory

Note: if you're using the cli, every plugin should end with .plugin.ts and have default export of the plugin itself.

Also you can use loadPluginsFromFiles method to load plugins from files:

typechain.loadPluginsFromFiles(
	'./plugins-directory'
)

Example of plugins usage

You can find an example of plugins usage in the examples directory.