-
Notifications
You must be signed in to change notification settings - Fork 18
/
Copy pathutils.ts
83 lines (72 loc) · 2.62 KB
/
utils.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
import { BN, BorshEventCoder, Idl } from "@coral-xyz/anchor";
import web3, { address, getProgramDerivedAddress, getU64Encoder, Address, RpcTransport } from "@solana/kit";
import { EventName, EventData, SVMEventNames } from "./types";
/**
* Helper to determine if the current RPC network is devnet.
*/
export async function isDevnet(rpc: web3.Rpc<web3.SolanaRpcApiFromTransport<RpcTransport>>): Promise<boolean> {
const genesisHash = await rpc.getGenesisHash().send();
return genesisHash === "EtWTRABZaYq6iMfeYKouRu166VU2xqa1wcaWoxPkrZBG";
}
/**
* Parses event data from a transaction.
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function parseEventData(eventData: any): any {
if (!eventData) return eventData;
if (Array.isArray(eventData)) {
return eventData.map(parseEventData);
}
if (typeof eventData === "object") {
if (eventData.constructor.name === "PublicKey") {
return address(eventData.toString());
}
if (BN.isBN(eventData)) {
return BigInt(eventData.toString());
}
// Convert each key from snake_case to camelCase and process the value recursively.
return Object.fromEntries(
Object.entries(eventData).map(([key, value]) => [snakeToCamel(key), parseEventData(value)])
);
}
return eventData;
}
/**
* Decodes a raw event according to a supplied IDL.
*/
export function decodeEvent(idl: Idl, rawEvent: string): { data: EventData; name: EventName } {
const event = new BorshEventCoder(idl).decode(rawEvent);
if (!event) throw new Error(`Malformed rawEvent for IDL ${idl.address}: ${rawEvent}`);
return {
name: getEventName(event.name),
data: parseEventData(event.data),
};
}
/**
* Converts a snake_case string to camelCase.
*/
function snakeToCamel(s: string): string {
return s.replace(/(_\w)/g, (match) => match[1].toUpperCase());
}
/**
* Gets the event name from a raw name.
*/
export function getEventName(rawName: string): EventName {
if (Object.values(SVMEventNames).some((name) => rawName.includes(name))) return rawName as EventName;
throw new Error(`Unknown event name: ${rawName}`);
}
/**
* Returns the PDA for the State account.
* @param programId The SpokePool program ID.
* @param extraSeed An optional extra seed. Defaults to 0.
* @returns The PDA for the State account.
*/
export async function getStatePda(programId: string, extraSeed = 0): Promise<Address> {
const seedEncoder = getU64Encoder();
const encodedExtraSeed = seedEncoder.encode(extraSeed);
const [statePda] = await getProgramDerivedAddress({
programAddress: address(programId),
seeds: ["state", encodedExtraSeed],
});
return statePda;
}