Transfer Event SubscriptionInteracting with Fungible Token Program
11/11 tutorials
100%

Transfer Events Subscription: Utilizing Sails Events

In this step, subscribe to transfer events to monitor token transfers and update balances accordingly.

Using Sails-JS library, events are monitored via subscriptions.

A particular service of the program contains all the necessary subscriptions for available events, such as transfer and approval. By using them, react to specific transactions and update the state of the application in real-time.

Subscribe to Transfer Events

Subscribe to transfer events using the subscribeToTransferEvent method from the VFT Service of the program instance.

This method allows listening for transfer events and executing a callback function when an event occurs.

Handling Transfer Events

Filter out events that do not match the specific transaction of interest, keeping only transfers from the developer account to Alice with the specified token amount.

When a matching transfer event is detected, read the updated balances of developer and Alice accounts using the balanceOf method described in the previous step. This ensures that the latest balance information is available after the transfer.

Once the desired transaction is found and the balances are updated, unsubscribe from the transfer events to stop listening for further events.

This approach allows efficient monitoring and reaction to specific token transfers, ensuring that the application state remains up-to-date with the latest network state.

import { decodeAddress, GearApi } from '@gear-js/api';
import { Keyring } from '@polkadot/api';
import { mnemonicGenerate } from '@polkadot/util-crypto';

import { Program } from './lib';

const VARA_TESTNET_ENDPOINT = 'wss://testnet.vara.network';
const api = await GearApi.create({ providerAddress: VARA_TESTNET_ENDPOINT });

const mnemonic = mnemonicGenerate();
const keyring = new Keyring({ type: 'sr25519' }).addFromMnemonic(mnemonic);
const aliceKeyring = new Keyring({ type: 'sr25519' }).addFromUri('//Alice');
const accountAddress = decodeAddress(keyring.address);
const aliceAccountAddress = decodeAddress(aliceKeyring.address);

const TOKEN = {
  NAME: 'Tutorial Token',
  SYMBOL: 'TT',
  DECIMALS: 12,
} as const;

const TOKENS_AMOUNT = 1 * 10 ** TOKEN.DECIMALS;

const PROGRAM_ID = '0x00';
const vftProgram = new Program(api, PROGRAM_ID);

const mintTokens = async () => {
  const mintTransaction = await vftProgram.vft
    .mint(accountAddress, TOKENS_AMOUNT)
    .withAccount(keyring)
    .calculateGas();

  const { response: mintResponse } = await mintTransaction.signAndSend();

  const mintResult = await mintResponse();

  return mintResult;
};

const transferTokens = async () => {
  const transferTransaction = await vftProgram.vft
    .transfer(aliceAccountAddress, TOKENS_AMOUNT)
    .withAccount(keyring)
    .calculateGas();

  const { response: transferResponse } =
    await transferTransaction.signAndSend();

  const transferResult = await transferResponse();

  return transferResult;
};

const getBalance = async () => {
  const queryResult = await vftProgram.vft.balanceOf(accountAddress);

  return queryResult;
};

const getAliceBalance = async () => {
  const queryResult = await vftProgram.vft.balanceOf(aliceAccountAddress);

  return queryResult;
};

const unsubscribe = vftProgram.vft.subscribeToTransferEvent(
  async ({ from, to, value }) => {
    if (
      from !== accountAddress ||
      to !== aliceAccountAddress ||
      value !== TOKENS_AMOUNT
    )
      return;

    const balance = await getBalance();
    const aliceBalance = await getAliceBalance();

    (await unsubscribe)();
  }
);