Skip to content

Commit d0bde64

Browse files
chore: merge
2 parents 4bf33bf + c9ee25e commit d0bde64

File tree

4 files changed

+50
-42
lines changed

4 files changed

+50
-42
lines changed

src/arch/svm/eventsClient.ts

+38-30
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { Idl } from "@coral-xyz/anchor";
12
import { getDeployedAddress, SvmSpokeIdl } from "@across-protocol/contracts";
23
import { getSolanaChainId } from "@across-protocol/contracts/dist/src/svm/web3-v1";
34
import web3, {
@@ -9,7 +10,7 @@ import web3, {
910
Signature,
1011
} from "@solana/kit";
1112
import { bs58 } from "../../utils";
12-
import { EventData, EventName, EventWithData } from "./types";
13+
import { EventName, EventWithData } from "./types";
1314
import { decodeEvent, isDevnet } from "./utils";
1415

1516
// 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
2526
type GetSignaturesForAddressTransaction = ReturnType<GetSignaturesForAddressApi["getSignaturesForAddress"]>[number];
2627
type GetSignaturesForAddressApiResponse = readonly GetSignaturesForAddressTransaction[];
2728

28-
export class SvmSpokeEventsClient {
29+
export class SvmCpiEventsClient {
2930
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;
3234

3335
/**
3436
* Private constructor. Use the async create() method to instantiate.
3537
*/
3638
private constructor(
3739
rpc: web3.Rpc<web3.SolanaRpcApiFromTransport<RpcTransport>>,
38-
svmSpokeAddress: Address,
39-
eventAuthority: Address
40+
address: Address,
41+
eventAuthority: Address,
42+
idl: Idl
4043
) {
4144
this.rpc = rpc;
42-
this.svmSpokeAddress = svmSpokeAddress;
43-
this.svmSpokeEventAuthority = eventAuthority;
45+
this.programAddress = address;
46+
this.programEventAuthority = eventAuthority;
47+
this.idl = idl;
4448
}
4549

4650
/**
4751
* Factory method to asynchronously create an instance of SvmSpokeEventsClient.
4852
*/
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> {
5254
const isTestnet = await isDevnet(rpc);
5355
const programId = getDeployedAddress("SvmSpoke", getSolanaChainId(isTestnet ? "devnet" : "mainnet").toString());
5456
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,
5868
seeds: ["__event_authority"],
5969
});
60-
return new SvmSpokeEventsClient(rpc, svmSpokeAddress, svmSpokeEventAuthority);
70+
return new SvmCpiEventsClient(rpc, address, eventAuthority, idl);
6171
}
6272

6373
/**
@@ -69,14 +79,14 @@ export class SvmSpokeEventsClient {
6979
* @param options - Options for fetching signatures.
7080
* @returns A promise that resolves to an array of events matching the eventName.
7181
*/
72-
public async queryEvents<T extends EventData>(
82+
public async queryEvents(
7383
eventName: EventName,
7484
fromSlot?: bigint,
7585
toSlot?: bigint,
7686
options: GetSignaturesForAddressConfig = { limit: 1000, commitment: "confirmed" }
77-
): Promise<EventWithData<T>[]> {
87+
): Promise<EventWithData[]> {
7888
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[];
8090
}
8191

8292
/**
@@ -91,14 +101,14 @@ export class SvmSpokeEventsClient {
91101
fromSlot?: bigint,
92102
toSlot?: bigint,
93103
options: GetSignaturesForAddressConfig = { limit: 1000, commitment: "confirmed" }
94-
): Promise<EventWithData<EventData>[]> {
104+
): Promise<EventWithData[]> {
95105
const allSignatures: GetSignaturesForAddressTransaction[] = [];
96106
let hasMoreSignatures = true;
97107
let currentOptions = options;
98108

99109
while (hasMoreSignatures) {
100110
const signatures: GetSignaturesForAddressApiResponse = await this.rpc
101-
.getSignaturesForAddress(this.svmSpokeAddress, currentOptions)
111+
.getSignaturesForAddress(this.programAddress, currentOptions)
102112
.send();
103113
// Signatures are sorted by slot in descending order.
104114
allSignatures.push(...signatures);
@@ -161,11 +171,9 @@ export class SvmSpokeEventsClient {
161171
* @param txResult - The transaction result.
162172
* @returns A promise that resolves to an array of events with their data and name.
163173
*/
164-
private processEventFromTx(
165-
txResult: GetTransactionReturnType
166-
): { program: Address; data: EventData; name: EventName }[] {
174+
private processEventFromTx(txResult: GetTransactionReturnType): { program: Address; data: unknown; name: string }[] {
167175
if (!txResult) return [];
168-
const events: { program: Address; data: EventData; name: EventName }[] = [];
176+
const events: { program: Address; data: unknown; name: string }[] = [];
169177

170178
const accountKeys = txResult.transaction.message.accountKeys;
171179
const messageAccountKeys = [...accountKeys];
@@ -181,22 +189,22 @@ export class SvmSpokeEventsClient {
181189
if (
182190
ixProgramId !== undefined &&
183191
singleIxAccount !== undefined &&
184-
this.svmSpokeAddress === ixProgramId &&
185-
this.svmSpokeEventAuthority === singleIxAccount
192+
this.programAddress === ixProgramId &&
193+
this.programEventAuthority === singleIxAccount
186194
) {
187195
const ixData = bs58.decode(ix.data);
188196
// Skip the first 8 bytes (assumed header) and encode the rest.
189197
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 });
192200
}
193201
}
194202
}
195203

196204
return events;
197205
}
198206

