feat(client): NET-910 Experimental GSN support
Summary
Please provide a summary of the changes and a motivation if applicable.
TODO: remove sand box scripts
Changes
Provide a bullet list of individual changes. Leave this section out if change set is small and obvious from summary.
Open questions
- [ ] Common error cases that occur sometimes, what to do about them?
- [ ] To test and how to test?
- [ ] Make gns logLevel not output so much stuff? Should we have ability to set it to
debugon request?
Limitations and future improvements
What to do about common error cases?
Occasionally hits the following error cases
Case 1
reason: Error: Failed to relay call. Results:
Ping errors (5):
https://gsn.streamr.network/gsn1 => Proposed gas price: 0x1238ca8e4b; relay's MinGasPrice: 94321711874
https://matic.relayer.prod.daory.net/gsn1 => Proposed gas price: 0x1238ca8e4b; relay's MinGasPrice: 90218195358
https://digglehopper-delta.com/gsn1 => Proposed gas price: 0x1238ca8e4b; relay's MinGasPrice: 93925357037
https://polygon-relay1.digglehopper-alpha.com/gsn1 => Proposed gas price: 0x1238ca8e4b; relay's MinGasPrice: 90709305594
https://relay-polygon.enzyme.finance/gsn1 => Proposed gas price: 0x1238ca8e4b; relay's MinGasPrice: 90709305594
Relaying errors (1):
https://matic-gsn.treejer.com/gsn1 => Got error response from relay: relayCall reverted in server: Returned error: {"jsonrpc":"2.0","id":20668547,"error":{"code":-32602,"message":""}}
at /home/harbu/work/monorepo/node_modules/@opengsn/provider/src/RelayProvider.ts:142:20
at processTicksAndRejections (node:internal/process/task_queues:96:5)
Case 2
Rejected relayTransaction call with reason: couldn't retrieve latest blockNumber from node. last block: 36258837, got block: 36258831
/home/harbu/work/monorepo/packages/client/src/utils/contract.ts:64
const wrappedError = new Error(`Error in contract call "${methodName}"`)
^
Error: Error in contract call "streamRegistry.createStream"
at withErrorHandling (/home/harbu/work/monorepo/packages/client/src/utils/contract.ts:64:30)
at async Object.createStream (/home/harbu/work/monorepo/packages/client/src/utils/contract.ts:78:29)
at async waitForTx (/home/harbu/work/monorepo/packages/client/src/utils/contract.ts:20:16)
at async StreamRegistry.createStream (/home/harbu/work/monorepo/packages/client/src/registry/StreamRegistry.ts:145:13)
at async /home/harbu/work/monorepo/packages/client/src/sandbox.ts:10:24 {
reason: Error: Rejected relayTransaction call with reason: couldn't retrieve latest blockNumber from node. last block: 36258837, got block: 36258831
at /home/harbu/work/monorepo/node_modules/@opengsn/provider/src/RelayProvider.ts:148:18
Checklist before requesting a review
- [ ] Is this a breaking change? If it is, be clear in summary.
- [ ] Read through code myself one more time.
- [ ] Make sure any and all
TODOcomments left behind are meant to be left in. - [ ] Has reasonable passing test coverage?
- [ ] Updated changelog if applicable.
- [ ] Updated documentation if applicable.
NET-910 client: Add experimental GSN support
Metatransactions are payloads signed by the user which are then transmitted to the chain by a relayer. The relayer pays gas, meaning that the user can effectively make gasless transactions.
GSN is a decentralized network of such relayers, minimizing the risk that a user's metatransaction doesn't get relayed to the chain correctly. It also implements a payment mechanism whereby the relayer gets compensated for the gas they pay.
We should start experimenting with enabling metatransactions/GSN in the streamr-client. The first step would be to add it as an option to stream creation (default: off). Once we have that working, from there we should expand this option to cover other interactions with the StreamRegistry (such as updating streams and setting permissions) as well as manipulating the StreamStorageRegistry.
The GSN integration could be configured via client constructor options as follows:
const client = new StreamrClient({
...,
GSN: {
// controls whether GSN is used for supported smart contract calls
enabled: false,
// default smart contract addresses should come from the config package
forwarderAddress: FORWARDER,
paymasterAddress: PAYMASTER,
// default relays
preferredRelays: ['https://gsn.streamr.network/gsn1'],
// other gsn-related settings
relayLookupWindowBlocks: 9000,
relayRegistrationLookupBlocks: 9000,
pastEventsQueryMaxPageSize: 9000,
auditorsCount: 0,
...
},
})
Here's an example of how to make GSN-enabled calls to the stream registry: https://github.com/streamr-dev/network-contracts/blob/master/packages/smartcontracts/scripts/transactThroughGSN.ts
The GSN calls should work with the different types of signers, i.e. when the client is configured with a private key and when a Web3 provider (MetaMask) is given.
This will not be merged, however I will keep it around in closed state if we need to reference it later.