1
+ import { Idl } from "@coral-xyz/anchor" ;
1
2
import { getDeployedAddress , SvmSpokeIdl } from "@across-protocol/contracts" ;
2
3
import { getSolanaChainId } from "@across-protocol/contracts/dist/src/svm/web3-v1" ;
3
4
import web3 , {
@@ -9,7 +10,7 @@ import web3, {
9
10
Signature ,
10
11
} from "@solana/kit" ;
11
12
import { bs58 } from "../../utils" ;
12
- import { EventData , EventName , EventWithData } from "./types" ;
13
+ import { EventName , EventWithData } from "./types" ;
13
14
import { decodeEvent , isDevnet } from "./utils" ;
14
15
15
16
// Utility type to extract the return type for the JSON encoding overload. We only care about the overload where the
@@ -25,39 +26,48 @@ type GetSignaturesForAddressConfig = Parameters<GetSignaturesForAddressApi["getS
25
26
type GetSignaturesForAddressTransaction = ReturnType < GetSignaturesForAddressApi [ "getSignaturesForAddress" ] > [ number ] ;
26
27
type GetSignaturesForAddressApiResponse = readonly GetSignaturesForAddressTransaction [ ] ;
27
28
28
- export class SvmSpokeEventsClient {
29
+ export class SvmCpiEventsClient {
29
30
private rpc : web3 . Rpc < web3 . SolanaRpcApiFromTransport < RpcTransport > > ;
30
- private svmSpokeAddress : Address ;
31
- private svmSpokeEventAuthority : Address ;
31
+ private programAddress : Address ;
32
+ private programEventAuthority : Address ;
33
+ private idl : Idl ;
32
34
33
35
/**
34
36
* Private constructor. Use the async create() method to instantiate.
35
37
*/
36
38
private constructor (
37
39
rpc : web3 . Rpc < web3 . SolanaRpcApiFromTransport < RpcTransport > > ,
38
- svmSpokeAddress : Address ,
39
- eventAuthority : Address
40
+ address : Address ,
41
+ eventAuthority : Address ,
42
+ idl : Idl
40
43
) {
41
44
this . rpc = rpc ;
42
- this . svmSpokeAddress = svmSpokeAddress ;
43
- this . svmSpokeEventAuthority = eventAuthority ;
45
+ this . programAddress = address ;
46
+ this . programEventAuthority = eventAuthority ;
47
+ this . idl = idl ;
44
48
}
45
49
46
50
/**
47
51
* Factory method to asynchronously create an instance of SvmSpokeEventsClient.
48
52
*/
49
- public static async create (
50
- rpc : web3 . Rpc < web3 . SolanaRpcApiFromTransport < RpcTransport > >
51
- ) : Promise < SvmSpokeEventsClient > {
53
+ public static async create ( rpc : web3 . Rpc < web3 . SolanaRpcApiFromTransport < RpcTransport > > ) : Promise < SvmCpiEventsClient > {
52
54
const isTestnet = await isDevnet ( rpc ) ;
53
55
const programId = getDeployedAddress ( "SvmSpoke" , getSolanaChainId ( isTestnet ? "devnet" : "mainnet" ) . toString ( ) ) ;
54
56
if ( ! programId ) throw new Error ( "Program not found" ) ;
55
- const svmSpokeAddress = web3 . address ( programId ) ;
56
- const [ svmSpokeEventAuthority ] = await web3 . getProgramDerivedAddress ( {
57
- programAddress : svmSpokeAddress ,
57
+ return this . createFor ( rpc , programId , SvmSpokeIdl ) ;
58
+ }
59
+
60
+ public static async createFor (
61
+ rpc : web3 . Rpc < web3 . SolanaRpcApiFromTransport < RpcTransport > > ,
62
+ programId : string ,
63
+ idl : Idl
64
+ ) : Promise < SvmCpiEventsClient > {
65
+ const address = web3 . address ( programId ) ;
66
+ const [ eventAuthority ] = await web3 . getProgramDerivedAddress ( {
67
+ programAddress : address ,
58
68
seeds : [ "__event_authority" ] ,
59
69
} ) ;
60
- return new SvmSpokeEventsClient ( rpc , svmSpokeAddress , svmSpokeEventAuthority ) ;
70
+ return new SvmCpiEventsClient ( rpc , address , eventAuthority , idl ) ;
61
71
}
62
72
63
73
/**
@@ -69,14 +79,14 @@ export class SvmSpokeEventsClient {
69
79
* @param options - Options for fetching signatures.
70
80
* @returns A promise that resolves to an array of events matching the eventName.
71
81
*/
72
- public async queryEvents < T extends EventData > (
82
+ public async queryEvents (
73
83
eventName : EventName ,
74
84
fromSlot ?: bigint ,
75
85
toSlot ?: bigint ,
76
86
options : GetSignaturesForAddressConfig = { limit : 1000 , commitment : "confirmed" }
77
- ) : Promise < EventWithData < T > [ ] > {
87
+ ) : Promise < EventWithData [ ] > {
78
88
const events = await this . queryAllEvents ( fromSlot , toSlot , options ) ;
79
- return events . filter ( ( event ) => event . name === eventName ) as EventWithData < T > [ ] ;
89
+ return events . filter ( ( event ) => event . name === eventName ) as EventWithData [ ] ;
80
90
}
81
91
82
92
/**
@@ -91,14 +101,14 @@ export class SvmSpokeEventsClient {
91
101
fromSlot ?: bigint ,
92
102
toSlot ?: bigint ,
93
103
options : GetSignaturesForAddressConfig = { limit : 1000 , commitment : "confirmed" }
94
- ) : Promise < EventWithData < EventData > [ ] > {
104
+ ) : Promise < EventWithData [ ] > {
95
105
const allSignatures : GetSignaturesForAddressTransaction [ ] = [ ] ;
96
106
let hasMoreSignatures = true ;
97
107
let currentOptions = options ;
98
108
99
109
while ( hasMoreSignatures ) {
100
110
const signatures : GetSignaturesForAddressApiResponse = await this . rpc
101
- . getSignaturesForAddress ( this . svmSpokeAddress , currentOptions )
111
+ . getSignaturesForAddress ( this . programAddress , currentOptions )
102
112
. send ( ) ;
103
113
// Signatures are sorted by slot in descending order.
104
114
allSignatures . push ( ...signatures ) ;
@@ -161,11 +171,9 @@ export class SvmSpokeEventsClient {
161
171
* @param txResult - The transaction result.
162
172
* @returns A promise that resolves to an array of events with their data and name.
163
173
*/
164
- private processEventFromTx (
165
- txResult : GetTransactionReturnType
166
- ) : { program : Address ; data : EventData ; name : EventName } [ ] {
174
+ private processEventFromTx ( txResult : GetTransactionReturnType ) : { program : Address ; data : unknown ; name : string } [ ] {
167
175
if ( ! txResult ) return [ ] ;
168
- const events : { program : Address ; data : EventData ; name : EventName } [ ] = [ ] ;
176
+ const events : { program : Address ; data : unknown ; name : string } [ ] = [ ] ;
169
177
170
178
const accountKeys = txResult . transaction . message . accountKeys ;
171
179
const messageAccountKeys = [ ...accountKeys ] ;
@@ -181,22 +189,22 @@ export class SvmSpokeEventsClient {
181
189
if (
182
190
ixProgramId !== undefined &&
183
191
singleIxAccount !== undefined &&
184
- this . svmSpokeAddress === ixProgramId &&
185
- this . svmSpokeEventAuthority === singleIxAccount
192
+ this . programAddress === ixProgramId &&
193
+ this . programEventAuthority === singleIxAccount
186
194
) {
187
195
const ixData = bs58 . decode ( ix . data ) ;
188
196
// Skip the first 8 bytes (assumed header) and encode the rest.
189
197
const eventData = Buffer . from ( ixData . slice ( 8 ) ) . toString ( "base64" ) ;
190
- const { name, data } = decodeEvent ( SvmSpokeIdl , eventData ) ;
191
- events . push ( { program : this . svmSpokeAddress , name, data } ) ;
198
+ const { name, data } = decodeEvent ( this . idl , eventData ) ;
199
+ events . push ( { program : this . programAddress , name, data } ) ;
192
200
}
193
201
}
194
202
}
195
203
196
204
return events ;
197
205
}
198
206
199
- public getSvmSpokeAddress ( ) : Address {
200
- return this . svmSpokeAddress ;
207
+ public getProgramAddress ( ) : Address {
208
+ return this . programAddress ;
201
209
}
202
210
}
0 commit comments