199-
public getSvmSpokeAddress(): Address {
200-
return this.svmSpokeAddress;
207+
public getProgramAddress(): Address {
208+
return this.programAddress;
201209
}
202210
}

src/arch/svm/types.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,13 @@ export enum SVMEventNames {
3636

3737
export type EventName = keyof typeof SVMEventNames;
3838

39-
export type EventWithData<T extends EventData> = {
39+
export type EventWithData = {
4040
confirmationStatus: string | null;
4141
blockTime: UnixTimestamp | null;
4242
signature: Signature;
4343
slot: bigint;
44-
name: EventName;
45-
data: T;
44+
name: string;
45+
data: unknown;
4646
program: Address;
4747
};
4848

src/arch/svm/utils.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { BN, BorshEventCoder, Idl } from "@coral-xyz/anchor";
22
import { BigNumber, isUint8Array, SvmAddress } from "../../utils";
33
import web3, { address, isAddress, RpcTransport, getProgramDerivedAddress, getU64Encoder, Address } from "@solana/kit";
44

5-
import { EventName, EventData, SVMEventNames } from "./types";
5+
import { EventName, SVMEventNames } from "./types";
66
import { FillType } from "../../interfaces";
77

88
/**
@@ -44,11 +44,11 @@ export function parseEventData(eventData: any): any {
4444
/**
4545
* Decodes a raw event according to a supplied IDL.
4646
*/
47-
export function decodeEvent(idl: Idl, rawEvent: string): { data: EventData; name: EventName } {
47+
export function decodeEvent(idl: Idl, rawEvent: string): { data: unknown; name: string } {
4848
const event = new BorshEventCoder(idl).decode(rawEvent);
4949
if (!event) throw new Error(`Malformed rawEvent for IDL ${idl.address}: ${rawEvent}`);
5050
return {
51-
name: getEventName(event.name),
51+
name: event.name,
5252
data: parseEventData(event.data),
5353
};
5454
}

src/clients/SpokePoolClient/SVMSpokePoolClient.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ import { Address, Rpc, RpcTransport, SolanaRpcApiFromTransport } from "@solana/k
22
import winston from "winston";
33
import {
44
SVMEventNames,
5-
SvmSpokeEventsClient,
65
unwrapEventData,
76
getFillDeadline,
87
getTimestampForSlot,
98
getStatePda,
9+
SvmCpiEventsClient,
1010
} from "../../arch/svm";
1111
import { FillStatus, RelayData, SortableEvent } from "../../interfaces";
1212
import {
@@ -34,9 +34,9 @@ export class SvmSpokePoolClient extends SpokePoolClient {
3434
chainId: number,
3535
deploymentSlot: bigint, // Using slot instead of block number for SVM
3636
eventSearchConfig: MakeOptional<EventSearchConfig, "to">,
37+
protected svmEventsClient: SvmCpiEventsClient,
3738
protected programId: Address,
3839
protected statePda: Address,
39-
protected svmEventsClient: SvmSpokeEventsClient,
4040
protected rpc: Rpc<SolanaRpcApiFromTransport<RpcTransport>>
4141
) {
4242
// Convert deploymentSlot to number for base class, might need refinement
@@ -54,18 +54,18 @@ export class SvmSpokePoolClient extends SpokePoolClient {
5454
eventSearchConfig: MakeOptional<EventSearchConfig, "to"> = { from: 0, maxLookBack: 0 }, // Provide default
5555
rpc: Rpc<SolanaRpcApiFromTransport<RpcTransport>>
5656
): Promise<SvmSpokePoolClient> {
57-
const svmEventsClient = await SvmSpokeEventsClient.create(rpc);
58-
const programId = svmEventsClient.getSvmSpokeAddress();
57+
const svmEventsClient = await SvmCpiEventsClient.create(rpc);
58+
const programId = svmEventsClient.getProgramAddress();
5959
const statePda = await getStatePda(programId);
6060
return new SvmSpokePoolClient(
6161
logger,
6262
hubPoolClient,
6363
chainId,
6464
deploymentSlot,
6565
eventSearchConfig,
66+
svmEventsClient,
6667
programId,
6768
statePda,
68-
svmEventsClient,
6969
rpc
7070
);
7171
}
@@ -107,7 +107,7 @@ export class SvmSpokePoolClient extends SpokePoolClient {
107107
return _searchConfig as EventSearchConfig;
108108
});
109109

110-
const spokePoolAddress = this.svmEventsClient.getSvmSpokeAddress();
110+
const spokePoolAddress = this.svmEventsClient.getProgramAddress();
111111

112112
this.log("debug", `Updating SpokePool client for chain ${this.chainId}`, {
113113
eventsToQuery,

0 commit comments

Comments
 (0)