Sending NGNT

We can use web3 to call contract functions. In fact, Etherscan uses web3 to let you call the mint & burn functions with their web interface.

Gas Stations Network (GSN)

NGNT implements GSN. This allows users & applications call contract functions without paying for gas in ETH.

The Gas Station Network (GSN) is a decentralized network of relayers which can be used to sign and send Ethereum transactions without the original sender (the end-users) paying for gas.

This is particularly useful for NGNT's use-case because gas is usually paid in Ether. Having to acquire and store Ether before being able to transfer tokens (especially one like NGNT) is a difficult, generally bad user experience.

The Code

The code snippet below shows how to use web3 to call the NGNT transfer function. We shall be using GSNProvider from @openzeppelin/gsn-provider instead of HttpProvider as in the previous examples.

const Web3 = require('web3');
const {GSNProvider} = require("@openzeppelin/gsn-provider");
const HDNode = require('ethers').utils.HDNode;
const mnemonic = <seed phrase>;
const masterNode = HDNode.fromMnemonic(mnemonic);
const url = <url to Ethereum client>;
const fromAddress = <sender address>;
const toAddress = <recipient address>;

// the next two lines of code assume you're storing addresses & path in a mongoose model called Account
const account = await Account.findOne({address: fromAddress});
const derivationPath = account.path;

const addressNode = masterNode.derivePath(derivationPath);
let privateKey = addressNode.privateKey;

const gsnProvider = new GSNProvider(url, {signKey: privateKey});
const web3Provider = new Web3(gsnProvider);
const provider = web3Provider.eth;

const NGNT = new provider.Contract(NGNTAbi, NGNTContractAddress);

// Use GSN to call transfer function & pay gas fee in NGNT.
await NGNT.methods.transfer(toAddress, valueInKobo).send({from: fromAddress})

// or you can call the transfer function without GSN.
// this requires that the sender address has some Ethereum to pay for gas.
if (privateKey.startsWith('0x')) {
  privateKey = privateKey.substring(2);
}

const privateKeyBuffer = Buffer.from(privateKey, 'hex');
const transactionData = await NGNT.methods.transfer(toAccount, valueInKobo).encodeABI();

const txObject = {
  nonce: await this.provider.getTransactionCount(fromAddress),
  to: toAddress,
  gasLimit: <gas limit>, // these determine how much you're willing to pay as gas for the transaction
  gasPrice: <gas price>,
  data: transactionData,
};

const transaction = new EthereumTx(txObject);
transaction.sign(privateKeyBuffer);
const serializedTransaction = transaction.serialize();
const rawTransaction = '0x' + serializedTransaction.toString('hex');

// it does not matter that the provider is still a GSN provider. 
// The sendSignedTransaction method acts like the HttpProvider and sends the transaction the normal way.
provider.sendSignedTransaction(rawTransaction);

Last updated

Was this helpful?