From fdc187163e9bb816d297a743d1a252ba60978ca8 Mon Sep 17 00:00:00 2001 From: baryon2 Date: Tue, 5 Sep 2023 23:41:28 +0200 Subject: [PATCH] Fixes 1. Return unparsed msg and public key in base64 format 2. Return correct public key --- package.json | 4 ++- src/codec.ts | 2 +- src/decoder.ts | 66 ++++++++++++++++++++++++++++++++++++++---------- src/sign-mode.ts | 25 ++++++++++++++++++ src/util.ts | 12 +++++---- yarn.lock | 13 ++++++++++ 6 files changed, 102 insertions(+), 20 deletions(-) create mode 100644 src/sign-mode.ts diff --git a/package.json b/package.json index fb4ff09..953acaa 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@leapwallet/buffer-boba", "description": "Buffer Boba is a library for decoding protocol buffers in the cosmos ecosystem.", - "version": "0.1.4", + "version": "0.1.5", "repository": "https://github.com/leapwallet/buffer-boba", "author": "Leap Wallet", "license": "MIT", @@ -47,6 +47,8 @@ }, "dependencies": { "@cosmjs/proto-signing": "0.30.1", + "base64js": "1.0.1", + "cosmjs-types": "0.8.0", "long": "5.2.0", "osmojs": "15.2.1", "protobufjs": "7.2.3", diff --git a/src/codec.ts b/src/codec.ts index a54c8f3..708d70c 100644 --- a/src/codec.ts +++ b/src/codec.ts @@ -50,7 +50,7 @@ export class ProtoCodec { return { ...any, - unpacked, + unpacked: { typeUrl: any.typeUrl, ...unpacked }, factory } } diff --git a/src/decoder.ts b/src/decoder.ts index a63b774..01bf7ea 100644 --- a/src/decoder.ts +++ b/src/decoder.ts @@ -1,4 +1,8 @@ -import { cosmos } from 'osmojs' +import { + TxBody as _TxBody, + AuthInfo as _AuthInfo, + SignDoc as _SignDoc +} from 'cosmjs-types/cosmos/tx/v1beta1/tx' import { AnyWithUnpacked, ProtoCodec, @@ -6,10 +10,12 @@ import { defaultProtoCodec } from './codec' import { decodeSignDoc } from './util' +import * as base64js from 'base64-js' +import { SIGN_MODES, SignMode } from './sign-mode' -export type TxBody = ReturnType -export type AuthInfo = ReturnType -export type SignDoc = ReturnType +export type TxBody = ReturnType +export type AuthInfo = ReturnType +export type SignDoc = ReturnType /** * @@ -29,21 +35,31 @@ export class DirectSignDocDecoder { public readonly signDoc: SignDoc, private readonly protoCodec: ProtoCodec = defaultProtoCodec ) { - this._txBody = cosmos.tx.v1beta1.TxBody.decode(this.signDoc.bodyBytes) - this._authInfo = cosmos.tx.v1beta1.AuthInfo.decode( - this.signDoc.authInfoBytes - ) + this._txBody = _TxBody.decode(this.signDoc.bodyBytes) + this._authInfo = _AuthInfo.decode(this.signDoc.authInfoBytes) } get txBody(): TxBody { + if (!this._txBody) { + this._txBody = _TxBody.decode(this.signDoc.bodyBytes) + } return this._txBody } get txMsgs(): AnyWithUnpacked[] { - return this.txBody.messages.map((msg) => this.protoCodec.unpackAny(msg)) + const msgs: AnyWithUnpacked[] = [] + for (const msg of this.txBody.messages) { + msgs.push(this.protoCodec.unpackAny(msg)) + } + + return msgs + //return this.txBody.messages.map((msg) => this.protoCodec.unpackAny(msg)) } get authInfo(): AuthInfo { + if (!this._authInfo) { + this._authInfo = _AuthInfo.decode(this.signDoc.authInfoBytes) + } return this._authInfo } @@ -56,7 +72,7 @@ export class DirectSignDocDecoder { } toBytes(): Uint8Array { - return cosmos.tx.v1beta1.SignDoc.encode(this.signDoc).finish() + return _SignDoc.encode(this.signDoc).finish() } toJSON(): { @@ -67,18 +83,42 @@ export class DirectSignDocDecoder { } { return { txBody: { - ...this.txBody, + ...(_TxBody.toJSON(this.txBody) as any), messages: this.txMsgs.map((msg) => { if (msg instanceof UnknownMessage) { return msg.toJSON() } if ('factory' in msg) { - return msg.factory.toJSON(msg.unpacked) + const json = msg.factory.toJSON(msg.unpacked) + if (json.msg instanceof Uint8Array) { + json.msg = base64js.fromByteArray(json.msg) + } + + return json } return msg }) }, - authInfo: this.authInfo, + authInfo: { + ...this.authInfo, + signerInfos: this.authInfo.signerInfos.map((si) => { + return { + ...si, + modeInfo: { + single: { + mode: SIGN_MODES[si.modeInfo?.single?.mode as SignMode] + } + }, + + publicKey: { + ...si.publicKey, + value: base64js.fromByteArray( + si.publicKey?.value.slice(2) ?? new Uint8Array() + ) + } + } + }) + }, chainId: this.chainId, accountNumber: this.accountNumber } diff --git a/src/sign-mode.ts b/src/sign-mode.ts new file mode 100644 index 0000000..e263a10 --- /dev/null +++ b/src/sign-mode.ts @@ -0,0 +1,25 @@ +export enum SignMode { + // SIGN_MODE_UNSPECIFIED specifies an unknown signing mode and will be + // rejected + SIGN_MODE_UNSPECIFIED = 0, + + // SIGN_MODE_DIRECT specifies a signing mode which uses SignDoc and is + // verified with raw bytes from Tx + SIGN_MODE_DIRECT = 1, + + // SIGN_MODE_TEXTUAL is a future signing mode that will verify some + // human-readable textual representation on top of the binary representation + // from SIGN_MODE_DIRECT + SIGN_MODE_TEXTUAL = 2, + + // SIGN_MODE_LEGACY_AMINO_JSON is a backwards compatibility mode which uses + // Amino JSON and will be removed in the future + SIGN_MODE_LEGACY_AMINO_JSON = 127 +} + +export const SIGN_MODES = { + [SignMode.SIGN_MODE_UNSPECIFIED]: 'SIGN_MODE_UNSPECIFIED', + [SignMode.SIGN_MODE_DIRECT]: 'SIGN_MODE_DIRECT', + [SignMode.SIGN_MODE_TEXTUAL]: 'SIGN_MODE_TEXTUAL', + [SignMode.SIGN_MODE_LEGACY_AMINO_JSON]: 'SIGN_MODE_LEGACY_AMINO_JSON' +} diff --git a/src/util.ts b/src/util.ts index dcf4151..898f2cd 100644 --- a/src/util.ts +++ b/src/util.ts @@ -17,21 +17,23 @@ export const convertObjectCasingFromCamelToSnake = ( const msgKeys = Object.keys(record) const convertedMsg = msgKeys.reduce((acc, key) => { const convertedKey = convertCamelCaseToSnakeCase(key) - const value = record[key] - if(value instanceof Date){ + const value = record[key] + if (value instanceof Date) { return { ...acc, [convertedKey]: value } } - if(Array.isArray(value)){ + if (Array.isArray(value)) { return { ...acc, - [convertedKey]: value.map(element => convertObjectCasingFromCamelToSnake(element)) + [convertedKey]: value.map((element) => + convertObjectCasingFromCamelToSnake(element) + ) } } - if (typeof value === 'object' && value !== null) { + if (typeof value === 'object' && value !== null) { return { ...acc, [convertedKey]: convertObjectCasingFromCamelToSnake(value) diff --git a/yarn.lock b/yarn.lock index 207d8fc..822039e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -966,6 +966,11 @@ base64-js@^1.3.0: resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== +base64js@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/base64js/-/base64js-1.0.1.tgz#1093cea0dc68731fff6bd247641048b95e20dff6" + integrity sha512-jxGN7DS7e+HHO5u+UT9NzK2BMKJByQPmmdXyvad7TN0mPKGC4kRMTnnV7g7HqhLlW51AFmtbRM4IDGxysBYuVg== + bech32@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" @@ -1162,6 +1167,14 @@ cosmjs-types@^0.7.1: long "^4.0.0" protobufjs "~6.11.2" +cosmjs-types@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/cosmjs-types/-/cosmjs-types-0.8.0.tgz#2ed78f3e990f770229726f95f3ef5bf9e2b6859b" + integrity sha512-Q2Mj95Fl0PYMWEhA2LuGEIhipF7mQwd9gTQ85DdP9jjjopeoGaDxvmPa5nakNzsq7FnO1DMTatXTAx6bxMH7Lg== + dependencies: + long "^4.0.0" + protobufjs "~6.11.2" + cross-spawn@^6.0.5: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"