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 { EventWithData } from "./types" ;
13
14
import { decodeEvent , isDevnet } from "./utils" ;
14
15
import { getSlotForBlock } from "./SpokeUtils" ;
15
16
@@ -26,39 +27,48 @@ type GetSignaturesForAddressConfig = Parameters<GetSignaturesForAddressApi["getS
26
27
type GetSignaturesForAddressTransaction = ReturnType < GetSignaturesForAddressApi [ "getSignaturesForAddress" ] > [ number ] ;
27
28
type GetSignaturesForAddressApiResponse = readonly GetSignaturesForAddressTransaction [ ] ;
28
29
29
- export class SvmSpokeEventsClient {
30
+ export class SvmCpiEventsClient {
30
31
private rpc : web3 . Rpc < web3 . SolanaRpcApiFromTransport < RpcTransport > > ;
31
- private svmSpokeAddress : Address ;
32
- private svmSpokeEventAuthority : Address ;
32
+ private programAddress : Address ;
33
+ private programEventAuthority : Address ;
34
+ private idl : Idl ;
33
35
34
36
/**
35
37
* Private constructor. Use the async create() method to instantiate.
36
38
*/
37
39
private constructor (
38
40
rpc : web3 . Rpc < web3 . SolanaRpcApiFromTransport < RpcTransport > > ,
39
- svmSpokeAddress : Address ,
40
- eventAuthority : Address
41
+ address : Address ,
42
+ eventAuthority : Address ,
43
+ idl : Idl
41
44
) {
42
45
this . rpc = rpc ;
43
- this . svmSpokeAddress = svmSpokeAddress ;
44
- this . svmSpokeEventAuthority = eventAuthority ;
46
+ this . programAddress = address ;
47
+ this . programEventAuthority = eventAuthority ;
48
+ this . idl = idl ;
45
49
}
46
50
47
51
/**
48
52
* Factory method to asynchronously create an instance of SvmSpokeEventsClient.
49
53
*/
50
- public static async create (
51
- rpc : web3 . Rpc < web3 . SolanaRpcApiFromTransport < RpcTransport > >
52
- ) : Promise < SvmSpokeEventsClient > {
54
+ public static async create ( rpc : web3 . Rpc < web3 . SolanaRpcApiFromTransport < RpcTransport > > ) : Promise < SvmCpiEventsClient > {
53
55
const isTestnet = await isDevnet ( rpc ) ;
54
56
const programId = getDeployedAddress ( "SvmSpoke" , getSolanaChainId ( isTestnet ? "devnet" : "mainnet" ) . toString ( ) ) ;
55
57
if ( ! programId ) throw new Error ( "Program not found" ) ;
56
- const svmSpokeAddress = web3 . address ( programId ) ;
57
- const [ svmSpokeEventAuthority ] = await web3 . getProgramDerivedAddress ( {
58
- programAddress : svmSpokeAddress ,
58
+ return this . createFor ( rpc , programId , SvmSpokeIdl ) ;
59
+ }
60
+
61
+ public static async createFor (
62
+ rpc : web3 . Rpc < web3 . SolanaRpcApiFromTransport < RpcTransport > > ,
63
+ programId : string ,
64
+ idl : Idl
65
+ ) : Promise < SvmCpiEventsClient > {
66
+ const address = web3 . address ( programId ) ;
67
+ const [ eventAuthority ] = await web3 . getProgramDerivedAddress ( {
68
+ programAddress : address ,
59
69
seeds : [ "__event_authority" ] ,
60
70
} ) ;
61
- return new SvmSpokeEventsClient ( rpc , svmSpokeAddress , svmSpokeEventAuthority ) ;
71
+ return new SvmCpiEventsClient ( rpc , address , eventAuthority , idl ) ;
62
72
}
63
73
64
74
/**
@@ -70,14 +80,14 @@ export class SvmSpokeEventsClient {
70
80
* @param options - Options for fetching signatures.
71
81
* @returns A promise that resolves to an array of events matching the eventName.
72
82
*/
73
- public async queryEvents < T extends EventData > (
74
- eventName : EventName ,
83
+ public async queryEvents (
84
+ eventName : string ,
75
85
fromBlock ?: bigint ,
76
86
toBlock ?: bigint ,
77
87
options : GetSignaturesForAddressConfig = { limit : 1000 , commitment : "confirmed" }
78
- ) : Promise < EventWithData < T > [ ] > {
88
+ ) : Promise < EventWithData [ ] > {
79
89
const events = await this . queryAllEvents ( fromBlock , toBlock , options ) ;
80
- return events . filter ( ( event ) => event . name === eventName ) as EventWithData < T > [ ] ;
90
+ return events . filter ( ( event ) => event . name === eventName ) as EventWithData [ ] ;
81
91
}
82
92
83
93
/**
@@ -92,7 +102,7 @@ export class SvmSpokeEventsClient {
92
102
fromBlock ?: bigint ,
93
103
toBlock ?: bigint ,
94
104
options : GetSignaturesForAddressConfig = { limit : 1000 , commitment : "confirmed" }
95
- ) : Promise < EventWithData < EventData > [ ] > {
105
+ ) : Promise < EventWithData [ ] > {
96
106
const allSignatures : GetSignaturesForAddressTransaction [ ] = [ ] ;
97
107
let hasMoreSignatures = true ;
98
108
let currentOptions = options ;
@@ -112,7 +122,7 @@ export class SvmSpokeEventsClient {
112
122
113
123
while ( hasMoreSignatures ) {
114
124
const signatures : GetSignaturesForAddressApiResponse = await this . rpc
115
- . getSignaturesForAddress ( this . svmSpokeAddress , currentOptions )
125
+ . getSignaturesForAddress ( this . programAddress , currentOptions )
116
126
. send ( ) ;
117
127
// Signatures are sorted by slot in descending order.
118
128
allSignatures . push ( ...signatures ) ;
@@ -175,11 +185,9 @@ export class SvmSpokeEventsClient {
175
185
* @param txResult - The transaction result.
176
186
* @returns A promise that resolves to an array of events with their data and name.
177
187
*/
178
- private processEventFromTx (
179
- txResult : GetTransactionReturnType
180
- ) : { program : Address ; data : EventData ; name : EventName } [ ] {
188
+ private processEventFromTx ( txResult : GetTransactionReturnType ) : { program : Address ; data : unknown ; name : string } [ ] {
181
189
if ( ! txResult ) return [ ] ;
182
- const events : { program : Address ; data : EventData ; name : EventName } [ ] = [ ] ;
190
+ const events : { program : Address ; data : unknown ; name : string } [ ] = [ ] ;
183
191
184
192
const accountKeys = txResult . transaction . message . accountKeys ;
185
193
const messageAccountKeys = [ ...accountKeys ] ;
@@ -195,22 +203,22 @@ export class SvmSpokeEventsClient {
195
203
if (
196
204
ixProgramId !== undefined &&
197
205
singleIxAccount !== undefined &&
198
- this . svmSpokeAddress === ixProgramId &&
199
- this . svmSpokeEventAuthority === singleIxAccount
206
+ this . programAddress === ixProgramId &&
207
+ this . programEventAuthority === singleIxAccount
200
208
) {
201
209
const ixData = bs58 . decode ( ix . data ) ;
202
210
// Skip the first 8 bytes (assumed header) and encode the rest.
203
211
const eventData = Buffer . from ( ixData . slice ( 8 ) ) . toString ( "base64" ) ;
204
- const { name, data } = decodeEvent ( SvmSpokeIdl , eventData ) ;
205
- events . push ( { program : this . svmSpokeAddress , name, data } ) ;
212
+ const { name, data } = decodeEvent ( this . idl , eventData ) ;
213
+ events . push ( { program : this . programAddress , name, data } ) ;
206
214
}
207
215
}
208
216
}
209
217
210
218
return events ;
211
219
}
212
220
213
- public getSvmSpokeAddress ( ) : Address {
214
- return this . svmSpokeAddress ;
221
+ public getProgramAddress ( ) : Address {
222
+ return this . programAddress ;
215
223
}
216
224
}
0 commit comments