GSN Helpers is deprecated. We are no longer developing new features nor addressing issues. Read here for more info.

Preparing a Testing Environment

When testing a GSN application, you need more than a local blockchain: the GSN RelayHub contract has to be deployed, there must be relayers running, and your recipients need to be funded.

This guide will provide you with simple scripts you can add to your project to start testing using the GSN right away.

Simple Bash Setup

It is not uncommon for projects to have a test.sh file that performs some initialization after a local blockchain is running, but before the tests themselves execute.

The following script will deploy RelayHub, download the relayer binary, run a relayer server and register on the hub:

// Perform necessary cleanup on exit
trap cleanup EXIT

cleanup() {
  kill $gsn_relay_server_pid
}

ganache_url="http://localhost:$ganache_port"
relayer_port=8099

setup_gsn_relay() {
  gsn_relay_server_pid=$(npx oz-gsn run-relayer --ethereumNodeURL $ganache_url --port $relayer_port --detach --quiet)
}

Advanced Configuration

If you want to have more fine-grained control over the setup process, you can use the following setup:

ganache_url="http://localhost:8545"
relayer_port=8099
relayer_url="http://localhost:${relayer_port}"

relayer_running() {
  nc -z localhost "$relayer_port"
}

setup_gsn_relay() {
  relay_hub_addr=$(npx oz-gsn deploy-relay-hub --ethereumNodeURL $ganache_url)
  echo "Launching GSN relay server to hub $relay_hub_addr"

  ./bin/gsn-relay -DevMode -RelayHubAddress $relay_hub_addr -EthereumNodeUrl $ganache_url -Url $relayer_url &> /dev/null &
  gsn_relay_server_pid=$!

  while ! relayer_running; do
    sleep 0.1
  done
  echo "GSN relay server launched!"

  npx oz-gsn register-relayer --ethereumNodeURL $ganache_url --relayUrl $relayer_url
}

Interacting with the GSN

Once the GSN setup is complete, before your test cases are executed you will need to set up an OpenZeppelin GSN Provider and register any recipients:

beforeEach(async function () {
  // Create web3 instance and a contract
  this.web3 = new Web3(PROVIDER_URL);
  this.accounts = await this.web3.eth.getAccounts();

  // Create recipient contract
  const Recipient = new this.web3.eth.Contract(RecipientAbi, null, { data: RecipientBytecode });
  this.recipient = await Recipient.deploy().send({ from: this.accounts[0], gas: 1e6 });

  // Register the recipient in the hub
  await fundRecipient(this.web3, { recipient: this.recipient.options.address });

  // Create gsn provider and plug it into the recipient
  const gsnProvider = new GSNProvider(PROVIDER_URL);
  this.recipient.setProvider(gsnProvider);
});

All transactions sent to the recipient contract instance will be sent as a meta-transaction via the GSN running locally on your workstation.