Skip to content

Instantly share code, notes, and snippets.

@heyitsarpit
Created June 19, 2025 16:05
Show Gist options
  • Save heyitsarpit/c49201e4b42a0cd798b8a592dfd2dc75 to your computer and use it in GitHub Desktop.
Save heyitsarpit/c49201e4b42a0cd798b8a592dfd2dc75 to your computer and use it in GitHub Desktop.
solana intent event parsing
// src/intentEventParser.ts
import { Connection, PublicKey } from '@solana/web3.js';
/* -------------------------------------------------------------------------- */
/* Types & helpers */
/* -------------------------------------------------------------------------- */
export interface ParsedIntentEvent {
intentId: string;
messageId: string;
initiator: string;
receiver: string;
inputAsset: string;
outputAsset: string;
normalizedAmount: bigint;
maxFee: number;
originDomain: number;
nonce: bigint;
ttl: bigint;
timestamp: bigint;
destinationCount: number;
destinations: number[];
data: string; // 0x-prefixed
}
/** Reverse little-endian hex -> big-endian hex (deadbeef ➜ efbeadde). */
const reverseBytes = (hex: string) => hex.match(/.{2}/g)!.reverse().join('');
const leHexToBigInt = (hex: string) => BigInt('0x' + reverseBytes(hex));
const leHexToNumber = (hex: string) => Number(leHexToBigInt(hex));
const strip0x = (h: string) => h.replace(/^0x/i, '').toLowerCase();
/* Slice helper that advances an internal cursor. Starts after 32-byte discriminator. */
const slicer = (hex: string) => {
let offset = 64;
return (chars: number) => {
const part = hex.slice(offset, offset + chars);
offset += chars;
return part;
};
};
/* -------------------------------------------------------------------------- */
/* Pure parsing function */
/* -------------------------------------------------------------------------- */
export function parseIntentEvent(hexData: string): ParsedIntentEvent {
const raw = strip0x(hexData);
const next = slicer(raw);
const intentId = '0x' + next(64);
const messageId = '0x' + next(64);
const initiator = '0x' + next(64);
const receiver = '0x' + next(64);
const inputAsset = '0x' + next(64);
const outputAsset = '0x' + next(64);
const normalizedAmount = leHexToBigInt(next(32));
const maxFee = leHexToNumber(next(8));
const originDomain = leHexToNumber(next(8));
const nonce = leHexToBigInt(next(16));
const ttl = leHexToBigInt(next(16));
const timestamp = leHexToBigInt(next(16));
const destinationCount = leHexToNumber(next(8));
const destinations: number[] = [];
for (let i = 0; i < destinationCount; i++) {
destinations.push(leHexToNumber(next(8)));
}
const dataLength = leHexToNumber(next(8));
const data = '0x' + next(dataLength);
return {
intentId,
messageId,
initiator,
receiver,
inputAsset,
outputAsset,
normalizedAmount,
maxFee,
originDomain,
nonce,
ttl,
timestamp,
destinationCount,
destinations,
data,
};
}
/* -------------------------------------------------------------------------- */
/* Fetch-and-parse convenience helper */
/* -------------------------------------------------------------------------- */
/**
* Fetches a Solana transaction, extracts all Anchor `emit!` blobs from the
* program logs of `programId`, parses them, and returns an array of events.
*/
export async function fetchParsedIntentEvents(
connection: Connection,
txSignature: string,
programId: PublicKey,
): Promise<ParsedIntentEvent[]> {
const tx = await connection.getTransaction(txSignature, {
maxSupportedTransactionVersion: 0,
commitment: 'confirmed',
});
if (!tx) return [];
// Anchor encodes events as base64 after the prefix `Program data: `
const EV_PREFIX = 'Program data: ';
const blobs = tx.meta?.logMessages
?.filter((l) => l.startsWith(EV_PREFIX) && l.includes(programId.toBase58()))
.map((l) => l.slice(EV_PREFIX.length).trim()) ?? [];
return blobs.map((b64) => {
const hex = Buffer.from(b64, 'base64').toString('hex');
return parseIntentEvent(hex);
});
}
/* -------------------------------------------------------------------------- */
/* Example usage */
/* -------------------------------------------------------------------------- */
/*
import { Connection, PublicKey } from '@solana/web3.js';
(async () => {
const connection = new Connection('https://api.mainnet-beta.solana.com');
const PROGRAM_ID = new PublicKey('YourProgram111111111111111111111111111111111');
const SIG = '5cD3…<tx signature>';
const events = await fetchParsedIntentEvents(connection, SIG, PROGRAM_ID);
console.log(events);
})();
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment