scio-labs / use-inkathon

Typesafe React hooks and utility functions that simplify the process of working with Substrate-based networks and ink! smart contracts.
https://inkathon.xyz
GNU General Public License v3.0
50 stars 17 forks source link
blockchain hooks ink javascript polkadot polkadot-blockchain polkadot-js polkadot-js-api polkadot-network react react-hook react-hooks reactjs rust smart-contract smart-contracts substrate typescript web3

inkathon Devtooling Banner

useInkathon ā€“ React Hooks & Utility Library

License: GPL v3 Built with ink! TypeScript React

This library provides typesafe React hooks and utility functions that simplify the process of working with Substrate-based networks and ink! smart contracts. It abstracts away the complexities of polkadot{.js} but still lets you access the full power of the underlying API.

The project is part of a Scio Labs initiative to improve the developer experience in the ink! ecosystem and a proud member of the Aleph Zero EFP. šŸ’œ

Other projects include:

Join the discussion in our Telegram Group šŸ’¬

Checkout our TypeDoc Documentation šŸ“ƒ


  1. Getting started šŸš€
  2. Features āœØ
  3. Contract Registry šŸ—³ļø
    1. How it works
    2. Typed Contracts
  4. Examples šŸ“š
  5. Package Development šŸ› 

Getting started šŸš€

[!IMPORTANT]
If you are looking for a boilerplate to start your dApp project from scratch, checkout ink!athon.

  1. Go to your existing project and install the package from the npm registry:
pnpm add @scio-labs/use-inkathon
# or
npm install @scio-labs/use-inkathon
# or
yarn add @scio-labs/use-inkathon
  1. Wrap it around your app or parent component:
import { development, UseInkathonProvider } from '@scio-labs/use-inkathon'
<UseInkathonProvider appName="My dApp" defaultChain={development}>
  <Component {...pageProps} />
</UseInkathonProvider>
  1. Use the primary useInkathon hook for connecting the wallet or accessing the API:
import { useInkathon } from '@scio-labs/use-inkathon'
const { api, connect, activeChain, activeAccount, ā€¦ } = useInkathon()

Features āœØ

At its core, this library serves as a wrapper for polkadot{.js}, potentially saving you over 100 lines of code. This includes:

[!NOTE]
Checkout our TypeDoc Documentation for more details.

Contract Registry šŸ—³ļø

Often when working with smart contracts in the frontend, you have to import the contract metadata multiple times across a project, then determine the matching deployment address for the active chain, and create a ContractPromise instance manually each time.

The idea of a Contract Registry is to define contract metadata & addresses only once and use them everywhere with a simple hook:

const { contract } = useRegisteredContract('greeter')

How it works

Start by defining an async getDeployments function that returns SubstrateDeployment[] metadata objects for each contract deployment on each chain.

[!NOTE]
Checkout an advanced example within the ink!athon boilerplate here where metadata is imported dynamically based on defined chains and contract identifiers.

import { alephzeroTestnet, SubstrateDeployment } from '@scio-labs/use-inkathon'

export const getDeployments = async (): Promise<SubstrateDeployment[]> => {
  return [
    {
      contractId: 'greeter',
      networkId: alephzeroTestnet.network,
      abi: await import(`../deployments/metadata.json`),
      address: '5HPwzKmJ6wgs18BEcLdH5P3mULnfnowvRzBtFcgQcwTLVwFc',
    },
  ]
}

The function's result passed to the UseInkathonProvider provider:

<UseInkathonProvider
  appName="My dApp"
  defaultChain={alephzeroTestnet}
  deployments={getDeployments()}
>
  <Component {...pageProps} />
</UseInkathonProvider>

Then access the contract as above:

const { contract } = useRegisteredContract('greeter')

Typed Contracts

[!NOTE]
Make sure to also install @727-ventures/typechain-types, bn.js, and @types/bn.js as dependencies in your project. Find a complete setup & usage example in the ink!athon boilerplate.

If you are using typechain-polkadot to generate type-safe contracts, you can use the useRegisteredTypedContract hook instead:

import GreeterContract from '[ā€¦]/typed-contracts/contracts/greeter'

// ā€¦

const { typedContract } = useRegisteredTypedContract('greeter', GreeterContract)
const result = await typedContract.query.greet()

[!IMPORTANT]
Currently, only queries are supported until typechain-polkadot#138 is merged. Alternatively, we're considering switching to the prosopo/typechain-polkadot fork completely.

Examples šŸ“š

Within this repository:

Live examples:

Package Development šŸ› 

If you want to contribute, please read our Contributor Guidelines šŸ™

Pre-requisites:

# Install dependencies
pnpm i

# Enable pre-commit hooks
pnpm simple-git-hooks

# Run tsup in development mode (watching)
pnpm dev

# Run package compilation in parallel with vanilla React example
pnpm run dev:react-example

# Build the package
pnpm build
How to import a development version of this package locally? Unfortunately, importing this package locally into other local projects requires some manual steps. You need to build & pack this package into a `.tgz`-build and then update this dependency in your other project. These steps must be repeated each time you make changes to this package. ```bash # 1. [THIS PACKAGE] Generate a .tgz package of the build pnpm tsup && pnpm pack # 2. [OTHER PROJECT] Add it as a dependency in your other project like: # `"@scio-labs/use-inkathon": "file:../scio-labs-use-inkathon-0.0.X.tgz"` pnpm add ../use-inkathon/scio-labs-use-inkathon-0.0.X.tgz # 3. [OTHER PROJECT] Subsequent updates can be done via pnpm update @scio-labs/use-inkathon --force ```