How to interact with EVM Smart Contracts in Javascript
Tags: smartcontract, pancakeswap, bnbsmartchain, web3
Published: 2023-05-22 16:56:06

This tutorial is an introduction to the fundamentals of interacting with EVM compatible Smart Contracts in Javascript. We will demonstrates how to read from or write to [Pancakeswap Prediction](https://pancakeswap.finance/prediction) Smart Contract using web3.js. Pancakeswap Prediction Smart contract allows you to place bets on BNBUSD or CAKEUSD price moves.

## Step 1: connect to web3

Pancakeswap runs on BNB Smart Chain. To interact with it we will use [web3.js](https://web3js.readthedocs.io/en/v1.10.0/) package which contains a collection of libraries that allows interaction with a blockchain node using HTTP, RPC or WebSocket providers. We will use HTTP provider `https://bsc-dataseed1.binance.org:443`

```javascript
const Web3 = require("web3");
const provider = "https://bsc-dataseed1.binance.org:443";
const web3 = new Web3(provider);
```
## Step 2: connect to Smart Contract

To connect to Smart Contract we would need its address and ABI. Address of the contract could be found in Pancakeswap [docs ](https://docs.pancakeswap.finance/developers/smart-contracts/prediction-v2). Once we know the address, we can retrieve its ABI from [BscScan](https://bscscan.com/) by using its API. To make a network call we will use `axios` library

```javascript
const { default: axios } = require("axios");

const contractAddress = "0x18B2A687610328590Bc8F2e5fEdDe3b582A49cdA";
 
const execute = async() => {
    const response = await axios.get(`https://api.bscscan.com/api?module=contract&action=getabi&address=${contractAddress}&apikey=YOUR_API_KEY`)
    const contract = new web3.eth.Contract(JSON.parse(response.data.result), contractAddress);
}

execute()

```
## Step 3: interact with Smart Contract

In EVM world Smart Contract functions could be of 2 types: read and write. Read functions allow to read Smart Contract data and they do not change Smart Contract state. Write functions instead do alter the state and we would require to pay for it to be executed (calling address should have enough blockchain native currency balance)

```javascript
const epoch = await contract.methods.currentEpoch().call(); // read function
const roundData = await contract.methods.rounds(epoch).call(); // read function
const gasPrice = await web3.eth.getGasPrice(); // blockchain utility function
const betBullFunctionABI = contract.methods.betBull(epoch).encodeABI(); // prepare write function
const betBearFunctionABI = contract.methods.betBear(epoch).encodeABI(); // prepare write function
const custodialAddress = "your_address";
const custodialAddressKey = "your_address_key";
const account = web3.eth.accounts.privateKeyToAccount(custodialAddressKey); // used to sign transaction
const nonce = await web3.eth.getTransactionCount(custodialAddress); // get your account nonce
const transaction = {
     nonce,
     from: custodialAddress,
     to: contractAddress,
     gasPrice,
     gas: 5000000,
     data: betBullFunctionABI,
     value: "12008140256521106"
} // compose transaction object
   
const signedTransaction = await account.signTransaction(transaction); // sign transaction
const sentTransaction = await web3.eth.sendSignedTransaction(signedTransaction.rawTransaction); // send transaction to blockchain
console.log(sentTransaction)
const isClaimable = await contract.methods.claimable(epoch, custodialAddress).call(); // read function
if(isClaimable){ // recompose transaction to claim wins
      const claimFunctionABI = contract.methods.claim([epoch]).encodeABI(); // prepare write function
      const nonce = await web3.eth.getTransactionCount(custodialAddress); // get your account nonce
      const claimTransaction = {
            nonce,
            from: custodialAddress,
            to: bnbPredictionContractAddress,
            gasPrice,
            gas: 5000000,
            data: claimFunctionABI,
       }; // compose transaction object
      const signedClaimTransaction = await account.signTransaction(claimTransaction); // sign transaction
      const sentClaimTransaction = await web3.eth.sendSignedTransaction(signedClaimTransaction.rawTransaction); // send transaction to blockchain
      console.log(sentClaimTransaction)
}

```

Our final code should look like this

```javascript
const { default: axios } = require("axios");
const Web3 = require("web3");

const provider = "https://bsc-dataseed1.binance.org:443";

const web3 = new Web3(provider);

const contractAddress = "0x18B2A687610328590Bc8F2e5fEdDe3b582A49cdA";
 
const execute = async() => {
    const response = await axios.get(`https://api.bscscan.com/api?module=contract&action=getabi&address=${contractAddress}&apikey=YOUR_API_KEY`)
    const contract = new web3.eth.Contract(JSON.parse(response.data.result), contractAddress);
    const epoch = await contract.methods.currentEpoch().call(); // read function
    const roundData = await contract.methods.rounds(epoch).call(); // read function
    const gasPrice = await web3.eth.getGasPrice(); // blockchain utility function
    const betBullFunctionABI = contract.methods.betBull(epoch).encodeABI(); // prepare write function
    const betBearFunctionABI = contract.methods.betBear(epoch).encodeABI(); // prepare write function
    const custodialAddress = "your_address";
    const custodialAddressKey = "your_address_key";
    const account = web3.eth.accounts.privateKeyToAccount(custodialAddressKey); // used to sign transaction
    const nonce = await web3.eth.getTransactionCount(custodialAddress); // get your account nonce
    const transaction = {
        nonce,
        from: custodialAddress,
        to: contractAddress,
        gasPrice,
        gas: 5000000,
        data: betBullFunctionABI,
        value: "12008140256521106"
    } // compose transaction object
   
    const signedTransaction = await account.signTransaction(transaction); // sign transaction
    const sentTransaction = await web3.eth.sendSignedTransaction(signedTransaction.rawTransaction); // send transaction to blockchain
    console.log(sentTransaction)
    const isClaimable = await contract.methods.claimable(epoch, custodialAddress).call(); // read function
    if(isClaimable){ // recompose transaction to claim wins
        const claimFunctionABI = contract.methods.claim([epoch]).encodeABI(); // prepare write function
        const nonce = await web3.eth.getTransactionCount(custodialAddress); // get your account nonce
        const claimTransaction = {
            nonce,
            from: custodialAddress,
            to: bnbPredictionContractAddress,
            gasPrice,
            gas: 5000000,
            data: claimFunctionABI,
          }; // compose transaction object
        const signedClaimTransaction = await account.signTransaction(claimTransaction); // sign transaction
        const sentClaimTransaction = await web3.eth.sendSignedTransaction(signedClaimTransaction.rawTransaction); // send transaction to blockchain
        console.log(sentClaimTransaction)
    }
}

execute()

```
Link to gist [here](https://gist.github.com/BellaBe/55861311d3d6a9346bb6b0c87fface8a)

P.S Keep in mind that executing the above script might lead to money loss and you would require a good prediction strategy that will help to minimize it.