From dae08b2d7a0f7de0c0f1469ee25474ef8cbc5e56 Mon Sep 17 00:00:00 2001 From: Kirill Fomichev Date: Tue, 3 Dec 2024 13:04:34 -0500 Subject: [PATCH] nodejs: add parse err function (#483) Co-authored-by: Dmitry Rybalchenko <108054435+dm-rybalchenko@users.noreply.github.com> --- CHANGELOG.md | 1 + Cargo.toml | 2 +- Makefile | 1 + examples/typescript/package-lock.json | 2 +- examples/typescript/src/client.ts | 28 +++++++++++++++---- .../package-lock.json | 26 +++++++++++------ yellowstone-grpc-client-nodejs/package.json | 2 +- .../solana-encoding-wasm/Cargo.lock | 2 +- .../solana-encoding-wasm/Cargo.toml | 2 +- .../solana-encoding-wasm/src/lib.rs | 15 ++++++++-- yellowstone-grpc-client-nodejs/src/index.ts | 19 ++++++++++--- yellowstone-grpc-client-nodejs/src/types.ts | 5 +++- 12 files changed, 80 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e33d301..b7e6c047 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ The minor version will be incremented upon a breaking change and the patch versi ### Features - proto: add tonic feature ([#474](https://github.com/rpcpool/yellowstone-grpc/pull/474)) +- nodejs: add parse err function ([#483](https://github.com/rpcpool/yellowstone-grpc/pull/483)) ### Breaking diff --git a/Cargo.toml b/Cargo.toml index bc3b2795..040ca75f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ members = [ "yellowstone-grpc-proto", # 4.0.0 ] exclude = [ - "yellowstone-grpc-client-nodejs/solana-encoding-wasm", # 1.0.0 + "yellowstone-grpc-client-nodejs/solana-encoding-wasm", # 3.0.0 ] [workspace.package] diff --git a/Makefile b/Makefile index 97a64d4a..a41cc0f6 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,5 @@ clean: clean-nodejs clean-rust + rm -rf test-ledger clean-nodejs: rm -rf examples/typescript/dist diff --git a/examples/typescript/package-lock.json b/examples/typescript/package-lock.json index d93c5fa5..107c085d 100644 --- a/examples/typescript/package-lock.json +++ b/examples/typescript/package-lock.json @@ -19,7 +19,7 @@ }, "../../yellowstone-grpc-client-nodejs": { "name": "@triton-one/yellowstone-grpc", - "version": "1.2.0", + "version": "1.3.0", "license": "Apache-2.0", "dependencies": { "@grpc/grpc-js": "^1.8.0" diff --git a/examples/typescript/src/client.ts b/examples/typescript/src/client.ts index 7068e30c..155c4ce8 100644 --- a/examples/typescript/src/client.ts +++ b/examples/typescript/src/client.ts @@ -1,4 +1,5 @@ import yargs from "yargs"; +import { inspect } from "node:util"; import Client, { CommitmentLevel, SubscribeRequest, @@ -6,6 +7,7 @@ import Client, { SubscribeRequestFilterAccountsFilterLamports, SubscribeUpdateTransactionInfo, txEncode, + txErrDecode, } from "@triton-one/yellowstone-grpc"; async function main() { @@ -85,13 +87,24 @@ async function subscribeCommand(client, args) { // Handle updates stream.on("data", (data) => { - if (data.transaction && args.transactionsParsed) { + if ( + data.transaction && + (args.transactionsParsed || args.transactionsDecodeErr) + ) { const slot = data.transaction.slot; const message = data.transaction.transaction; - const tx = txEncode.encode(message, txEncode.encoding.Json, 255, true); - console.log( - `TX filters: ${data.filters}, slot#${slot}, tx: ${JSON.stringify(tx)}` - ); + if (args.transactionsParsed) { + const tx = txEncode.encode(message, txEncode.encoding.Json, 255, true); + console.log( + `TX filters: ${data.filters}, slot#${slot}, tx: ${JSON.stringify(tx)}` + ); + } + if (message.meta.err && args.transactionsDecodeErr) { + const err = txErrDecode.decode(message.meta.err.err); + console.log( + `TX filters: ${data.filters}, slot#${slot}, err: ${inspect(err)}}` + ); + } return; } @@ -391,6 +404,11 @@ function parseCommandLineArgs() { describe: "parse transaction to json", type: "boolean", }, + "transactions-decode-err": { + default: false, + describe: "decode transactions errors", + type: "boolean", + }, "transactions-status": { default: false, describe: "subscribe on transactionsStatus updates", diff --git a/yellowstone-grpc-client-nodejs/package-lock.json b/yellowstone-grpc-client-nodejs/package-lock.json index 2f26ccac..ddf87547 100644 --- a/yellowstone-grpc-client-nodejs/package-lock.json +++ b/yellowstone-grpc-client-nodejs/package-lock.json @@ -1,12 +1,12 @@ { "name": "@triton-one/yellowstone-grpc", - "version": "1.2.0", + "version": "1.3.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@triton-one/yellowstone-grpc", - "version": "1.2.0", + "version": "1.3.0", "license": "Apache-2.0", "dependencies": { "@grpc/grpc-js": "^1.8.0" @@ -22,16 +22,16 @@ } }, "node_modules/@grpc/grpc-js": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.8.0.tgz", - "integrity": "sha512-ySMTXQuMvvswoobvN+0LsaPf7ITO2JVfJmHxQKI4cGehNrrUms+n81BlHEX7Hl/LExji6XE3fnI9U04GSkRruA==", + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.12.3.tgz", + "integrity": "sha512-iaxAZnANdCwMNpJlyhkI1W1jQZIDZKFNtU2OpQDdgd+pBcU3t7G+PT7svobkW4WSZTdis+CVV6y8KIwu83HDYQ==", "license": "Apache-2.0", "dependencies": { - "@grpc/proto-loader": "^0.7.0", - "@types/node": ">=12.12.47" + "@grpc/proto-loader": "^0.7.13", + "@js-sdsl/ordered-map": "^4.4.2" }, "engines": { - "node": "^8.13.0 || >=10.10.0" + "node": ">=12.10.0" } }, "node_modules/@grpc/proto-loader": { @@ -58,6 +58,16 @@ "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==", "license": "Apache-2.0" }, + "node_modules/@js-sdsl/ordered-map": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz", + "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, "node_modules/@protobufjs/aspromise": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", diff --git a/yellowstone-grpc-client-nodejs/package.json b/yellowstone-grpc-client-nodejs/package.json index f2833120..b9afff84 100644 --- a/yellowstone-grpc-client-nodejs/package.json +++ b/yellowstone-grpc-client-nodejs/package.json @@ -1,6 +1,6 @@ { "name": "@triton-one/yellowstone-grpc", - "version": "1.2.0", + "version": "1.3.0", "license": "Apache-2.0", "author": "Triton One", "description": "Yellowstone gRPC Geyser Node.js Client", diff --git a/yellowstone-grpc-client-nodejs/solana-encoding-wasm/Cargo.lock b/yellowstone-grpc-client-nodejs/solana-encoding-wasm/Cargo.lock index e0ca9859..271f3ab6 100644 --- a/yellowstone-grpc-client-nodejs/solana-encoding-wasm/Cargo.lock +++ b/yellowstone-grpc-client-nodejs/solana-encoding-wasm/Cargo.lock @@ -3273,7 +3273,7 @@ dependencies = [ [[package]] name = "yellowstone-grpc-solana-encoding-wasm" -version = "2.0.0" +version = "3.0.0" dependencies = [ "serde_json", "solana-transaction-status", diff --git a/yellowstone-grpc-client-nodejs/solana-encoding-wasm/Cargo.toml b/yellowstone-grpc-client-nodejs/solana-encoding-wasm/Cargo.toml index 9bdf2828..ada23c27 100644 --- a/yellowstone-grpc-client-nodejs/solana-encoding-wasm/Cargo.toml +++ b/yellowstone-grpc-client-nodejs/solana-encoding-wasm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "yellowstone-grpc-solana-encoding-wasm" -version = "2.0.0" +version = "3.0.0" authors = ["Triton One"] edition = "2021" homepage = "https://triton.one" diff --git a/yellowstone-grpc-client-nodejs/solana-encoding-wasm/src/lib.rs b/yellowstone-grpc-client-nodejs/solana-encoding-wasm/src/lib.rs index 703fa9cd..df3edccb 100644 --- a/yellowstone-grpc-client-nodejs/solana-encoding-wasm/src/lib.rs +++ b/yellowstone-grpc-client-nodejs/solana-encoding-wasm/src/lib.rs @@ -2,7 +2,9 @@ use { solana_transaction_status::{TransactionWithStatusMeta, UiTransactionEncoding}, wasm_bindgen::prelude::*, yellowstone_grpc_proto::{ - convert_from, prelude::SubscribeUpdateTransactionInfo, prost::Message, + convert_from, + prelude::{SubscribeUpdateTransactionInfo, TransactionError as TransactionErrorProto}, + prost::Message, }, }; @@ -29,7 +31,7 @@ impl From for UiTransactionEncoding { } #[wasm_bindgen] -pub fn encode( +pub fn encode_tx( data: &[u8], encoding: WasmUiTransactionEncoding, max_supported_transaction_version: Option, @@ -49,3 +51,12 @@ pub fn encode( Err(JsError::new("tx with missing metadata")) } } + +#[wasm_bindgen] +pub fn decode_tx_error(err: Vec) -> Result { + match convert_from::create_tx_error(Some(&TransactionErrorProto { err })) { + Ok(Some(err)) => serde_json::to_string(&err).map_err(Into::into), + Ok(None) => Err(JsError::new("unexpected")), + Err(error) => Err(JsError::new(error)), + } +} diff --git a/yellowstone-grpc-client-nodejs/src/index.ts b/yellowstone-grpc-client-nodejs/src/index.ts index 5a0421f7..27b385a7 100644 --- a/yellowstone-grpc-client-nodejs/src/index.ts +++ b/yellowstone-grpc-client-nodejs/src/index.ts @@ -57,11 +57,15 @@ export { // Import transaction encoding function created in Rust import * as wasm from "./encoding/yellowstone_grpc_solana_encoding_wasm"; -// Import mapper to get return type based on WasmUiTransactionEncoding -import { MapTransactionEncodingToReturnType } from "./types"; +import type { + TransactionErrorSolana, + // Import mapper to get return type based on WasmUiTransactionEncoding + MapTransactionEncodingToReturnType, +} from "./types"; + export const txEncode = { encoding: wasm.WasmUiTransactionEncoding, - encode_raw: wasm.encode, + encode_raw: wasm.encode_tx, encode: ( message: SubscribeUpdateTransactionInfo, encoding: T, @@ -69,7 +73,7 @@ export const txEncode = { show_rewards: boolean ): MapTransactionEncodingToReturnType[T] => { return JSON.parse( - wasm.encode( + wasm.encode_tx( SubscribeUpdateTransactionInfo.encode(message).finish(), encoding, max_supported_transaction_version, @@ -79,6 +83,13 @@ export const txEncode = { }, }; +export const txErrDecode = { + decode_raw: wasm.decode_tx_error, + decode: (buf: Uint8Array): TransactionErrorSolana => { + return JSON.parse(wasm.decode_tx_error(buf)); + }, +}; + export default class Client { _client: GeyserClient; _insecureXToken: string | undefined; diff --git a/yellowstone-grpc-client-nodejs/src/types.ts b/yellowstone-grpc-client-nodejs/src/types.ts index 520780f2..452d7d8b 100644 --- a/yellowstone-grpc-client-nodejs/src/types.ts +++ b/yellowstone-grpc-client-nodejs/src/types.ts @@ -1,5 +1,6 @@ import { type GetTransactionApi } from "@solana/rpc-api"; -import { type Signature } from "@solana/keys/dist/types"; +import { type Signature } from "@solana/keys"; +import { type TransactionError } from "@solana/rpc-types"; const fakeGetTransition: GetTransactionApi["getTransaction"] = ( signature, @@ -20,3 +21,5 @@ export type MapTransactionEncodingToReturnType = { 3: typeof json; 4: typeof jsonParsed; }; + +export type TransactionErrorSolana = TransactionError;