From 24b723e1e1be1bed69725502b306bf35c819e1ec Mon Sep 17 00:00:00 2001 From: Armani Ferrante Date: Thu, 20 May 2021 02:28:27 -0700 Subject: [PATCH] ts: Event decode api updates (#292) --- CHANGELOG.md | 2 ++ ts/src/coder.ts | 33 +++++++++++++++++++++------- ts/src/program/event.ts | 27 +++-------------------- ts/src/program/index.ts | 6 +---- ts/src/program/namespace/simulate.ts | 2 +- 5 files changed, 32 insertions(+), 38 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f743cd2a4..ec4bdf4da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,8 @@ incremented for features. ## Breaking Changes +* ts: Event coder `decode` API changed to decode strings directly instead of buffers ([#292](https://github.com/project-serum/anchor/pull/292)). +* ts: Event coder `encode` API removed ([#292](https://github.com/project-serum/anchor/pull/292)). * ts: Replace deprecated `web3.Account` with `web3.Signer` in public APIs ([#296](https://github.com/project-serum/anchor/pull/296)). ## [0.5.0] - 2021-05-07 diff --git a/ts/src/coder.ts b/ts/src/coder.ts index 4c244c017..00d4a43d7 100644 --- a/ts/src/coder.ts +++ b/ts/src/coder.ts @@ -1,4 +1,5 @@ import camelCase from "camelcase"; +import * as base64 from "base64-js"; import { snakeCase } from "snake-case"; import { Layout } from "buffer-layout"; import * as sha256 from "js-sha256"; @@ -213,6 +214,11 @@ class EventCoder { */ private layouts: Map; + /** + * Maps base64 encoded event discriminator to event name. + */ + private discriminators: Map; + public constructor(idl: Idl) { if (idl.events === undefined) { this.layouts = new Map(); @@ -232,18 +238,29 @@ class EventCoder { }); // @ts-ignore this.layouts = new Map(layouts); + + this.discriminators = new Map( + idl.events === undefined + ? [] + : idl.events.map((e) => [ + base64.fromByteArray(eventDiscriminator(e.name)), + e.name, + ]) + ); } - public encode(eventName: string, account: T): Buffer { - const buffer = Buffer.alloc(1000); // TODO: use a tighter buffer. - const layout = this.layouts.get(eventName); - const len = layout.encode(account, buffer); - return buffer.slice(0, len); - } + public decode(log: string): T | null { + const logArr = Buffer.from(base64.toByteArray(log)); + const disc = base64.fromByteArray(logArr.slice(0, 8)); + + // Only deserialize if the discriminator implies a proper event. + const eventName = this.discriminators.get(disc); + if (eventName === undefined) { + return undefined; + } - public decode(eventName: string, ix: Buffer): T { const layout = this.layouts.get(eventName); - return layout.decode(ix); + return layout.decode(logArr.slice(8)); } } diff --git a/ts/src/program/event.ts b/ts/src/program/event.ts index d1dbba5cc..0c8639d5e 100644 --- a/ts/src/program/event.ts +++ b/ts/src/program/event.ts @@ -1,8 +1,7 @@ import { PublicKey } from "@solana/web3.js"; import * as base64 from "base64-js"; import * as assert from "assert"; -import Coder, { eventDiscriminator } from "../coder"; -import { Idl } from "../idl"; +import Coder from "../coder"; const LOG_START_INDEX = "Program log: ".length; @@ -15,20 +14,10 @@ export type Event = { export class EventParser { private coder: Coder; private programId: PublicKey; - // Maps base64 encoded event discriminator to event name. - private discriminators: Map; - constructor(coder: Coder, programId: PublicKey, idl: Idl) { + constructor(coder: Coder, programId: PublicKey) { this.coder = coder; this.programId = programId; - this.discriminators = new Map( - idl.events === undefined - ? [] - : idl.events.map((e) => [ - base64.fromByteArray(eventDiscriminator(e.name)), - e.name, - ]) - ); } // Each log given, represents an array of messages emitted by @@ -88,17 +77,7 @@ export class EventParser { // This is a `msg!` log. if (log.startsWith("Program log:")) { const logStr = log.slice(LOG_START_INDEX); - const logArr = Buffer.from(base64.toByteArray(logStr)); - const disc = base64.fromByteArray(logArr.slice(0, 8)); - // Only deserialize if the discriminator implies a proper event. - let event = null; - let eventName = this.discriminators.get(disc); - if (eventName !== undefined) { - event = { - name: eventName, - data: this.coder.events.decode(eventName, logArr.slice(8)), - }; - } + const event = this.coder.events.decode(logStr); return [event, null, false]; } // System log. diff --git a/ts/src/program/index.ts b/ts/src/program/index.ts index 058fe69c1..711131a05 100644 --- a/ts/src/program/index.ts +++ b/ts/src/program/index.ts @@ -301,11 +301,7 @@ export class Program { eventName: string, callback: (event: any, slot: number) => void ): number { - const eventParser = new EventParser( - this._coder, - this._programId, - this._idl - ); + const eventParser = new EventParser(this._coder, this._programId); return this._provider.connection.onLogs(this._programId, (logs, ctx) => { if (logs.err) { console.error(logs); diff --git a/ts/src/program/namespace/simulate.ts b/ts/src/program/namespace/simulate.ts index 20312da32..2d3416d91 100644 --- a/ts/src/program/namespace/simulate.ts +++ b/ts/src/program/namespace/simulate.ts @@ -63,7 +63,7 @@ export default class SimulateFactory { const events = []; if (idl.events) { - let parser = new EventParser(coder, programId, idl); + let parser = new EventParser(coder, programId); parser.parseLogs(logs, (event) => { events.push(event); });