1
1
import { Constants , Payload } from '@0xsequence/wallet-primitives'
2
- import { AbiFunction , Address , Bytes , Hex } from 'ox'
2
+ import { AbiFunction , Address , Bytes , Hex , TransactionReceipt } from 'ox'
3
3
import { FeeOption , FeeQuote , OperationStatus , Relayer } from './relayer.js'
4
4
5
+ type GenericProviderTransactionReceipt = 'success' | 'failed' | 'unknown'
6
+
5
7
export interface GenericProvider {
6
- sendTransaction ( args : { to : string ; data : string } ) : Promise < string >
8
+ sendTransaction ( args : { to : string ; data : string } , chainId : bigint ) : Promise < string >
9
+ getTransactionReceipt ( txHash : string , chainId : bigint ) : Promise < GenericProviderTransactionReceipt >
7
10
}
8
11
9
12
export class LocalRelayer implements Relayer {
@@ -18,15 +21,33 @@ export class LocalRelayer implements Relayer {
18
21
return undefined
19
22
}
20
23
24
+ const trySwitchChain = async ( chainId : bigint ) => {
25
+ try {
26
+ await eth . request ( {
27
+ method : 'wallet_switchEthereumChain' ,
28
+ params : [
29
+ {
30
+ chainId : `0x${ chainId . toString ( 16 ) } ` ,
31
+ } ,
32
+ ] ,
33
+ } )
34
+ } catch ( error ) {
35
+ // Log and continue
36
+ console . error ( 'Error switching chain' , error )
37
+ }
38
+ }
39
+
21
40
return new LocalRelayer ( {
22
- sendTransaction : async ( args ) => {
41
+ sendTransaction : async ( args , chainId ) => {
23
42
const accounts : string [ ] = await eth . request ( { method : 'eth_requestAccounts' } )
24
43
const from = accounts [ 0 ]
25
44
if ( ! from ) {
26
45
console . warn ( 'No account selected, skipping local relayer' )
27
46
return undefined
28
47
}
29
48
49
+ await trySwitchChain ( chainId )
50
+
30
51
const tx = await eth . request ( {
31
52
method : 'eth_sendTransaction' ,
32
53
params : [
@@ -39,6 +60,20 @@ export class LocalRelayer implements Relayer {
39
60
} )
40
61
return tx
41
62
} ,
63
+ getTransactionReceipt : async ( txHash , chainId ) => {
64
+ await trySwitchChain ( chainId )
65
+
66
+ const rpcReceipt = await eth . request ( { method : 'eth_getTransactionReceipt' , params : [ txHash ] } )
67
+ if ( rpcReceipt ) {
68
+ const receipt = TransactionReceipt . fromRpc ( rpcReceipt )
69
+ if ( receipt ?. status === 'success' ) {
70
+ return 'success'
71
+ } else if ( receipt ?. status === 'reverted' ) {
72
+ return 'failed'
73
+ }
74
+ }
75
+ return 'unknown'
76
+ } ,
42
77
} )
43
78
}
44
79
@@ -65,17 +100,26 @@ export class LocalRelayer implements Relayer {
65
100
}
66
101
67
102
async relay ( to : Address . Address , data : Hex . Hex , chainId : bigint , _ ?: FeeQuote ) : Promise < { opHash : Hex . Hex } > {
68
- const hash = Payload . hash ( to , chainId , this . decodeCalls ( data ) )
69
-
70
- await this . provider . sendTransaction ( {
71
- to,
72
- data,
73
- } )
103
+ const txHash = await this . provider . sendTransaction (
104
+ {
105
+ to,
106
+ data,
107
+ } ,
108
+ chainId ,
109
+ )
110
+ Hex . assert ( txHash )
74
111
75
- return { opHash : Hex . fromBytes ( hash ) }
112
+ return { opHash : txHash }
76
113
}
77
114
78
- status ( opHash : Hex . Hex , chainId : bigint ) : Promise < OperationStatus > {
79
- throw new Error ( 'Method not implemented.' )
115
+ async status ( opHash : Hex . Hex , chainId : bigint ) : Promise < OperationStatus > {
116
+ const receipt = await this . provider . getTransactionReceipt ( opHash , chainId )
117
+ if ( receipt === 'unknown' ) {
118
+ // Could be pending but we don't know
119
+ return { status : 'unknown' }
120
+ }
121
+ return receipt === 'success'
122
+ ? { status : 'confirmed' , transactionHash : opHash }
123
+ : { status : 'failed' , reason : 'failed' }
80
124
}
81
125
}
0 commit comments