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.