2

I have a base smart contract in rust with package manager cargo. In that smart contract I have some events which I'm emitting while function calling. For listing that events I have a service in java script but I'm not sure how to decode that event that trigger by contract while there is a transaction happened in a blockchain using that smartcontract. I have a link from where I can decode that https://github.com/polkadot-js/api/blob/f701c398c349159d5afd7344ea38c1d52e4aab56/packages/api-contract/src/Abi/index.ts#L111 but I have implement that but not able to decode the events. I'm pasting my contract and service here let me know if you got something or suggest something.

Contract

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

use ink_lang as ink;

#[ink::contract]
mod test {

    /// Defines the storage of your contract.
    /// Add new fields to the below struct in order
    /// to add new static storage fields to your contract.
    #[ink(storage)]
    pub struct Test {
        /// Stores a single `bool` value on the storage.
        value: bool,
    }

    /// Event emitted when a token transfer occurs.
    #[ink(event)]
    pub struct Transfer {
        #[ink(topic)]
        from: Option<AccountId>,
        #[ink(topic)]
        to: Option<AccountId>,
        value: Balance,
    }

    impl Test {
        /// Constructor that initializes the `bool` value to the given `init_value`.
        #[ink(constructor)]
        pub fn new(init_value: bool) -> Self {
            Self { value: init_value }
        }

        /// Constructor that initializes the `bool` value to `false`.
        ///
        /// Constructors can delegate to other constructors.
        #[ink(constructor)]
        pub fn default() -> Self {
            Self::new(Default::default())
        }

        /// A message that can be called on instantiated contracts.
        /// This one flips the value of the stored `bool` from `true`
        /// to `false` and vice versa.
        #[ink(message)]
        pub fn flip(&mut self) {
            self.value = !self.value;
            Self::env().emit_event(Transfer {
                from: None,
                to: None,
                value: 10000,
            });
        }

        /// Simply returns the current value of our `bool`.
        #[ink(message)]
        pub fn get(&self) {
            Self::env().emit_event(Transfer {
                from: None,
                to: None,
                value: 10000,
            });
        }
    }

    /// Unit tests in Rust are normally defined within such a `#[cfg(test)]`
    /// module and test functions are marked with a `#[test]` attribute.
    /// The below code is technically just normal Rust code.
    #[cfg(test)]
    mod tests {
        /// Imports all the definitions from the outer scope so we can use them here.
        use super::*;

        /// Imports `ink_lang` so we can use `#[ink::test]`.
        use ink_lang as ink;

        /// We test if the default constructor does its job.
        #[ink::test]
        fn default_works() {
            let test = Test::default();
            assert_eq!(test.get(), false);
        }

        /// We test a simple use case of our contract.
        #[ink::test]
        fn it_works() {
            let mut test = Test::new(false);
            assert_eq!(test.get(), false);
            test.flip();
            assert_eq!(test.get(), true);
        }
    }
}

Service.js

const { ApiPromise, WsProvider } = require('@polkadot/api')
const { ContractPromise, Abi } = require('@polkadot/api-contract')
const {
  assert,
  assertReturn,
  compactAddLength,
  compactStripLength,
  isNumber,
  isObject,
  isString,
  logger,
  stringCamelCase,
  stringify,
  u8aConcat,
  u8aToHex,
} = require('@polkadot/util')

// Import the test keyring (already has dev keys for Alice, Bob, Charlie, Eve & Ferdie)
const { Keyring } = require('@polkadot/keyring')

const bridgePerr = require('./flipper/examples/test/target/ink/metadata.json')

const Contract_Address_Peer = '5FfwrjcXmWsCZCtzRJPwtPBS3AEnPKJy9c2yEi17mFa5hhS3'

// Acc :- 30 may 11:33
const Peer_Private_key =
  '0xb0969cc635d807e6d6bfcb05cad88758c64df2da338050ce2103815653d05606'

const PeerProvider = new WsProvider('ws://127.0.0.1:9944')

// const self = '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY'
const to = '5Gue2tLHMZrfaeX6gDNs8EAPm64mpAnHsWWw5TWhGsb3Fkxo'
const AMOUNT = 1000000000000

async function main() {
  const api = await ApiPromise.create({ PeerProvider })

  //ed25519 edwards
  const keyring = new Keyring({ type: 'ed25519' })

  const PeerBridge = new ContractPromise(api, bridgePerr, Contract_Address_Peer)
  // the address we are going to query

  // Find the actual keypair in the keyring
  // const alicePair = keyring.getPair(target)
  const userPair = keyring.addFromUri(Peer_Private_key)

  console.log('Sending', AMOUNT, 'from', userPair.address, 'to', to)

  PeerBridge.tx
    .get({
      value: 0,
      gasLimit: -1,
    })
    .signAndSend(userPair, ({ events = [], status }) => {
      console.log('Transaction status:', status.type)

      if (status.isInBlock) {
        console.log('Included at block hash', status.asInBlock.toHex())
        console.log('Events:')

        events.forEach(({ event: { data, method, section }, phase }) => {
          console.log(
            '\t',
            phase.toString(),
            `: ${section}.${method}`,
            data.toString(),
          )
        })
      } else if (status.isFinalized) {
        console.log('Finalized block hash', status.asFinalized.toHex())

        process.exit(0)
      }
    })
}

main()

logs

    Transaction status: Ready
    Transaction status: InBlock
    Included at block hash 0x20da51303e5e1518e90844be6823f85e51666cc27ee652960d25b65902a97e59
    Events:
             {"applyExtrinsic":1} : balances.Withdraw ["5Cht6EkuACEXLrF8XBywqZPDCL9AEgSQXS4MB6dwgZAeqCVc",2828033563974]
             {"applyExtrinsic":1} : contracts.ContractEmitted ["5DskQxeMsqqueJzauUsbh8xYiiDKR4x7e5Kz29pkCJ1EKmwZ","0x00000010270000000000000000000000000000"]
             {"applyExtrinsic":1} : balances.Deposit ["5Cht6EkuACEXLrF8XBywqZPDCL9AEgSQXS4MB6dwgZAeqCVc",1268853627292]
             {"applyExtrinsic":1} : balances.Deposit ["5EYCAe5ijiYfyeZ2JJCGq56LmPyNRAKzpG4QkoQkkQNB5e6Z",1247343949345]
             {"applyExtrinsic":1} : treasury.Deposit [1247343949345]
             {"applyExtrinsic":1} : balances.Deposit ["5GNJqTPyNqANBkUVMN1LPPrxXnFouWXoe2wNSmmEoLctxiZY",311835987337]
             {"applyExtrinsic":1} : system.ExtrinsicSuccess [{"weight":9072880260,"class":"Normal","paysFee":"Yes"}]
    Transaction status: Finalized
    Finalized 

block hash 0x20da51303e5e1518e90844be6823f85e51666cc27ee652960d25b65902a97e59

Anyone please suggest something or help me in this.

1 Answer 1

5

You want to decode the data from ContractEmitted. So you are half-way there in known that you can pass the Bytes to the decodeEvent on the API.

In mostly pseudo-code, you would need to adjust your event check loop -

events.forEach(({ event, phase }) => {
  if (api.events.contracts.ContractEmitted.is(event)) {
    // we are dealing with a contract event
    const [account_id, contract_evt] = event.data

    // find out ABI based on the accountId for the contract
    // here we assume we have stored ABIs for our known addresses
    const abi = abis[account_id.toString()]

    // decode
    const decoded = abi.decodeEvent(contract_evt)

    // display results, etc.
    ...
  } else {
    // normal/other event logic
  }
})

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.