/anchores

Minimal library for parsing Solana transaction, instructions and events

Primary LanguageTypeScriptMIT LicenseMIT

AnchorES

Minimal library for parsing Solana transaction, instructions and events.

  • Tree-shakeable: 9.72 kB -> 4.08 kB (gzip) to parse Jupiter Swap Events
  • ESM and commonjs
  • No IDL, structs defined in code
  • Typescript friendly
  • Minimal dependencies

Warning

This is still a work in progress. Support for all Borsh types is not yet implemented, and the API is subject to change.

Install

npm i anchores

Parsing Jupiter Swap Transactions

We export a parseTransaction function that takes a program id, a list of instruction and event parsers, and the transaction to parse.

import { parseTransaction } from "anchores";
import { JUPITER_V6_PROGRAM_ID, SwapEvent } from "anchores/parsers/jupiter";

const tx = await connection.getParsedTransaction("txhash");
const events = parseTransaction(
  JUPITER_V6_PROGRAM_ID,
  {
    events: [SwapEvent],
  },
  tx,
);

See tests for other usage examples.

Declaring your own parser

You can also declare your own parsers. Here is an example of a parser for the Jupiter Swap Event:

import * as b from "anchores/binary";

export function parseSwapEvent(data: Uint8Array) {
  const reader = b.createReader(data);
  return {
    amm: b.publicKey(reader),
    inputMint: b.publicKey(reader),
    inputAmount: b.u64(reader),
    outputMint: b.publicKey(reader),
    outputAmount: b.u64(reader),
  };
}
export type ParsedSwapEvent = ReturnType<typeof parseSwapEvent>;

You can use this function directly or form a parser object to pass to parseTransaction, decodeEvents, decodeStructs.

import { createSighash } from "anchores/anchor";

export const SwapEvent = {
  name: "SwapEvent" as const,
  discriminator: createSighash("event", "SwapEvent"),
  // declared above
  parse: parseSwapEvent,
};

// Usage
const events = parseTransaction(
  PROGRAM_ID,
  {
    events: [SwapEvent],
  },
  tx,
);
// or
const structs = tx.meta.innerInstructions.flatMap((inner) =>
  inner.instructions.filter(isJupiterInstruction).map((ix) => {
    const ixData = base58.decode(ix.data);
    const instruct = decodeStructs([SwapInstruction], ixData);
    if (instruct) {
      return instruct;
    }

    const event = decodeEvents([SwapEvent], ixData);
    return event;
  }),
);