1
+ import { ethers } from 'ethers' ;
2
+ import { ApiPromise , WsProvider } from '@polkadot/api' ;
3
+ import { ContractPromise } from '@polkadot/api-contract' ;
4
+ import { KeyringPair } from '@polkadot/keyring/types' ;
5
+ import type { WeightV2 } from '@polkadot/types/interfaces' ;
6
+ import evmABI from './artefacts/evm.json' ;
7
+ import wasmABI from './artefacts/wasm.json' ;
8
+ import { GasLimit } from './utils' ;
9
+
10
+ export class Relayer {
11
+ evm : ethers . Contract ;
12
+ wasm : ContractPromise ;
13
+ wasmSigner : KeyringPair ;
14
+ wasmGasLimit : WeightV2 ;
15
+
16
+ constructor (
17
+ evm : ethers . Contract ,
18
+ wasm : ContractPromise ,
19
+ wasmSigner : KeyringPair ,
20
+ wasmGasLimit : WeightV2
21
+ ) {
22
+ this . evm = evm ;
23
+ this . wasm = wasm ;
24
+ this . wasmSigner = wasmSigner ;
25
+ this . wasmGasLimit = wasmGasLimit
26
+ }
27
+
28
+ static async init (
29
+ evmProviderURL : string ,
30
+ evmAddr : string ,
31
+ wasmProviderURL : string ,
32
+ wasmAddr : string ,
33
+ wasmSigner : KeyringPair ,
34
+ wasmGasLimit : GasLimit
35
+ ) : Promise < Relayer > {
36
+ const evmProvider = ethers . getDefaultProvider ( evmProviderURL ) ;
37
+ const evm = new ethers . Contract ( evmAddr , evmABI , evmProvider ) ;
38
+
39
+ const wsProvider = new WsProvider ( wasmProviderURL ) ;
40
+ const api = await ApiPromise . create ( { provider : wsProvider } ) ;
41
+ const wasm = new ContractPromise ( api , wasmABI , wasmAddr ) ;
42
+ const weightV2 = api . registry . createType ( 'WeightV2' , wasmGasLimit ) as WeightV2 ;
43
+
44
+ return new Relayer ( evm , wasm , wasmSigner , weightV2 ) ;
45
+ }
46
+
47
+ start ( ) {
48
+ this . evm . on ( "InitiateRequest" , ( id , name , recipient , yearsToRegister , value , ttl ) => {
49
+ console . log ( "New request:" , Number ( id ) , name , ttl ) ;
50
+ // TODO: Check ttl is valid
51
+ this . executeRequest ( Number ( id ) , name , recipient , Number ( yearsToRegister ) , value ) ;
52
+ } )
53
+ }
54
+
55
+ async executeRequest (
56
+ id : number ,
57
+ name : string ,
58
+ recipient : string ,
59
+ yearsToRegister : number ,
60
+ maxFeesInEVM : number
61
+ ) {
62
+ const maxFeesInWASM = this . valueEVM2WASM ( maxFeesInEVM ) ;
63
+
64
+ // TODO: first dry-run to save Tx which would fail
65
+
66
+ await this . wasm . tx . register (
67
+ {
68
+ gasLimit : this . wasmGasLimit
69
+ } ,
70
+ id ,
71
+ name ,
72
+ recipient ,
73
+ yearsToRegister ,
74
+ maxFeesInWASM ,
75
+ )
76
+ . signAndSend ( this . wasmSigner , ( { events = [ ] , status } ) => {
77
+ if ( status . isFinalized ) {
78
+ let successEventRecord = events . find ( ( eventRecord ) => {
79
+ const isContractEvent = this . wasm . api . events . contracts . ContractEmitted . is ;
80
+ const verifyEventEmitter = ( addr : any ) => eventRecord . event . data . at ( 0 ) ?. eq ( addr ) ;
81
+
82
+ const successEventExists = ( eventRecord : any , id : number ) => {
83
+ const decoded = this . wasm . abi . decodeEvent ( eventRecord ) ;
84
+ const emittedID = Number ( decoded . args [ 0 ] ) ;
85
+ return decoded . event . identifier === "wasm::registration_proxy::Success" &&
86
+ emittedID === id ;
87
+ } ;
88
+
89
+ return isContractEvent ( eventRecord . event ) &&
90
+ verifyEventEmitter ( this . wasm . address ) &&
91
+ successEventExists ( eventRecord , id ) ;
92
+ } ) ;
93
+
94
+ if ( successEventRecord === undefined ) {
95
+ // Failure
96
+ console . log ( "Failed to register" )
97
+ } else {
98
+ // Success
99
+ const decoded = this . wasm . abi . decodeEvent ( successEventRecord ) ;
100
+ const priceInWASM = Number ( decoded . args [ 1 ] ) ;
101
+ console . log ( "Registered successfully with price:" , priceInWASM ) ;
102
+ }
103
+ }
104
+ } ) ;
105
+ }
106
+
107
+ private valueEVM2WASM ( valueInEVM : number ) {
108
+ // TODO: set value converter properly
109
+ return valueInEVM + 10000000000000 ;
110
+ }
111
+ }
0 commit comments