DEV Community

Cover image for Automate Smart Contract ABI load with Typescript
Bella Be
Bella Be

Posted on • Updated on

Automate Smart Contract ABI load with Typescript

To interact with a Smart Contract running on Ethereum family blockchains you would need contract ABI (Application Binary Interface). You can copy/paste it from the Smart Contract source code documentation or you can automate the process by using blockchain explorer service and its API. Here is a quick guide on how to do it using Typescript. As Smart Contract example we will use Pancakeswap Prediction Smart Contract.

STEP 1. Find Smart Contract documentation

Do browser search for Pancakeswap Prediction Smart Contract. The link we are interested in is https://docs.pancakeswap.finance/products/prediction

STEP 2. Identify Smart Contract address and blockchain where it is deployed

Prediction Smart Contract address is 0x18B2A687610328590Bc8F2e5fEdDe3b582A49cdA and it is running on BNB Smart Chain.

STEP 3. Identify explorer service for blockchain in use

BNB Smart Chain uses BscScan.

STEP 4. Open an account within blockchain explorer

To access BscScan API you would need to signup for an account.

STEP 5. Search for blockchain explorer Get Contract ABI API documentation

The page we are looking for is https://docs.bscscan.com/api-endpoints/contracts and our endpoint looks as follows:

https://api.bscscan.com/api
   ?module=contract
   &action=getabi
   &address=0x18B2A687610328590Bc8F2e5fEdDe3b582A49cdA
   &apikey=YourApiKeyToken
Enter fullscreen mode Exit fullscreen mode

STEP 6. Integrate Get Contract ABI endpoint into your code

Create project folder and init

mkdir common && cd common && npm init -y 
Enter fullscreen mode Exit fullscreen mode

Install typescript and axios as dependencies, init typescript

npm install -D typescript && npm install axios && tsc --init
Enter fullscreen mode Exit fullscreen mode

Create project structure, we want it to be a npm module that we can publish into npm registry and import it into our main module, it will look as follows

- node_modules
- src
  - smart-contract-utils
    - types
      - abi.ts
    - abi.ts
  - index.ts
- package.json
- package-lock.json

Enter fullscreen mode Exit fullscreen mode

To build the above structure type the following commands from the root of your project

mkdir src 
&& cd src && touch index.ts 
&& mkdir smart-contract-utils 
&& touch smart-contract-utils/abi.ts 
&& mkdir smart-contract-utils/types
&& touch smart-contract-utils/types/abi.ts
&& cd ..

Enter fullscreen mode Exit fullscreen mode

Now it is time to write our function, it will look as follows

import axios from "axios";

export const getContractABI = async (): Promise<string> => {
  const data = await axios.get(
    "https://api.bscscan.com/api
       ?module=contract
       &action=getabi
       &address=0x18B2A687610328590Bc8F2e5fEdDe3b582A49cdA
       &apikey=YourApiKeyToken"
  )
  return data.data.result;
}

Enter fullscreen mode Exit fullscreen mode

Place it into src/smart-contract-utils/abi.ts file. Right now our function is tightly coupled to Prediction Smart Contract. Let's move contract address into function arguments and make it reusable for any Smart Contract deployed on BNB Smart Chain

import axios from "axios";

export const getContractABI = async (contract_address: string): Promise<string> => {
  const data = await axios.get(
    `https://api.bscscan.com/api
       ?module=contract
       &action=getabi
       &address=${contract_address}
       &apikey=YourApiKeyToken`
  );
  return data.data.result;
}

Enter fullscreen mode Exit fullscreen mode

Great. Can we do more? BscScan explorer is serving BNB Smart Chain which is a hard fork of the Go Ethereum protocol and as such, it shares many similarities with the Ethereum blockchain. Can we extend our function to retrieve ABI from Etherscan as well? Yes, we can. Etherscan has similar to BscScan API and it looks as follows

https://api.etherscan.io/api
   ?module=contract
   &action=getabi
   &address=0xBB9bc244D798123fDe783fCc1C72d3Bb8C189413
   &apikey=YourApiKeyToken
Enter fullscreen mode Exit fullscreen mode

As you can see the only difference between Etherscan and BscScan is the base url. Excellent. Here is an improved version of our function

import axios from "axios";

export const getContractABI = async (
 explorer_base_url: string, explorer_api_key: string, contract_address: string
): Promise<string> => {
 const data = await axios.get(
   `${explorer_base_url}
    ?module=contract
    &action=getabi
    &address=${contract_address}
    &apikey=${explorer_api_key}`
   )
 return data.data.result;
}
Enter fullscreen mode Exit fullscreen mode

We can reuse our function to retrieve ABI for any Smart Contract deployed on Ethereum or BNB Smart Chain and as additional touch, I would like to wrap function arguments into an object and give it an interface as a type guard. Place the following code into smart-contract-utils/types/abi.ts file

export interface GetContractABIParams {
  explorer_base_url: string;
  explorer_api_key: string;
  contract_address: string;
}
Enter fullscreen mode Exit fullscreen mode

Import GetContractABIParams interface into smart-contract-utils/abi.ts file and use it

import axios from "axios";
import { GetContractABIParams } from "./types/abi"

export const getContractABI = async (
  params: GetContractABIParams
): Promise<string> => {
  const { explorer_base_url, explorer_api_key, contract_address } = params;
  const data = await axios.get(
   `${explorer_base_url}
    ?module=contract
    &action=getabi
    &address=${contract_address}
    &apikey=${explorer_api_key}`
   )
  return data.data.result;
}
Enter fullscreen mode Exit fullscreen mode

Our reusable function is ready, let's export it together with GetContractABIParams interface through index.ts file, our project entry point

export * from "./smart-contract-utils/abi"
export * from "./smart-contract-utils/types/abi"
Enter fullscreen mode Exit fullscreen mode

That's it. In the next tutorial we will build our package and publish it to npm registry.

P.S. Other blockchains and explorers that could be used with this function are:
Polygon | PolygonScan
Optimism | OptimisticEtherScan

Top comments (0)