Skip to content

Commit

Permalink
ts: CPI events parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
ochaloup committed Apr 3, 2024
1 parent c138a55 commit 44b3bd6
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 0 deletions.
35 changes: 35 additions & 0 deletions ts/packages/anchor/src/coder/borsh/event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,19 @@ import * as base64 from "../../utils/bytes/base64.js";
import { Idl } from "../../idl.js";
import { IdlCoder } from "./idl.js";
import { EventCoder } from "../index.js";
import BN from "bn.js";
import { PublicKey } from "@solana/web3.js";
import { decode as bs58Decode } from "../../utils/bytes/bs58.js";

export class BorshEventCoder implements EventCoder {
/**
* CPI event discriminator.
* https://github.com/coral-xyz/anchor/blob/v0.29.0/lang/src/event.rs
*/
private static eventIxTag: BN = new BN("1d9acb512ea545e4", "hex");

private address: string;

/**
* Maps account type identifier to a layout.
*/
Expand Down Expand Up @@ -42,6 +53,8 @@ export class BorshEventCoder implements EventCoder {
ev.name,
])
);

this.address = idl.address;
}

public decode(log: string): {
Expand Down Expand Up @@ -70,4 +83,26 @@ export class BorshEventCoder implements EventCoder {
const data = layout.decode(logArr.slice(8));
return { data, name: eventName };
}

get idlAddress(): PublicKey {
return new PublicKey(this.address);
}

public static isCPIEventData(buffer: Buffer): boolean {
return buffer
.subarray(0, 8)
.equals(BorshEventCoder.eventIxTag.toBuffer("le"));
}

public decodeCpi(ixInputData: string): {
name: string;
data: any;
} | null {
const ixInputBufferData = bs58Decode(ixInputData);
if (BorshEventCoder.isCPIEventData(ixInputBufferData)) {
const eventData = base64.encode(ixInputBufferData.subarray(8));
return this.decode(eventData);
}
return null;
}
}
36 changes: 36 additions & 0 deletions ts/packages/anchor/src/utils/events.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import {
CompiledInnerInstruction,
VersionedTransactionResponse,
} from "@solana/web3.js";
import { BorshEventCoder } from "src/coder";
import { Idl } from "src/idl";
import { IdlEvents } from "src/program";

// https://github.com/coral-xyz/anchor/blob/v0.29.0/tests/events/tests/events.ts#L61-L62
export function parseCpiEvents(
eventDecoder: BorshEventCoder,
transactionResponse: VersionedTransactionResponse
): { name: string; data: any }[] {
const events: { name: string; data: any }[] = [];
const inner: CompiledInnerInstruction[] =
transactionResponse?.meta?.innerInstructions ?? [];
const idlProgramId = eventDecoder.idlAddress;
for (let i = 0; i < inner.length; i++) {
for (let j = 0; j < inner[i].instructions.length; j++) {
const ix = inner[i].instructions[j];
const programPubkey =
transactionResponse?.transaction.message.staticAccountKeys[
ix.programIdIndex
];
if (programPubkey === undefined || !programPubkey.equals(idlProgramId)) {
// we are at instructions that does not match the linked program
continue;
}
const event = eventDecoder.decodeCpi(ix.data);
if (event) {
events.push(event);
}
}
}
return events;
}
1 change: 1 addition & 0 deletions ts/packages/anchor/src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ export * as bytes from "./bytes/index.js";
export * as token from "./token.js";
export * as features from "./features.js";
export * as registry from "./registry.js";
export * as events from "./events.js";

0 comments on commit 44b3bd6

Please sign in to comment.