From d64bdd6e3529ee66720034194e08ec0d63cbee37 Mon Sep 17 00:00:00 2001 From: Lucas Assmann Date: Thu, 1 Jul 2021 17:48:24 -0300 Subject: [PATCH 1/9] Fix: Cast hexadecimal literals to BigInt to be compatible with React Native applications on android (#392) * Fix: Cast hexadecimal literals to BigInt to be compatible with React Native applications on android * remove n from hexa becaus it's redundand with BigInt --- src/encoding/uint64.ts | 2 +- src/transaction.ts | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/encoding/uint64.ts b/src/encoding/uint64.ts index d64f7d714..81e894630 100644 --- a/src/encoding/uint64.ts +++ b/src/encoding/uint64.ts @@ -8,7 +8,7 @@ export function encodeUint64(num: number | bigint) { const isInteger = typeof num === 'bigint' || Number.isInteger(num); - if (!isInteger || num < 0 || num > 0xffffffffffffffffn) { + if (!isInteger || num < 0 || num > BigInt('0xffffffffffffffff')) { throw new Error('Input is not a 64-bit unsigned integer'); } diff --git a/src/transaction.ts b/src/transaction.ts index c52b89ff6..f850e9b08 100644 --- a/src/transaction.ts +++ b/src/transaction.ts @@ -244,7 +244,8 @@ export class Transaction implements TransactionStorageStructure { txn.amount !== undefined && (!( Number.isSafeInteger(txn.amount) || - (typeof txn.amount === 'bigint' && txn.amount <= 0xffffffffffffffffn) + (typeof txn.amount === 'bigint' && + txn.amount <= BigInt('0xffffffffffffffff')) ) || txn.amount < 0) ) @@ -267,7 +268,7 @@ export class Transaction implements TransactionStorageStructure { (!( Number.isSafeInteger(txn.assetTotal) || (typeof txn.assetTotal === 'bigint' && - txn.assetTotal <= 0xffffffffffffffffn) + txn.assetTotal <= BigInt('0xffffffffffffffff')) ) || txn.assetTotal < 0) ) From 9e2997006d0e237641710e2ae1849c535f4b1b58 Mon Sep 17 00:00:00 2001 From: Jacob Daitzman Date: Wed, 7 Jul 2021 17:32:35 -0400 Subject: [PATCH 2/9] Support transactions with a first round of zero (#397) --- .eslintrc.js | 4 ++++ src/client/client.ts | 2 -- src/encoding/uint64.ts | 2 -- src/makeTxn.ts | 6 ------ src/multisig.ts | 4 ++-- src/transaction.ts | 6 ++++++ tests/5.Transaction.js | 24 ++++++++++++++++++++++++ tests/6.Multisig.js | 8 ++++---- tests/cucumber/steps/steps.js | 2 +- 9 files changed, 41 insertions(+), 17 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 322622404..526720baa 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -28,6 +28,10 @@ module.exports = { 'always', { exceptAfterSingleLine: true }, ], + 'no-unused-vars': 'off', + '@typescript-eslint/no-unused-vars': ['error'], + 'no-redeclare': 'off', + '@typescript-eslint/no-redeclare': ['error'], }, overrides: [ { diff --git a/src/client/client.ts b/src/client/client.ts index 8598664c3..20f267ddf 100644 --- a/src/client/client.ts +++ b/src/client/client.ts @@ -70,11 +70,9 @@ type Query = { * requested format. * @param query */ -/* eslint-disable no-redeclare,no-unused-vars */ function getAcceptFormat( query?: Query<'msgpack' | 'json'> ): 'application/msgpack' | 'application/json' { - /* eslint-enable no-redeclare,no-unused-vars */ if ( query !== undefined && Object.prototype.hasOwnProperty.call(query, 'format') diff --git a/src/encoding/uint64.ts b/src/encoding/uint64.ts index 81e894630..3dc6e1a2e 100644 --- a/src/encoding/uint64.ts +++ b/src/encoding/uint64.ts @@ -37,7 +37,6 @@ export function encodeUint64(num: number | bigint) { * @returns The integer that was encoded in the input data. The return type will * be determined by the parameter decodingMode. */ -/* eslint-disable no-unused-vars,no-redeclare */ export function decodeUint64(data: Uint8Array, decodingMode: 'safe'): number; export function decodeUint64( data: Uint8Array, @@ -45,7 +44,6 @@ export function decodeUint64( ): number | bigint; export function decodeUint64(data: Uint8Array, decodingMode: 'bigint'): bigint; export function decodeUint64(data: any, decodingMode: any = 'safe') { - /* eslint-enable no-unused-vars,no-redeclare */ if ( decodingMode !== 'safe' && decodingMode !== 'mixed' && diff --git a/src/makeTxn.ts b/src/makeTxn.ts index 07ccce74f..459201667 100644 --- a/src/makeTxn.ts +++ b/src/makeTxn.ts @@ -158,7 +158,6 @@ export function makePaymentTxnWithSuggestedParamsFromObject( * @param nonParticipation - configure whether the address wants to stop participating. If true, * voteKey, selectionKey, voteFirst, voteLast, and voteKeyDilution must be undefined. */ -/* eslint-disable no-unused-vars,no-redeclare */ export function makeKeyRegistrationTxnWithSuggestedParams( from: KeyRegistrationTxn['from'], note: KeyRegistrationTxn['note'], @@ -195,7 +194,6 @@ export function makeKeyRegistrationTxnWithSuggestedParams( rekeyTo?: any, nonParticipation = false ) { - /* eslint-enable no-unused-vars,no-redeclare */ const o: KeyRegistrationTxn = { from, note, @@ -234,7 +232,6 @@ export function makeKeyRegistrationTxnWithSuggestedParams( * voteKey, selectionKey, voteFirst, voteLast, and voteKeyDilution must be undefined. * @Deprecated in version 2.0 this will change to use the "WithSuggestedParams" signature. */ -/* eslint-disable no-unused-vars,no-redeclare */ export function makeKeyRegistrationTxn( from: KeyRegistrationTxn['from'], fee: MustHaveSuggestedParamsInline['fee'], @@ -283,7 +280,6 @@ export function makeKeyRegistrationTxn( rekeyTo?: any, nonParticipation: any = false ) { - /* eslint-enable no-unused-vars,no-redeclare */ const suggestedParams: SuggestedParams = { genesisHash, genesisID, @@ -306,7 +302,6 @@ export function makeKeyRegistrationTxn( } // helper for above makeKeyRegistrationTxnWithSuggestedParams, instead accepting an arguments object -/* eslint-disable no-unused-vars,no-redeclare */ export function makeKeyRegistrationTxnWithSuggestedParamsFromObject( o: Pick< RenameProperty< @@ -340,7 +335,6 @@ export function makeKeyRegistrationTxnWithSuggestedParamsFromObject( } ): txnBuilder.Transaction; export function makeKeyRegistrationTxnWithSuggestedParamsFromObject(o: any) { - /* eslint-enable no-unused-vars,no-redeclare */ return makeKeyRegistrationTxnWithSuggestedParams( o.from, o.note, diff --git a/src/multisig.ts b/src/multisig.ts index 0213f5eab..c6d1930e6 100644 --- a/src/multisig.ts +++ b/src/multisig.ts @@ -85,7 +85,7 @@ export function createMultisigTransaction( * MultisigTransaction is a Transaction that also supports creating partially-signed multisig transactions. */ export class MultisigTransaction extends txnBuilder.Transaction { - /* eslint-disable class-methods-use-this,no-unused-vars,no-dupe-class-members */ + /* eslint-disable class-methods-use-this,@typescript-eslint/no-unused-vars,no-dupe-class-members */ /** * Override inherited method to throw an error, as mutating transactions are prohibited in this context */ @@ -107,7 +107,7 @@ export class MultisigTransaction extends txnBuilder.Transaction { signTxn(sk: any): any { throw new Error(MULTISIG_USE_PARTIAL_SIGN_ERROR_MSG); } - /* eslint-enable class-methods-use-this,no-unused-vars,no-dupe-class-members */ + /* eslint-enable class-methods-use-this,@typescript-eslint/no-unused-vars,no-dupe-class-members */ /** * partialSignTxn partially signs this transaction and returns a partially-signed multisig transaction, diff --git a/src/transaction.ts b/src/transaction.ts index f850e9b08..4f5c62b49 100644 --- a/src/transaction.ts +++ b/src/transaction.ts @@ -491,6 +491,7 @@ export class Transaction implements TransactionStorageStructure { if (!txn.note.length) delete txn.note; if (!txn.amt) delete txn.amt; if (!txn.fee) delete txn.fee; + if (!txn.fv) delete txn.fv; if (!txn.gen) delete txn.gen; if (txn.grp === undefined) delete txn.grp; if (!txn.lx.length) delete txn.lx; @@ -519,6 +520,7 @@ export class Transaction implements TransactionStorageStructure { if (!txn.note.length) delete txn.note; if (!txn.lx.length) delete txn.lx; if (!txn.fee) delete txn.fee; + if (!txn.fv) delete txn.fv; if (!txn.gen) delete txn.gen; if (txn.grp === undefined) delete txn.grp; if (this.reKeyTo !== undefined) { @@ -573,6 +575,7 @@ export class Transaction implements TransactionStorageStructure { if (!txn.lx.length) delete txn.lx; if (!txn.amt) delete txn.amt; if (!txn.fee) delete txn.fee; + if (!txn.fv) delete txn.fv; if (!txn.gen) delete txn.gen; if (this.reKeyTo !== undefined) { txn.rekey = Buffer.from(this.reKeyTo.publicKey); @@ -637,6 +640,7 @@ export class Transaction implements TransactionStorageStructure { if (!txn.aamt) delete txn.aamt; if (!txn.amt) delete txn.amt; if (!txn.fee) delete txn.fee; + if (!txn.fv) delete txn.fv; if (!txn.gen) delete txn.gen; if (txn.grp === undefined) delete txn.grp; if (!txn.aclose) delete txn.aclose; @@ -670,6 +674,7 @@ export class Transaction implements TransactionStorageStructure { if (!txn.lx.length) delete txn.lx; if (!txn.amt) delete txn.amt; if (!txn.fee) delete txn.fee; + if (!txn.fv) delete txn.fv; if (!txn.gen) delete txn.gen; if (!txn.afrz) delete txn.afrz; if (txn.grp === undefined) delete txn.grp; @@ -727,6 +732,7 @@ export class Transaction implements TransactionStorageStructure { if (!txn.lx.length) delete txn.lx; if (!txn.amt) delete txn.amt; if (!txn.fee) delete txn.fee; + if (!txn.fv) delete txn.fv; if (!txn.gen) delete txn.gen; if (!txn.apid) delete txn.apid; if (!txn.apls.nui) delete txn.apls.nui; diff --git a/tests/5.Transaction.js b/tests/5.Transaction.js index 920059bc3..339404d4a 100644 --- a/tests/5.Transaction.js +++ b/tests/5.Transaction.js @@ -472,6 +472,30 @@ describe('Sign', () => { assert.deepStrictEqual(reencRep, encRep); }); + it('should correctly serialize and deserialize a first round of 0', () => { + const address = + 'BH55E5RMBD4GYWXGX5W5PJ5JAHPGM5OXKDQH5DC4O2MGI7NW4H6VOE4CP4'; + const o = { + from: address, + fee: 10, + firstRound: 0, + lastRound: 1000, + genesisHash: 'SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=', + type: 'afrz', + freezeAccount: address, + assetIndex: 1, + freezeState: true, + }; + + const expectedTxn = new algosdk.Transaction(o); + const encRep = expectedTxn.get_obj_for_encoding(); + const encTxn = algosdk.encodeObj(encRep); + const decEncRep = algosdk.decodeObj(encTxn); + const decTxn = algosdk.Transaction.from_obj_for_encoding(decEncRep); + const reencRep = decTxn.get_obj_for_encoding(); + assert.deepStrictEqual(reencRep, encRep); + }); + it('reserializes correctly no genesis ID', () => { const o = { from: 'XMHLMNAVJIMAW2RHJXLXKKK4G3J3U6VONNO3BTAQYVDC3MHTGDP3J5OCRU', diff --git a/tests/6.Multisig.js b/tests/6.Multisig.js index 2a86a453a..cdadacc53 100644 --- a/tests/6.Multisig.js +++ b/tests/6.Multisig.js @@ -21,7 +21,7 @@ describe('Multisig Functionality', () => { ).publicKey, ], }; - /* eslint-disable no-unused-vars */ + /* eslint-disable @typescript-eslint/no-unused-vars */ const multisigAddr = 'RWJLJCMQAFZ2ATP2INM2GZTKNL6OULCCUBO5TQPXH3V2KR4AG7U5UA5JNM'; const mnem1 = @@ -30,7 +30,7 @@ describe('Multisig Functionality', () => { 'since during average anxiety protect cherry club long lawsuit loan expand embark forum theory winter park twenty ball kangaroo cram burst board host ability left'; const mnem3 = 'advice pudding treat near rule blouse same whisper inner electric quit surface sunny dismiss leader blood seat clown cost exist hospital century reform able sponsor'; - /* eslint-enable no-unused-vars */ + /* eslint-enable @typescript-eslint/no-unused-vars */ const o = { snd: Buffer.from( @@ -93,7 +93,7 @@ describe('Multisig Functionality', () => { ).publicKey, ], }; - /* eslint-disable no-unused-vars */ + /* eslint-disable @typescript-eslint/no-unused-vars */ const multisigAddr = 'RWJLJCMQAFZ2ATP2INM2GZTKNL6OULCCUBO5TQPXH3V2KR4AG7U5UA5JNM'; const mnem1 = @@ -102,7 +102,7 @@ describe('Multisig Functionality', () => { 'since during average anxiety protect cherry club long lawsuit loan expand embark forum theory winter park twenty ball kangaroo cram burst board host ability left'; const mnem3 = 'advice pudding treat near rule blouse same whisper inner electric quit surface sunny dismiss leader blood seat clown cost exist hospital century reform able sponsor'; - /* eslint-enable no-unused-vars */ + /* eslint-enable @typescript-eslint/no-unused-vars */ const o = { snd: Buffer.from( diff --git a/tests/cucumber/steps/steps.js b/tests/cucumber/steps/steps.js index b9e7bf986..bc63703ed 100644 --- a/tests/cucumber/steps/steps.js +++ b/tests/cucumber/steps/steps.js @@ -1835,7 +1835,7 @@ module.exports = function getSteps(options) { When( 'we make any {string} call to {string}.', - // eslint-disable-next-line no-unused-vars + // eslint-disable-next-line @typescript-eslint/no-unused-vars async function (client, _endpoint) { try { if (client === 'algod') { From 6d57c7aca3655a6bbaa7866effb0dd2cad7edbad Mon Sep 17 00:00:00 2001 From: Jacob Daitzman Date: Thu, 8 Jul 2021 14:08:02 -0400 Subject: [PATCH 3/9] Add `prepare` script to support npm installing with the git URL (#400) --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 214bb1ea1..489659509 100644 --- a/package.json +++ b/package.json @@ -66,6 +66,7 @@ }, "scripts": { "test": "node -r ts-node/register tests/mocha.js", + "prepare": "npm run build", "prepare-browser-tests": "npm run build && mkdir -p tests/cucumber/browser/build && cp dist/browser/algosdk.min.* tests/cucumber/browser/build/ && webpack --config tests/cucumber/browser/webpack.config.js", "build": "concurrently \"webpack --config webpack.config.js\" \"tsc -p tsconfig-esm.json\" \"tsc -p tsconfig-cjs.json\"", "docs": "typedoc src/main.ts", From b15369aaca3bd071813969aac1757d13e0b6d0a0 Mon Sep 17 00:00:00 2001 From: Jason Paulos Date: Thu, 8 Jul 2021 11:11:13 -0700 Subject: [PATCH 4/9] Fix msgpack encoding of dryrun objects (#399) * Fix msgpack encoding of dryrun objects * Add docstring * Address feedback * Update eslint directives --- src/client/v2/algod/dryrun.ts | 2 +- src/client/v2/algod/models/base.ts | 112 ++++---- src/client/v2/algod/models/types.ts | 391 ++++++++++++++++++++++------ templates/model.vm | 36 ++- tests/7.AlgoSDK.js | 96 ++++--- 5 files changed, 463 insertions(+), 174 deletions(-) diff --git a/src/client/v2/algod/dryrun.ts b/src/client/v2/algod/dryrun.ts index 740b2ea41..7e5b650c3 100644 --- a/src/client/v2/algod/dryrun.ts +++ b/src/client/v2/algod/dryrun.ts @@ -9,7 +9,7 @@ export default class Dryrun extends JSONRequest { constructor(c: HTTPClient, dr: modelsv2.DryrunRequest) { super(c); - this.blob = encoding.encode(dr.get_obj_for_encoding()); + this.blob = encoding.encode(dr.get_obj_for_encoding(true)); } // eslint-disable-next-line class-methods-use-this diff --git a/src/client/v2/algod/models/base.ts b/src/client/v2/algod/models/base.ts index 96c20fa30..ffb0ea169 100644 --- a/src/client/v2/algod/models/base.ts +++ b/src/client/v2/algod/models/base.ts @@ -1,63 +1,79 @@ -import { Address } from '../../../../types/address'; - /** * Base class for models */ -/* eslint-disable no-underscore-dangle,camelcase,class-methods-use-this */ -export default class BaseModel { - attribute_map: Record; - - _is_primitive(val: any): val is string | boolean | number | bigint { - return ( - val === undefined || - val == null || - (typeof val !== 'object' && typeof val !== 'function') - ); - } +/* eslint-disable no-underscore-dangle,camelcase */ +function _is_primitive(val: any): val is string | boolean | number | bigint { + /* eslint-enable no-underscore-dangle,camelcase */ + return ( + val === undefined || + val == null || + (typeof val !== 'object' && typeof val !== 'function') + ); +} - _is_address(val: any): val is Address { - return val.publicKey !== undefined && val.checksum !== undefined; - } +/* eslint-disable no-underscore-dangle,camelcase,no-redeclare,no-unused-vars */ +function _get_obj_for_encoding( + val: Function, + binary: boolean +): Record; +function _get_obj_for_encoding(val: any[], binary: boolean): any[]; +function _get_obj_for_encoding( + val: Record, + binary: boolean +): Record; +function _get_obj_for_encoding(val: any, binary: boolean): any { + /* eslint-enable no-underscore-dangle,camelcase,no-redeclare,no-unused-vars */ + let targetPropValue: any; - /* eslint-disable no-dupe-class-members,no-unused-vars */ - _get_obj_for_encoding(val: Function): Record; - _get_obj_for_encoding(val: any[]): any[]; - _get_obj_for_encoding(val: Record): Record; - _get_obj_for_encoding(val: any): any { - /* eslint-disable no-unused-vars */ - let targetPropValue: any; - if (typeof val.get_obj_for_encoding === 'function') { - targetPropValue = val.get_obj_for_encoding(); - } else if (Array.isArray(val)) { - targetPropValue = []; - for (const elem of val) { - targetPropValue.push(this._get_obj_for_encoding(elem)); - } - } else if (typeof val === 'object') { - const obj = {}; - for (const prop of Object.keys(val)) { - obj[prop] = this._get_obj_for_encoding(val[prop]); - } - targetPropValue = obj; - } else if (this._is_primitive(val)) { - targetPropValue = val; - } else { - throw new Error(`Unsupported value: ${String(val)}`); + if (val instanceof Uint8Array) { + targetPropValue = binary ? val : Buffer.from(val).toString('base64'); + } else if (typeof val.get_obj_for_encoding === 'function') { + targetPropValue = val.get_obj_for_encoding(binary); + } else if (Array.isArray(val)) { + targetPropValue = []; + for (const elem of val) { + targetPropValue.push(_get_obj_for_encoding(elem, binary)); } - return targetPropValue; + } else if (typeof val === 'object') { + const obj = {}; + for (const prop of Object.keys(val)) { + obj[prop] = _get_obj_for_encoding(val[prop], binary); + } + targetPropValue = obj; + } else if (_is_primitive(val)) { + targetPropValue = val; + } else { + throw new Error(`Unsupported value: ${String(val)}`); } - /* eslint-disable no-dupe-class-members */ + return targetPropValue; +} + +export default class BaseModel { + /* eslint-disable no-underscore-dangle,camelcase */ + attribute_map: Record; - get_obj_for_encoding() { + /** + * Get an object ready for encoding to either JSON or msgpack. + * @param binary - Use true to indicate that the encoding can handle raw binary objects + * (Uint8Arrays). Use false to indicate that raw binary objects should be converted to base64 + * strings. True should be used for objects that will be encoded with msgpack, and false should + * be used for objects that will be encoded with JSON. + */ + get_obj_for_encoding(binary = false) { + /* eslint-enable no-underscore-dangle,camelcase */ const obj: Record = {}; - for (const prop of Object.keys(this)) { - const val = this[prop]; - if (prop !== 'attribute_map' && typeof val !== 'undefined') { - const name = this.attribute_map[prop]; - obj[name] = val === null ? null : this._get_obj_for_encoding(val); + + for (const prop of Object.keys(this.attribute_map)) { + const name = this.attribute_map[prop]; + const value = this[prop]; + + if (typeof value !== 'undefined') { + obj[name] = + value === null ? null : _get_obj_for_encoding(value, binary); } } + return obj; } } diff --git a/src/client/v2/algod/models/types.ts b/src/client/v2/algod/models/types.ts index dd791803c..4f964dace 100644 --- a/src/client/v2/algod/models/types.ts +++ b/src/client/v2/algod/models/types.ts @@ -244,7 +244,7 @@ export class AccountParticipation extends BaseModel { /** * (sel) Selection public key (if any) currently registered for this round. */ - public selectionParticipationKey: string; + public selectionParticipationKey: Uint8Array; /** * (voteFst) First round for which this participation is valid. @@ -265,7 +265,7 @@ export class AccountParticipation extends BaseModel { * (vote) root participation public key (if any) currently registered for this * round. */ - public voteParticipationKey: string; + public voteParticipationKey: Uint8Array; /** * Creates a new `AccountParticipation` object. @@ -283,18 +283,24 @@ export class AccountParticipation extends BaseModel { voteLastValid, voteParticipationKey, }: { - selectionParticipationKey: string; + selectionParticipationKey: string | Uint8Array; voteFirstValid: number | bigint; voteKeyDilution: number | bigint; voteLastValid: number | bigint; - voteParticipationKey: string; + voteParticipationKey: string | Uint8Array; }) { super(); - this.selectionParticipationKey = selectionParticipationKey; + this.selectionParticipationKey = + typeof selectionParticipationKey === 'string' + ? new Uint8Array(Buffer.from(selectionParticipationKey, 'base64')) + : selectionParticipationKey; this.voteFirstValid = voteFirstValid; this.voteKeyDilution = voteKeyDilution; this.voteLastValid = voteLastValid; - this.voteParticipationKey = voteParticipationKey; + this.voteParticipationKey = + typeof voteParticipationKey === 'string' + ? new Uint8Array(Buffer.from(voteParticipationKey, 'base64')) + : voteParticipationKey; this.attribute_map = { selectionParticipationKey: 'selection-participation-key', @@ -310,12 +316,19 @@ export class AccountParticipation extends BaseModel { * Application state delta. */ export class AccountStateDelta extends BaseModel { + public address: string; + + /** + * Application state delta. + */ + public delta: EvalDeltaKeyValue[]; + /** * Creates a new `AccountStateDelta` object. * @param address - * @param delta - Application state delta. */ - constructor(public address: string, public delta: EvalDeltaKeyValue[]) { + constructor(address: string, delta: EvalDeltaKeyValue[]) { super(); this.address = address; this.delta = delta; @@ -331,12 +344,22 @@ export class AccountStateDelta extends BaseModel { * Application index and its parameters */ export class Application extends BaseModel { + /** + * (appidx) application index. + */ + public id: number | bigint; + + /** + * (appparams) application parameters. + */ + public params: ApplicationParams; + /** * Creates a new `Application` object. * @param id - (appidx) application index. * @param params - (appparams) application parameters. */ - constructor(public id: number | bigint, public params: ApplicationParams) { + constructor(id: number | bigint, params: ApplicationParams) { super(); this.id = id; this.params = params; @@ -352,6 +375,21 @@ export class Application extends BaseModel { * Stores local state associated with an application. */ export class ApplicationLocalState extends BaseModel { + /** + * The application which this local state is for. + */ + public id: number | bigint; + + /** + * (hsch) schema. + */ + public schema: ApplicationStateSchema; + + /** + * (tkv) storage. + */ + public keyValue?: TealKeyValue[]; + /** * Creates a new `ApplicationLocalState` object. * @param id - The application which this local state is for. @@ -359,9 +397,9 @@ export class ApplicationLocalState extends BaseModel { * @param keyValue - (tkv) storage. */ constructor( - public id: number | bigint, - public schema: ApplicationStateSchema, - public keyValue?: TealKeyValue[] + id: number | bigint, + schema: ApplicationStateSchema, + keyValue?: TealKeyValue[] ) { super(); this.id = id; @@ -383,12 +421,12 @@ export class ApplicationParams extends BaseModel { /** * (approv) approval program. */ - public approvalProgram: string; + public approvalProgram: Uint8Array; /** * (clearp) approval program. */ - public clearStateProgram: string; + public clearStateProgram: Uint8Array; /** * The address that created this application. This is the address where the @@ -436,8 +474,8 @@ export class ApplicationParams extends BaseModel { globalStateSchema, localStateSchema, }: { - approvalProgram: string; - clearStateProgram: string; + approvalProgram: string | Uint8Array; + clearStateProgram: string | Uint8Array; creator: string; extraProgramPages?: number | bigint; globalState?: TealKeyValue[]; @@ -445,8 +483,14 @@ export class ApplicationParams extends BaseModel { localStateSchema?: ApplicationStateSchema; }) { super(); - this.approvalProgram = approvalProgram; - this.clearStateProgram = clearStateProgram; + this.approvalProgram = + typeof approvalProgram === 'string' + ? new Uint8Array(Buffer.from(approvalProgram, 'base64')) + : approvalProgram; + this.clearStateProgram = + typeof clearStateProgram === 'string' + ? new Uint8Array(Buffer.from(clearStateProgram, 'base64')) + : clearStateProgram; this.creator = creator; this.extraProgramPages = extraProgramPages; this.globalState = globalState; @@ -469,15 +513,22 @@ export class ApplicationParams extends BaseModel { * Specifies maximums on the number of each type that may be stored. */ export class ApplicationStateSchema extends BaseModel { + /** + * (nui) num of uints. + */ + public numUint: number | bigint; + + /** + * (nbs) num of byte slices. + */ + public numByteSlice: number | bigint; + /** * Creates a new `ApplicationStateSchema` object. * @param numUint - (nui) num of uints. * @param numByteSlice - (nbs) num of byte slices. */ - constructor( - public numUint: number | bigint, - public numByteSlice: number | bigint - ) { + constructor(numUint: number | bigint, numByteSlice: number | bigint) { super(); this.numUint = numUint; this.numByteSlice = numByteSlice; @@ -493,6 +544,19 @@ export class ApplicationStateSchema extends BaseModel { * Specifies both the unique identifier and the parameters for an asset */ export class Asset extends BaseModel { + /** + * unique asset identifier + */ + public index: number | bigint; + + /** + * AssetParams specifies the parameters for an asset. + * (apar) when part of an AssetConfig transaction. + * Definition: + * data/transactions/asset.go : AssetParams + */ + public params: AssetParams; + /** * Creates a new `Asset` object. * @param index - unique asset identifier @@ -501,7 +565,7 @@ export class Asset extends BaseModel { * Definition: * data/transactions/asset.go : AssetParams */ - constructor(public index: number | bigint, public params: AssetParams) { + constructor(index: number | bigint, params: AssetParams) { super(); this.index = index; this.params = params; @@ -519,6 +583,28 @@ export class Asset extends BaseModel { * data/basics/userBalance.go : AssetHolding */ export class AssetHolding extends BaseModel { + /** + * (a) number of units held. + */ + public amount: number | bigint; + + /** + * Asset ID of the holding. + */ + public assetId: number | bigint; + + /** + * Address that created this asset. This is the address where the parameters for + * this asset can be found, and also the address where unwanted asset units can be + * sent in the worst case. + */ + public creator: string; + + /** + * (f) whether or not the holding is frozen. + */ + public isFrozen: boolean; + /** * Creates a new `AssetHolding` object. * @param amount - (a) number of units held. @@ -529,10 +615,10 @@ export class AssetHolding extends BaseModel { * @param isFrozen - (f) whether or not the holding is frozen. */ constructor( - public amount: number | bigint, - public assetId: number | bigint, - public creator: string, - public isFrozen: boolean + amount: number | bigint, + assetId: number | bigint, + creator: string, + isFrozen: boolean ) { super(); this.amount = amount; @@ -602,7 +688,7 @@ export class AssetParams extends BaseModel { * (am) A commitment to some unspecified asset metadata. The format of this * metadata is up to the application. */ - public metadataHash?: string; + public metadataHash?: Uint8Array; /** * (an) Name of this asset, as supplied by the creator. @@ -668,7 +754,7 @@ export class AssetParams extends BaseModel { defaultFrozen?: boolean; freeze?: string; manager?: string; - metadataHash?: string; + metadataHash?: string | Uint8Array; name?: string; reserve?: string; unitName?: string; @@ -682,7 +768,10 @@ export class AssetParams extends BaseModel { this.defaultFrozen = defaultFrozen; this.freeze = freeze; this.manager = manager; - this.metadataHash = metadataHash; + this.metadataHash = + typeof metadataHash === 'string' + ? new Uint8Array(Buffer.from(metadataHash, 'base64')) + : metadataHash; this.name = name; this.reserve = reserve; this.unitName = unitName; @@ -709,13 +798,24 @@ export class AssetParams extends BaseModel { * Encoded block object. */ export class BlockResponse extends BaseModel { + /** + * Block header data. + */ + public block: BlockHeader; + + /** + * Optional certificate object. This is only included when the format is set to + * message pack. + */ + public cert?: Record; + /** * Creates a new `BlockResponse` object. * @param block - Block header data. * @param cert - Optional certificate object. This is only included when the format is set to * message pack. */ - constructor(public block: BlockHeader, public cert?: Record) { + constructor(block: BlockHeader, cert?: Record) { super(); this.block = block; this.cert = cert; @@ -787,11 +887,16 @@ export class BuildVersion extends BaseModel { * */ export class CatchpointAbortResponse extends BaseModel { + /** + * Catchup abort response string + */ + public catchupMessage: string; + /** * Creates a new `CatchpointAbortResponse` object. * @param catchupMessage - Catchup abort response string */ - constructor(public catchupMessage: string) { + constructor(catchupMessage: string) { super(); this.catchupMessage = catchupMessage; @@ -805,11 +910,16 @@ export class CatchpointAbortResponse extends BaseModel { * */ export class CatchpointStartResponse extends BaseModel { + /** + * Catchup start response string + */ + public catchupMessage: string; + /** * Creates a new `CatchpointStartResponse` object. * @param catchupMessage - Catchup start response string */ - constructor(public catchupMessage: string) { + constructor(catchupMessage: string) { super(); this.catchupMessage = catchupMessage; @@ -823,12 +933,22 @@ export class CatchpointStartResponse extends BaseModel { * Teal compile Result */ export class CompileResponse extends BaseModel { + /** + * base32 SHA512_256 of program bytes (Address style) + */ + public hash: string; + + /** + * base64 encoded program bytes + */ + public result: string; + /** * Creates a new `CompileResponse` object. * @param hash - base32 SHA512_256 of program bytes (Address style) * @param result - base64 encoded program bytes */ - constructor(public hash: string, public result: string) { + constructor(hash: string, result: string) { super(); this.hash = hash; this.result = result; @@ -926,17 +1046,22 @@ export class DryrunRequest extends BaseModel { * DryrunResponse contains per-txn debug information from a dryrun. */ export class DryrunResponse extends BaseModel { + public error: string; + + /** + * Protocol version is the protocol version Dryrun was operated under. + */ + public protocolVersion: string; + + public txns: DryrunTxnResult[]; + /** * Creates a new `DryrunResponse` object. * @param error - * @param protocolVersion - Protocol version is the protocol version Dryrun was operated under. * @param txns - */ - constructor( - public error: string, - public protocolVersion: string, - public txns: DryrunTxnResult[] - ) { + constructor(error: string, protocolVersion: string, txns: DryrunTxnResult[]) { super(); this.error = error; this.protocolVersion = protocolVersion; @@ -955,6 +1080,19 @@ export class DryrunResponse extends BaseModel { * transactions or application state. */ export class DryrunSource extends BaseModel { + /** + * FieldName is what kind of sources this is. If lsig then it goes into the + * transactions[this.TxnIndex].LogicSig. If approv or clearp it goes into the + * Approval Program or Clear State Program of application[this.AppIndex]. + */ + public fieldName: string; + + public source: string; + + public txnIndex: number | bigint; + + public appIndex: number | bigint; + /** * Creates a new `DryrunSource` object. * @param fieldName - FieldName is what kind of sources this is. If lsig then it goes into the @@ -965,10 +1103,10 @@ export class DryrunSource extends BaseModel { * @param appIndex - */ constructor( - public fieldName: string, - public source: string, - public txnIndex: number | bigint, - public appIndex: number | bigint + fieldName: string, + source: string, + txnIndex: number | bigint, + appIndex: number | bigint ) { super(); this.fieldName = fieldName; @@ -1123,12 +1261,16 @@ export class DryrunTxnResult extends BaseModel { * An error response with optional data field. */ export class ErrorResponse extends BaseModel { + public message: string; + + public data?: string; + /** * Creates a new `ErrorResponse` object. * @param message - * @param data - */ - constructor(public message: string, public data?: string) { + constructor(message: string, data?: string) { super(); this.message = message; this.data = data; @@ -1144,17 +1286,28 @@ export class ErrorResponse extends BaseModel { * Represents a TEAL value delta. */ export class EvalDelta extends BaseModel { + /** + * (at) delta action. + */ + public action: number | bigint; + + /** + * (bs) bytes value. + */ + public bytes?: string; + + /** + * (ui) uint value. + */ + public uint?: number | bigint; + /** * Creates a new `EvalDelta` object. * @param action - (at) delta action. * @param bytes - (bs) bytes value. * @param uint - (ui) uint value. */ - constructor( - public action: number | bigint, - public bytes?: string, - public uint?: number | bigint - ) { + constructor(action: number | bigint, bytes?: string, uint?: number | bigint) { super(); this.action = action; this.bytes = bytes; @@ -1172,12 +1325,19 @@ export class EvalDelta extends BaseModel { * Key-value pairs for StateDelta. */ export class EvalDeltaKeyValue extends BaseModel { + public key: string; + + /** + * Represents a TEAL value delta. + */ + public value: EvalDelta; + /** * Creates a new `EvalDeltaKeyValue` object. * @param key - * @param value - Represents a TEAL value delta. */ - constructor(public key: string, public value: EvalDelta) { + constructor(key: string, value: EvalDelta) { super(); this.key = key; this.value = value; @@ -1528,14 +1688,24 @@ export class PendingTransactionResponse extends BaseModel { * elements in the **top-transactions** array is fewer than **total-transactions**. */ export class PendingTransactionsResponse extends BaseModel { + /** + * An array of signed transaction objects. + */ + public topTransactions: EncodedSignedTransaction[]; + + /** + * Total number of transactions in the pool. + */ + public totalTransactions: number | bigint; + /** * Creates a new `PendingTransactionsResponse` object. * @param topTransactions - An array of signed transaction objects. * @param totalTransactions - Total number of transactions in the pool. */ constructor( - public topTransactions: EncodedSignedTransaction[], - public totalTransactions: number | bigint + topTransactions: EncodedSignedTransaction[], + totalTransactions: number | bigint ) { super(); this.topTransactions = topTransactions; @@ -1552,11 +1722,16 @@ export class PendingTransactionsResponse extends BaseModel { * Transaction ID of the submission. */ export class PostTransactionsResponse extends BaseModel { + /** + * encoding of the transaction hash. + */ + public txid: string; + /** * Creates a new `PostTransactionsResponse` object. * @param txid - encoding of the transaction hash. */ - constructor(public txid: string) { + constructor(txid: string) { super(); this.txid = txid; @@ -1570,6 +1745,21 @@ export class PostTransactionsResponse extends BaseModel { * Proof of transaction in a block. */ export class ProofResponse extends BaseModel { + /** + * Index of the transaction in the block's payset. + */ + public idx: number | bigint; + + /** + * Merkle proof of transaction membership. + */ + public proof: Uint8Array; + + /** + * Hash of SignedTxnInBlock for verifying proof. + */ + public stibhash: Uint8Array; + /** * Creates a new `ProofResponse` object. * @param idx - Index of the transaction in the block's payset. @@ -1577,14 +1767,20 @@ export class ProofResponse extends BaseModel { * @param stibhash - Hash of SignedTxnInBlock for verifying proof. */ constructor( - public idx: number | bigint, - public proof: string, - public stibhash: string + idx: number | bigint, + proof: string | Uint8Array, + stibhash: string | Uint8Array ) { super(); this.idx = idx; - this.proof = proof; - this.stibhash = stibhash; + this.proof = + typeof proof === 'string' + ? new Uint8Array(Buffer.from(proof, 'base64')) + : proof; + this.stibhash = + typeof stibhash === 'string' + ? new Uint8Array(Buffer.from(stibhash, 'base64')) + : stibhash; this.attribute_map = { idx: 'idx', @@ -1598,6 +1794,21 @@ export class ProofResponse extends BaseModel { * Supply represents the current supply of MicroAlgos in the system. */ export class SupplyResponse extends BaseModel { + /** + * Round + */ + public currentRound: number | bigint; + + /** + * OnlineMoney + */ + public onlineMoney: number | bigint; + + /** + * TotalMoney + */ + public totalMoney: number | bigint; + /** * Creates a new `SupplyResponse` object. * @param currentRound - Round @@ -1605,9 +1816,9 @@ export class SupplyResponse extends BaseModel { * @param totalMoney - TotalMoney */ constructor( - public currentRound: number | bigint, - public onlineMoney: number | bigint, - public totalMoney: number | bigint + currentRound: number | bigint, + onlineMoney: number | bigint, + totalMoney: number | bigint ) { super(); this.currentRound = currentRound; @@ -1626,12 +1837,19 @@ export class SupplyResponse extends BaseModel { * Represents a key-value pair in an application store. */ export class TealKeyValue extends BaseModel { + public key: string; + + /** + * Represents a TEAL value. + */ + public value: TealValue; + /** * Creates a new `TealKeyValue` object. * @param key - * @param value - Represents a TEAL value. */ - constructor(public key: string, public value: TealValue) { + constructor(key: string, value: TealValue) { super(); this.key = key; this.value = value; @@ -1647,17 +1865,28 @@ export class TealKeyValue extends BaseModel { * Represents a TEAL value. */ export class TealValue extends BaseModel { + /** + * (tt) value type. + */ + public type: number | bigint; + + /** + * (tb) bytes value. + */ + public bytes: string; + + /** + * (ui) uint value. + */ + public uint: number | bigint; + /** * Creates a new `TealValue` object. * @param type - (tt) value type. * @param bytes - (tb) bytes value. * @param uint - (ui) uint value. */ - constructor( - public type: number | bigint, - public bytes: string, - public uint: number | bigint - ) { + constructor(type: number | bigint, bytes: string, uint: number | bigint) { super(); this.type = type; this.bytes = bytes; @@ -1693,7 +1922,7 @@ export class TransactionParametersResponse extends BaseModel { /** * GenesisHash is the hash of the genesis block. */ - public genesisHash: string; + public genesisHash: Uint8Array; /** * GenesisID is an ID listed in the genesis block. @@ -1735,7 +1964,7 @@ export class TransactionParametersResponse extends BaseModel { }: { consensusVersion: string; fee: number | bigint; - genesisHash: string; + genesisHash: string | Uint8Array; genesisId: string; lastRound: number | bigint; minFee: number | bigint; @@ -1743,7 +1972,10 @@ export class TransactionParametersResponse extends BaseModel { super(); this.consensusVersion = consensusVersion; this.fee = fee; - this.genesisHash = genesisHash; + this.genesisHash = + typeof genesisHash === 'string' + ? new Uint8Array(Buffer.from(genesisHash, 'base64')) + : genesisHash; this.genesisId = genesisId; this.lastRound = lastRound; this.minFee = minFee; @@ -1763,6 +1995,14 @@ export class TransactionParametersResponse extends BaseModel { * algod version information. */ export class Version extends BaseModel { + public build: BuildVersion; + + public genesisHashB64: Uint8Array; + + public genesisId: string; + + public versions: string[]; + /** * Creates a new `Version` object. * @param build - @@ -1771,14 +2011,17 @@ export class Version extends BaseModel { * @param versions - */ constructor( - public build: BuildVersion, - public genesisHashB64: string, - public genesisId: string, - public versions: string[] + build: BuildVersion, + genesisHashB64: string | Uint8Array, + genesisId: string, + versions: string[] ) { super(); this.build = build; - this.genesisHashB64 = genesisHashB64; + this.genesisHashB64 = + typeof genesisHashB64 === 'string' + ? new Uint8Array(Buffer.from(genesisHashB64, 'base64')) + : genesisHashB64; this.genesisId = genesisId; this.versions = versions; diff --git a/templates/model.vm b/templates/model.vm index ba12e99ca..4b5ffeb0d 100644 --- a/templates/model.vm +++ b/templates/model.vm @@ -3,7 +3,7 @@ $str.kebabToCamel($param.propertyName.replaceAll("_", "-"))## #end ## Converts a parameter type into the SDK specific type. -#macro ( toSdkType $param ) +#macro ( toSdkType $param $isArgType ) #if ( $param.algorandFormat == "SignedTransaction" ) EncodedSignedTransaction## #elseif ( $param.algorandFormat == "Address" ) ## No special handling for Address in go SDK @@ -25,7 +25,11 @@ Uint8Array## #elseif($param.arrayType && $param.format == "byte") Uint8Array## #elseif( $param.type == "string" && $param.format == "byte" ) -string## +#if ( $isArgType ) +string | Uint8Array## +#else +Uint8Array## +#end #elseif( $param.type == "string" || $param.arrayType == "string" ) string## #elseif( $param.arrayType ) @@ -43,6 +47,24 @@ $unknown.type ## force a template failure with an unknown type #end #if ($param.arrayType && $param.arrayType != "")[]#end## Add array postfix to arrays... #end +## Converts a parameter type into the SDK specific type. +#macro ( constructorAssignType $prop ) +#set( $argType = "#toSdkType($prop, true)" ) +#set( $fieldType = "#toSdkType($prop, false)" ) +#set( $name = "#paramName($prop)" ) +#if ( $argType == $fieldType ) +$name## +#elseif ( $argType == "string | Uint8Array" && $fieldType == "Uint8Array" ) +typeof $name === 'string' ? new Uint8Array(Buffer.from($name, 'base64')) : $name## +#else +UNHANDLED CONSTRUCTOR TYPE CONVERSION +- property: $prop +- propertyName: $name +- argType: $argType +- fieldType type: $fieldType +$unknown.type ## force a template failure with an unknown type +#end +#end #macro ( questionMarkIfOptional $param ) #if ( ! $param.required ) ?## @@ -79,16 +101,14 @@ import BlockHeader from '../../../../types/blockHeader'; */ #end export class $def.name extends BaseModel { -#if ($use_object_params) #foreach( $prop in $props ) #if ( !$prop.doc.isEmpty() ) /** * $str.formatDoc($prop.doc, " * ") */ #end - public #paramName($prop)#questionMarkIfOptional($prop): #toSdkType($prop); + public #paramName($prop)#questionMarkIfOptional($prop): #toSdkType($prop, false); -#end #end /** * Creates a new `$def.name` object. @@ -105,13 +125,13 @@ export class $def.name extends BaseModel { #if ($use_object_params) #paramName($prop), #else - public #paramName($prop)#questionMarkIfOptional($prop): #toSdkType($prop), + #paramName($prop)#questionMarkIfOptional($prop): #toSdkType($prop, true), #end #end #if ($use_object_params) }: { #foreach ( $prop in $props ) - #paramName($prop)#questionMarkIfOptional($prop): #toSdkType($prop) + #paramName($prop)#questionMarkIfOptional($prop): #toSdkType($prop, true) #end }) { @@ -121,7 +141,7 @@ export class $def.name extends BaseModel { super(); #foreach( $prop in $props ) #set( $var = "#paramName($prop)" ) - this.$var = $var; + this.$var = #constructorAssignType($prop); #end this.attribute_map = { diff --git a/tests/7.AlgoSDK.js b/tests/7.AlgoSDK.js index ba763ffbc..6ad333d09 100644 --- a/tests/7.AlgoSDK.js +++ b/tests/7.AlgoSDK.js @@ -924,52 +924,62 @@ describe('Algosdk (AKA end to end)', () => { }); describe('v2 Dryrun models', () => { - it('should be properly serialized', () => { - const schema = new algosdk.modelsv2.ApplicationStateSchema(5, 5); - const acc = new algosdk.modelsv2.Account({ - address: 'UAPJE355K7BG7RQVMTZOW7QW4ICZJEIC3RZGYG5LSHZ65K6LCNFPJDSR7M', - amount: 5002280000000000, - amountWithoutPendingRewards: 5000000000000000, - pendingRewards: 2280000000000, - rewardBase: 456, - rewards: 2280000000000, - round: 18241, - status: 'Online', - }); - const params = new algosdk.modelsv2.ApplicationParams({ - creator: 'UAPJE355K7BG7RQVMTZOW7QW4ICZJEIC3RZGYG5LSHZ65K6LCNFPJDSR7M', - approvalProgram: 'AiABASI=', - clearStateProgram: 'AiABASI=', - localStateSchema: schema, - globalStateSchema: schema, - }); - const app = new algosdk.modelsv2.Application(1380011588, params); - // make a raw txn - const txn = { - apsu: 'AiABASI=', - fee: 1000, - fv: 18242, - gh: 'ZIkPs8pTDxbRJsFB1yJ7gvnpDu0Q85FRkl2NCkEAQLU=', - lv: 19242, - note: 'tjpNge78JD8=', - snd: 'UAPJE355K7BG7RQVMTZOW7QW4ICZJEIC3RZGYG5LSHZ65K6LCNFPJDSR7M', - type: 'appl', - }; - const req = new algosdk.modelsv2.DryrunRequest({ - accounts: [acc], - apps: [app], - round: 18241, - protocolVersion: 'future', - latestTimestamp: 1592537757, - sources: null, - txns: [{ txn }], - }); + const schema = new algosdk.modelsv2.ApplicationStateSchema(5, 5); + const acc = new algosdk.modelsv2.Account({ + address: 'UAPJE355K7BG7RQVMTZOW7QW4ICZJEIC3RZGYG5LSHZ65K6LCNFPJDSR7M', + amount: 5002280000000000, + amountWithoutPendingRewards: 5000000000000000, + pendingRewards: 2280000000000, + rewardBase: 456, + rewards: 2280000000000, + round: 18241, + status: 'Online', + }); + const params = new algosdk.modelsv2.ApplicationParams({ + creator: 'UAPJE355K7BG7RQVMTZOW7QW4ICZJEIC3RZGYG5LSHZ65K6LCNFPJDSR7M', + approvalProgram: 'AiABASI=', + clearStateProgram: 'AiABASI=', + localStateSchema: schema, + globalStateSchema: schema, + }); + const app = new algosdk.modelsv2.Application(1380011588, params); + // make a raw txn + const txn = { + apsu: 'AiABASI=', + fee: 1000, + fv: 18242, + gh: 'ZIkPs8pTDxbRJsFB1yJ7gvnpDu0Q85FRkl2NCkEAQLU=', + lv: 19242, + note: 'tjpNge78JD8=', + snd: 'UAPJE355K7BG7RQVMTZOW7QW4ICZJEIC3RZGYG5LSHZ65K6LCNFPJDSR7M', + type: 'appl', + }; + const req = new algosdk.modelsv2.DryrunRequest({ + accounts: [acc], + apps: [app], + round: 18241, + protocolVersion: 'future', + latestTimestamp: 1592537757, + txns: [{ txn }], + }); + + it('should be properly serialized to JSON', () => { const actual = req.get_obj_for_encoding(); const golden = - 'ewogICJhY2NvdW50cyI6IFsKICAgIHsKICAgICAgImFkZHJlc3MiOiAiVUFQSkUzNTVLN0JHN1JRVk1UWk9XN1FXNElDWkpFSUMzUlpHWUc1TFNIWjY1SzZMQ05GUEpEU1I3TSIsCiAgICAgICJhbW91bnQiOiA1MDAyMjgwMDAwMDAwMDAwLAogICAgICAiYW1vdW50LXdpdGhvdXQtcGVuZGluZy1yZXdhcmRzIjogNTAwMDAwMDAwMDAwMDAwMCwKICAgICAgInBlbmRpbmctcmV3YXJkcyI6IDIyODAwMDAwMDAwMDAsCiAgICAgICJyZXdhcmQtYmFzZSI6IDQ1NiwKICAgICAgInJld2FyZHMiOiAyMjgwMDAwMDAwMDAwLAogICAgICAicm91bmQiOiAxODI0MSwKICAgICAgInN0YXR1cyI6ICJPbmxpbmUiCiAgICB9CiAgXSwKICAiYXBwcyI6IFsKICAgIHsKICAgICAgImlkIjogMTM4MDAxMTU4OCwKICAgICAgInBhcmFtcyI6IHsKICAgICAgICAiY3JlYXRvciI6ICJVQVBKRTM1NUs3Qkc3UlFWTVRaT1c3UVc0SUNaSkVJQzNSWkdZRzVMU0haNjVLNkxDTkZQSkRTUjdNIiwKICAgICAgICAiYXBwcm92YWwtcHJvZ3JhbSI6ICJBaUFCQVNJPSIsCiAgICAgICAgImNsZWFyLXN0YXRlLXByb2dyYW0iOiAiQWlBQkFTST0iLAogICAgICAgICJnbG9iYWwtc3RhdGUtc2NoZW1hIjogewogICAgICAgICAgIm51bS1ieXRlLXNsaWNlIjogNSwKICAgICAgICAgICJudW0tdWludCI6IDUKICAgICAgICB9LAogICAgICAgICJsb2NhbC1zdGF0ZS1zY2hlbWEiOiB7CiAgICAgICAgICAibnVtLWJ5dGUtc2xpY2UiOiA1LAogICAgICAgICAgIm51bS11aW50IjogNQogICAgICAgIH0KICAgICAgfQogICAgfQogIF0sCiAgImxhdGVzdC10aW1lc3RhbXAiOiAxNTkyNTM3NzU3LAogICJwcm90b2NvbC12ZXJzaW9uIjogImZ1dHVyZSIsCiAgInJvdW5kIjogMTgyNDEsCiAgInNvdXJjZXMiOiBudWxsLAogICJ0eG5zIjogWwogICAgewogICAgICAidHhuIjogewogICAgICAgICJhcHN1IjogIkFpQUJBU0k9IiwKICAgICAgICAiZmVlIjogMTAwMCwKICAgICAgICAiZnYiOiAxODI0MiwKICAgICAgICAiZ2giOiAiWklrUHM4cFREeGJSSnNGQjF5Sjdndm5wRHUwUTg1RlJrbDJOQ2tFQVFMVT0iLAogICAgICAgICJsdiI6IDE5MjQyLAogICAgICAgICJub3RlIjogInRqcE5nZTc4SkQ4PSIsCiAgICAgICAgInNuZCI6ICJVQVBKRTM1NUs3Qkc3UlFWTVRaT1c3UVc0SUNaSkVJQzNSWkdZRzVMU0haNjVLNkxDTkZQSkRTUjdNIiwKICAgICAgICAidHlwZSI6ICJhcHBsIgogICAgICB9CiAgICB9CiAgXQp9Cg=='; - const json = Buffer.from(golden, 'base64').toString('utf8'); - const expected = JSON.parse(json); + 'ewogICJhY2NvdW50cyI6IFsKICAgIHsKICAgICAgImFkZHJlc3MiOiAiVUFQSkUzNTVLN0JHN1JRVk1UWk9XN1FXNElDWkpFSUMzUlpHWUc1TFNIWjY1SzZMQ05GUEpEU1I3TSIsCiAgICAgICJhbW91bnQiOiA1MDAyMjgwMDAwMDAwMDAwLAogICAgICAiYW1vdW50LXdpdGhvdXQtcGVuZGluZy1yZXdhcmRzIjogNTAwMDAwMDAwMDAwMDAwMCwKICAgICAgInBlbmRpbmctcmV3YXJkcyI6IDIyODAwMDAwMDAwMDAsCiAgICAgICJyZXdhcmQtYmFzZSI6IDQ1NiwKICAgICAgInJld2FyZHMiOiAyMjgwMDAwMDAwMDAwLAogICAgICAicm91bmQiOiAxODI0MSwKICAgICAgInN0YXR1cyI6ICJPbmxpbmUiCiAgICB9CiAgXSwKICAiYXBwcyI6IFsKICAgIHsKICAgICAgImlkIjogMTM4MDAxMTU4OCwKICAgICAgInBhcmFtcyI6IHsKICAgICAgICAiY3JlYXRvciI6ICJVQVBKRTM1NUs3Qkc3UlFWTVRaT1c3UVc0SUNaSkVJQzNSWkdZRzVMU0haNjVLNkxDTkZQSkRTUjdNIiwKICAgICAgICAiYXBwcm92YWwtcHJvZ3JhbSI6ICJBaUFCQVNJPSIsCiAgICAgICAgImNsZWFyLXN0YXRlLXByb2dyYW0iOiAiQWlBQkFTST0iLAogICAgICAgICJnbG9iYWwtc3RhdGUtc2NoZW1hIjogewogICAgICAgICAgIm51bS1ieXRlLXNsaWNlIjogNSwKICAgICAgICAgICJudW0tdWludCI6IDUKICAgICAgICB9LAogICAgICAgICJsb2NhbC1zdGF0ZS1zY2hlbWEiOiB7CiAgICAgICAgICAibnVtLWJ5dGUtc2xpY2UiOiA1LAogICAgICAgICAgIm51bS11aW50IjogNQogICAgICAgIH0KICAgICAgfQogICAgfQogIF0sCiAgImxhdGVzdC10aW1lc3RhbXAiOiAxNTkyNTM3NzU3LAogICJwcm90b2NvbC12ZXJzaW9uIjogImZ1dHVyZSIsCiAgInJvdW5kIjogMTgyNDEsCiAgInR4bnMiOiBbCiAgICB7CiAgICAgICJ0eG4iOiB7CiAgICAgICAgImFwc3UiOiAiQWlBQkFTST0iLAogICAgICAgICJmZWUiOiAxMDAwLAogICAgICAgICJmdiI6IDE4MjQyLAogICAgICAgICJnaCI6ICJaSWtQczhwVER4YlJKc0ZCMXlKN2d2bnBEdTBRODVGUmtsMk5Da0VBUUxVPSIsCiAgICAgICAgImx2IjogMTkyNDIsCiAgICAgICAgIm5vdGUiOiAidGpwTmdlNzhKRDg9IiwKICAgICAgICAic25kIjogIlVBUEpFMzU1SzdCRzdSUVZNVFpPVzdRVzRJQ1pKRUlDM1JaR1lHNUxTSFo2NUs2TENORlBKRFNSN00iLAogICAgICAgICJ0eXBlIjogImFwcGwiCiAgICAgIH0KICAgIH0KICBdCn0K'; + const goldenString = Buffer.from(golden, 'base64').toString('utf8'); + const expected = JSON.parse(goldenString); + + assert.deepStrictEqual(actual, expected); + }); + + it('should be properly serialized to msgpack', () => { + const actual = req.get_obj_for_encoding(true); + const golden = + 'hqhhY2NvdW50c5GIp2FkZHJlc3PZOlVBUEpFMzU1SzdCRzdSUVZNVFpPVzdRVzRJQ1pKRUlDM1JaR1lHNUxTSFo2NUs2TENORlBKRFNSN02mYW1vdW50zwARxYwSd5AAvmFtb3VudC13aXRob3V0LXBlbmRpbmctcmV3YXJkc88AEcN5N+CAAK9wZW5kaW5nLXJld2FyZHPPAAACEtqXEACrcmV3YXJkLWJhc2XNAcincmV3YXJkc88AAAIS2pcQAKVyb3VuZM1HQaZzdGF0dXOmT25saW5lpGFwcHORgqJpZM5SQU5EpnBhcmFtc4WwYXBwcm92YWwtcHJvZ3JhbcQFAiABASKzY2xlYXItc3RhdGUtcHJvZ3JhbcQFAiABASKnY3JlYXRvctk6VUFQSkUzNTVLN0JHN1JRVk1UWk9XN1FXNElDWkpFSUMzUlpHWUc1TFNIWjY1SzZMQ05GUEpEU1I3TbNnbG9iYWwtc3RhdGUtc2NoZW1hgq5udW0tYnl0ZS1zbGljZQWobnVtLXVpbnQFsmxvY2FsLXN0YXRlLXNjaGVtYYKubnVtLWJ5dGUtc2xpY2UFqG51bS11aW50BbBsYXRlc3QtdGltZXN0YW1wzl7sMp2wcHJvdG9jb2wtdmVyc2lvbqZmdXR1cmWlcm91bmTNR0GkdHhuc5GBo3R4boikYXBzdahBaUFCQVNJPaNmZWXNA+iiZnbNR0KiZ2jZLFpJa1BzOHBURHhiUkpzRkIxeUo3Z3ZucER1MFE4NUZSa2wyTkNrRUFRTFU9omx2zUsqpG5vdGWsdGpwTmdlNzhKRDg9o3NuZNk6VUFQSkUzNTVLN0JHN1JRVk1UWk9XN1FXNElDWkpFSUMzUlpHWUc1TFNIWjY1SzZMQ05GUEpEU1I3TaR0eXBlpGFwcGw='; + const goldenBinary = new Uint8Array(Buffer.from(golden, 'base64')); + const expected = algosdk.decodeObj(goldenBinary); assert.deepStrictEqual(actual, expected); }); From 66f1c5ee9d730cac466d49893d80235f7856a436 Mon Sep 17 00:00:00 2001 From: Amit Yadav Date: Fri, 9 Jul 2021 23:48:01 +0530 Subject: [PATCH 5/9] Export Rest API types (#391) * export types * export algodV2 types * add prepare * update * update * update * fix lint * remove modelsv2 * update * remove SuggestedParamsRequest * add line --- src/main.ts | 2 +- src/types/index.ts | 3 +++ src/types/transactions/encoded.ts | 2 +- src/types/transactions/index.ts | 2 +- 4 files changed, 6 insertions(+), 3 deletions(-) create mode 100644 src/types/index.ts diff --git a/src/main.ts b/src/main.ts index 3aa70ddd2..544279910 100644 --- a/src/main.ts +++ b/src/main.ts @@ -234,7 +234,6 @@ export const ERROR_INVALID_MICROALGOS = new Error( convert.INVALID_MICROALGOS_ERROR_MSG ); -export * from './types/transactions'; export * from './client/algod'; export { default as Algodv2 } from './client/v2/algod/algod'; export { default as Kmd } from './client/kmd'; @@ -272,3 +271,4 @@ export const LogicTemplates = LogicTemplatesCommonJSExport.default; export * from './makeTxn'; export * from './transaction'; +export * from './types'; diff --git a/src/types/index.ts b/src/types/index.ts new file mode 100644 index 000000000..d7657e836 --- /dev/null +++ b/src/types/index.ts @@ -0,0 +1,3 @@ +export * from './transactions'; +export * from './multisig'; +export * from './address'; diff --git a/src/types/transactions/encoded.ts b/src/types/transactions/encoded.ts index 5ca13b749..c39d1896a 100644 --- a/src/types/transactions/encoded.ts +++ b/src/types/transactions/encoded.ts @@ -313,7 +313,7 @@ export interface EncodedSignedTransaction { sgnr?: Buffer; } -interface EncodedSubsig { +export interface EncodedSubsig { pk: Uint8Array; s?: Uint8Array; } diff --git a/src/types/transactions/index.ts b/src/types/transactions/index.ts index 427fc2eb8..320225953 100644 --- a/src/types/transactions/index.ts +++ b/src/types/transactions/index.ts @@ -23,7 +23,7 @@ export { MustHaveSuggestedParams, MustHaveSuggestedParamsInline, } from './builder'; -export { EncodedTransaction, EncodedSignedTransaction } from './encoded'; +export * from './encoded'; // Transaction types export { default as PaymentTxn } from './payment'; From 0104ec5009986932b8b3aceb3b936adcc3e6f137 Mon Sep 17 00:00:00 2001 From: Amit Yadav Date: Tue, 13 Jul 2021 19:57:54 +0530 Subject: [PATCH 6/9] add `msig` and `lsig` fields to `EncodedSignedTransaction` type (#401) * add missing fields to type * Update src/types/transactions/encoded.ts Co-authored-by: Jason Paulos Co-authored-by: Jason Paulos --- src/types/transactions/encoded.ts | 50 ++++++++++++++++++------------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/src/types/transactions/encoded.ts b/src/types/transactions/encoded.ts index c39d1896a..a6b7ecdb9 100644 --- a/src/types/transactions/encoded.ts +++ b/src/types/transactions/encoded.ts @@ -293,26 +293,6 @@ export interface EncodedTransaction { apep?: number; } -/** - * A structure for an encoded signed transaction object - */ -export interface EncodedSignedTransaction { - /** - * Transaction signature - */ - sig: Buffer; - - /** - * The transaction that was signed - */ - txn: EncodedTransaction; - - /** - * The signor, if signing with a different key than the Transaction type `from` property indicates - */ - sgnr?: Buffer; -} - export interface EncodedSubsig { pk: Uint8Array; s?: Uint8Array; @@ -360,3 +340,33 @@ export interface EncodedLogicSig { sig?: Uint8Array; msig?: EncodedMultisig; } + +/** + * A structure for an encoded signed transaction object + */ +export interface EncodedSignedTransaction { + /** + * Transaction signature + */ + sig?: Buffer; + + /** + * The transaction that was signed + */ + txn: EncodedTransaction; + + /** + * Multisig structure + */ + msig?: EncodedMultisig; + + /** + * Logic signature + */ + lsig?: EncodedLogicSig; + + /** + * The signer, if signing with a different key than the Transaction type `from` property indicates + */ + sgnr?: Buffer; +} From 418c1385cbc0f76677dcd8afd3bfd4ed6cefbab9 Mon Sep 17 00:00:00 2001 From: Jason Paulos Date: Thu, 15 Jul 2021 10:45:02 -0700 Subject: [PATCH 7/9] Fix various transaction types and migrate multisig tests to TypeScript (#402) --- src/multisig.ts | 9 +- src/transaction.ts | 45 ++- src/types/transactions/encoded.ts | 8 +- tests/{6.Multisig.js => 6.Multisig.ts} | 420 ++++++++++++------------- 4 files changed, 256 insertions(+), 226 deletions(-) rename tests/{6.Multisig.js => 6.Multisig.ts} (50%) diff --git a/src/multisig.ts b/src/multisig.ts index c6d1930e6..fb0f8b54e 100644 --- a/src/multisig.ts +++ b/src/multisig.ts @@ -49,7 +49,7 @@ interface MultisigMetadataWithPks extends Omit { * @param pks - ordered list of public keys in this multisig * @returns encoded multisig blob */ -export function createMultisigTransaction( +function createMultisigTransaction( txnForEncoding: EncodedTransaction, { rawSig, myPk }: MultisigOptions, { version, threshold, pks }: MultisigMetadataWithPks @@ -142,6 +142,13 @@ export class MultisigTransaction extends txnBuilder.Transaction { { version, threshold, pks } ); } + + // eslint-disable-next-line camelcase + static from_obj_for_encoding( + txnForEnc: EncodedTransaction + ): MultisigTransaction { + return super.from_obj_for_encoding(txnForEnc) as MultisigTransaction; + } } /** diff --git a/src/transaction.ts b/src/transaction.ts index 4f5c62b49..b7711c07c 100644 --- a/src/transaction.ts +++ b/src/transaction.ts @@ -13,6 +13,8 @@ import AnyTransaction, { MustHaveSuggestedParamsInline, EncodedTransaction, EncodedSignedTransaction, + EncodedMultisig, + EncodedLogicSig, } from './types/transactions'; import { Address } from './types/address'; @@ -756,7 +758,7 @@ export class Transaction implements TransactionStorageStructure { } // eslint-disable-next-line camelcase - static from_obj_for_encoding(txnForEnc: EncodedTransaction) { + static from_obj_for_encoding(txnForEnc: EncodedTransaction): Transaction { const txn = Object.create(this.prototype); txn.name = 'Transaction'; txn.tag = Buffer.from('TX'); @@ -1073,18 +1075,53 @@ export function decodeUnsignedTransaction( return Transaction.from_obj_for_encoding(partlyDecodedObject); } +/** + * Object representing a transaction with a signature + */ +export interface SignedTransaction { + /** + * Transaction signature + */ + sig?: Buffer; + + /** + * The transaction that was signed + */ + txn: Transaction; + + /** + * Multisig structure + */ + msig?: EncodedMultisig; + + /** + * Logic signature + */ + lsig?: EncodedLogicSig; + + /** + * The signer, if signing with a different key than the Transaction type `from` property indicates + */ + sgnr?: Buffer; +} + /** * decodeSignedTransaction takes a Buffer (from transaction.signTxn) and converts it to an object * containing the Transaction (txn), the signature (sig), and the auth-addr field if applicable (sgnr) * @param transactionBuffer - the Uint8Array containing a transaction * @returns containing a Transaction, the signature, and possibly an auth-addr field */ -export function decodeSignedTransaction(transactionBuffer: Uint8Array) { +export function decodeSignedTransaction( + transactionBuffer: Uint8Array +): SignedTransaction { const stxnDecoded = encoding.decode( transactionBuffer ) as EncodedSignedTransaction; - stxnDecoded.txn = Transaction.from_obj_for_encoding(stxnDecoded.txn); - return stxnDecoded; + const stxn: SignedTransaction = { + ...stxnDecoded, + txn: Transaction.from_obj_for_encoding(stxnDecoded.txn), + }; + return stxn; } /** diff --git a/src/types/transactions/encoded.ts b/src/types/transactions/encoded.ts index a6b7ecdb9..e762a64e7 100644 --- a/src/types/transactions/encoded.ts +++ b/src/types/transactions/encoded.ts @@ -90,12 +90,12 @@ export interface EncodedTransaction { /** * fee */ - fee: number; + fee?: number; /** * firstRound */ - fv: number; + fv?: number; /** * lastRound @@ -105,7 +105,7 @@ export interface EncodedTransaction { /** * note */ - note: Buffer; + note?: Buffer; /** * from @@ -130,7 +130,7 @@ export interface EncodedTransaction { /** * lease */ - lx: Buffer; + lx?: Buffer; /** * group diff --git a/tests/6.Multisig.js b/tests/6.Multisig.ts similarity index 50% rename from tests/6.Multisig.js rename to tests/6.Multisig.ts index cdadacc53..b5624c722 100644 --- a/tests/6.Multisig.js +++ b/tests/6.Multisig.ts @@ -1,220 +1,191 @@ -const assert = require('assert'); -const algosdk = require('../index'); -const multisig = require('../src/multisig'); +import assert from 'assert'; +import algosdk from '../index'; +import { + MultisigTransaction, + MULTISIG_NO_MUTATE_ERROR_MSG, + MULTISIG_USE_PARTIAL_SIGN_ERROR_MSG, +} from '../src/multisig'; + +const sampleAccount1 = algosdk.mnemonicToSecretKey( + 'auction inquiry lava second expand liberty glass involve ginger illness length room item discover ahead table doctor term tackle cement bonus profit right above catch' +); +const sampleAccount2 = algosdk.mnemonicToSecretKey( + 'since during average anxiety protect cherry club long lawsuit loan expand embark forum theory winter park twenty ball kangaroo cram burst board host ability left' +); +const sampleAccount3 = algosdk.mnemonicToSecretKey( + 'advice pudding treat near rule blouse same whisper inner electric quit surface sunny dismiss leader blood seat clown cost exist hospital century reform able sponsor' +); + +// Multisig Golden Params +const sampleMultisigParams: algosdk.MultisigMetadata = { + version: 1, + threshold: 2, + addrs: [sampleAccount1.addr, sampleAccount2.addr, sampleAccount3.addr], +}; + +const sampleMultisigAddr = algosdk.multisigAddress(sampleMultisigParams); + +describe('Sample Multisig Info', () => { + it('is correct', () => { + assert.strictEqual( + sampleAccount1.addr, + 'DN7MBMCL5JQ3PFUQS7TMX5AH4EEKOBJVDUF4TCV6WERATKFLQF4MQUPZTA' + ); + assert.strictEqual( + sampleAccount2.addr, + 'BFRTECKTOOE7A5LHCF3TTEOH2A7BW46IYT2SX5VP6ANKEXHZYJY77SJTVM' + ); + assert.strictEqual( + sampleAccount3.addr, + '47YPQTIGQEO7T4Y4RWDYWEKV6RTR2UNBQXBABEEGM72ESWDQNCQ52OPASU' + ); + assert.strictEqual( + sampleMultisigAddr, + 'RWJLJCMQAFZ2ATP2INM2GZTKNL6OULCCUBO5TQPXH3V2KR4AG7U5UA5JNM' + ); + }); +}); describe('Multisig Functionality', () => { describe('should generate correct partial signature', () => { it('first partial sig should match golden main repo result', () => { - // Multisig Golden Params - const params = { - version: 1, - threshold: 2, - pks: [ - algosdk.decodeAddress( - 'DN7MBMCL5JQ3PFUQS7TMX5AH4EEKOBJVDUF4TCV6WERATKFLQF4MQUPZTA' - ).publicKey, - algosdk.decodeAddress( - 'BFRTECKTOOE7A5LHCF3TTEOH2A7BW46IYT2SX5VP6ANKEXHZYJY77SJTVM' - ).publicKey, - algosdk.decodeAddress( - '47YPQTIGQEO7T4Y4RWDYWEKV6RTR2UNBQXBABEEGM72ESWDQNCQ52OPASU' - ).publicKey, - ], - }; - /* eslint-disable @typescript-eslint/no-unused-vars */ - const multisigAddr = - 'RWJLJCMQAFZ2ATP2INM2GZTKNL6OULCCUBO5TQPXH3V2KR4AG7U5UA5JNM'; - const mnem1 = - 'auction inquiry lava second expand liberty glass involve ginger illness length room item discover ahead table doctor term tackle cement bonus profit right above catch'; - const mnem2 = - 'since during average anxiety protect cherry club long lawsuit loan expand embark forum theory winter park twenty ball kangaroo cram burst board host ability left'; - const mnem3 = - 'advice pudding treat near rule blouse same whisper inner electric quit surface sunny dismiss leader blood seat clown cost exist hospital century reform able sponsor'; - /* eslint-enable @typescript-eslint/no-unused-vars */ - - const o = { - snd: Buffer.from( - algosdk.decodeAddress( - 'RWJLJCMQAFZ2ATP2INM2GZTKNL6OULCCUBO5TQPXH3V2KR4AG7U5UA5JNM' - ).publicKey - ), - rcv: Buffer.from( - algosdk.decodeAddress( - 'PNWOET7LLOWMBMLE4KOCELCX6X3D3Q4H2Q4QJASYIEOF7YIPPQBG3YQ5YI' - ).publicKey - ), - fee: 1000, - amt: 1000, - close: Buffer.from( - algosdk.decodeAddress( - 'IDUTJEUIEVSMXTU4LGTJWZ2UE2E6TIODUKU6UW3FU3UKIQQ77RLUBBBFLA' - ).publicKey - ), - gh: Buffer.from( - '/rNsORAUOQDD2lVCyhg2sA/S+BlZElfNI/YEL5jINp0=', - 'base64' - ), - fv: 62229, - lv: 63229, - gen: 'devnet-v38.0', - type: 'pay', - note: Buffer.from('RSYiABhShvs=', 'base64'), - }; + const txn = algosdk.makePaymentTxnWithSuggestedParamsFromObject({ + from: sampleMultisigAddr, + to: 'PNWOET7LLOWMBMLE4KOCELCX6X3D3Q4H2Q4QJASYIEOF7YIPPQBG3YQ5YI', + amount: 1000, + note: new Uint8Array(Buffer.from('RSYiABhShvs=', 'base64')), + closeRemainderTo: + 'IDUTJEUIEVSMXTU4LGTJWZ2UE2E6TIODUKU6UW3FU3UKIQQ77RLUBBBFLA', + suggestedParams: { + fee: 1000, + flatFee: true, + firstRound: 62229, + lastRound: 63229, + genesisID: 'devnet-v38.0', + genesisHash: '/rNsORAUOQDD2lVCyhg2sA/S+BlZElfNI/YEL5jINp0=', + }, + }); + + const { txID, blob } = algosdk.signMultisigTransaction( + txn, + sampleMultisigParams, + sampleAccount1.sk + ); - const msigTxn = multisig.MultisigTransaction.from_obj_for_encoding(o); - const { sk } = algosdk.mnemonicToSecretKey(mnem1); - const msigBlob = msigTxn.partialSignTxn(params, sk); + const expectedTxID = + 'MANN3ESOHQVHFZBAGD6UK6XFVWEFZQJPWO5SQ2J5LZRCF5E2VVQQ'; + assert.strictEqual(txID, expectedTxID); - const goldenExpected = Buffer.from( + const expectedSignedTxn = Buffer.from( 'gqRtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RAuLAFE0oma0skOoAmOzEwfPuLYpEWl4LINtsiLrUqWQkDxh4WHb29//YCpj4MFbiSgD2jKYt0XKRD86zKCF4RDYGicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxgaJwa8Qg5/D4TQaBHfnzHI2HixFV9GcdUaGFwgCQhmf0SVhwaKGjdGhyAqF2AaN0eG6Lo2FtdM0D6KVjbG9zZcQgQOk0koglZMvOnFmmm2dUJonpocOiqepbZabopEIf/FejZmVlzQPoomZ2zfMVo2dlbqxkZXZuZXQtdjM4LjCiZ2jEIP6zbDkQFDkAw9pVQsoYNrAP0vgZWRJXzSP2BC+YyDadomx2zfb9pG5vdGXECEUmIgAYUob7o3JjdsQge2ziT+tbrMCxZOKcIixX9fY9w4fUOQSCWEEcX+EPfAKjc25kxCCNkrSJkAFzoE36Q1mjZmpq/OosQqBd2cH3PuulR4A36aR0eXBlo3BheQ==', 'base64' ); - assert.deepStrictEqual(Buffer.from(msigBlob), goldenExpected); + assert.deepStrictEqual(Buffer.from(blob), expectedSignedTxn); }); it('second partial sig should match golden main repo result', () => { - // Multisig Golden Params const oneSigTxn = Buffer.from( 'gqRtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RAuLAFE0oma0skOoAmOzEwfPuLYpEWl4LINtsiLrUqWQkDxh4WHb29//YCpj4MFbiSgD2jKYt0XKRD86zKCF4RDYGicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxgaJwa8Qg5/D4TQaBHfnzHI2HixFV9GcdUaGFwgCQhmf0SVhwaKGjdGhyAqF2AaN0eG6Lo2FtdM0D6KVjbG9zZcQgQOk0koglZMvOnFmmm2dUJonpocOiqepbZabopEIf/FejZmVlzQPoomZ2zfMVo2dlbqxkZXZuZXQtdjM4LjCiZ2jEIP6zbDkQFDkAw9pVQsoYNrAP0vgZWRJXzSP2BC+YyDadomx2zfb9pG5vdGXECEUmIgAYUob7o3JjdsQge2ziT+tbrMCxZOKcIixX9fY9w4fUOQSCWEEcX+EPfAKjc25kxCCNkrSJkAFzoE36Q1mjZmpq/OosQqBd2cH3PuulR4A36aR0eXBlo3BheQ==', 'base64' ); - const params = { - version: 1, - threshold: 2, - pks: [ - algosdk.decodeAddress( - 'DN7MBMCL5JQ3PFUQS7TMX5AH4EEKOBJVDUF4TCV6WERATKFLQF4MQUPZTA' - ).publicKey, - algosdk.decodeAddress( - 'BFRTECKTOOE7A5LHCF3TTEOH2A7BW46IYT2SX5VP6ANKEXHZYJY77SJTVM' - ).publicKey, - algosdk.decodeAddress( - '47YPQTIGQEO7T4Y4RWDYWEKV6RTR2UNBQXBABEEGM72ESWDQNCQ52OPASU' - ).publicKey, - ], - }; - /* eslint-disable @typescript-eslint/no-unused-vars */ - const multisigAddr = - 'RWJLJCMQAFZ2ATP2INM2GZTKNL6OULCCUBO5TQPXH3V2KR4AG7U5UA5JNM'; - const mnem1 = - 'auction inquiry lava second expand liberty glass involve ginger illness length room item discover ahead table doctor term tackle cement bonus profit right above catch'; - const mnem2 = - 'since during average anxiety protect cherry club long lawsuit loan expand embark forum theory winter park twenty ball kangaroo cram burst board host ability left'; - const mnem3 = - 'advice pudding treat near rule blouse same whisper inner electric quit surface sunny dismiss leader blood seat clown cost exist hospital century reform able sponsor'; - /* eslint-enable @typescript-eslint/no-unused-vars */ - - const o = { - snd: Buffer.from( - algosdk.decodeAddress( - 'RWJLJCMQAFZ2ATP2INM2GZTKNL6OULCCUBO5TQPXH3V2KR4AG7U5UA5JNM' - ).publicKey - ), - rcv: Buffer.from( - algosdk.decodeAddress( - 'PNWOET7LLOWMBMLE4KOCELCX6X3D3Q4H2Q4QJASYIEOF7YIPPQBG3YQ5YI' - ).publicKey - ), - fee: 1000, - amt: 1000, - close: Buffer.from( - algosdk.decodeAddress( - 'IDUTJEUIEVSMXTU4LGTJWZ2UE2E6TIODUKU6UW3FU3UKIQQ77RLUBBBFLA' - ).publicKey - ), - gh: Buffer.from( - '/rNsORAUOQDD2lVCyhg2sA/S+BlZElfNI/YEL5jINp0=', - 'base64' - ), - fv: 62229, - lv: 63229, - gen: 'devnet-v38.0', - type: 'pay', - note: Buffer.from('RSYiABhShvs=', 'base64'), - }; - const msigTxn = multisig.MultisigTransaction.from_obj_for_encoding(o); - const { sk } = algosdk.mnemonicToSecretKey(mnem2); - const msigBlob = msigTxn.partialSignTxn(params, sk); + const txn = algosdk.makePaymentTxnWithSuggestedParamsFromObject({ + from: sampleMultisigAddr, + to: 'PNWOET7LLOWMBMLE4KOCELCX6X3D3Q4H2Q4QJASYIEOF7YIPPQBG3YQ5YI', + amount: 1000, + note: new Uint8Array(Buffer.from('RSYiABhShvs=', 'base64')), + closeRemainderTo: + 'IDUTJEUIEVSMXTU4LGTJWZ2UE2E6TIODUKU6UW3FU3UKIQQ77RLUBBBFLA', + suggestedParams: { + fee: 1000, + flatFee: true, + firstRound: 62229, + lastRound: 63229, + genesisID: 'devnet-v38.0', + genesisHash: '/rNsORAUOQDD2lVCyhg2sA/S+BlZElfNI/YEL5jINp0=', + }, + }); + + const { txID, blob } = algosdk.signMultisigTransaction( + txn, + sampleMultisigParams, + sampleAccount2.sk + ); + + const expectedTxID = + 'MANN3ESOHQVHFZBAGD6UK6XFVWEFZQJPWO5SQ2J5LZRCF5E2VVQQ'; + assert.strictEqual(txID, expectedTxID); - const finMsigBlob = multisig.mergeMultisigTransactions([ - msigBlob, - oneSigTxn, - ]); - const goldenExpected = Buffer.from( + const expectedBlob = Buffer.from( + 'gqRtc2lng6ZzdWJzaWeTgaJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXiConBrxCAJYzIJU3OJ8HVnEXc5kcfQPhtzyMT1K/av8BqiXPnCcaFzxEAQIbskY7Dq5x6d7P8SPojCoi+0D7IfIiWdtmDiST9GhVMHnTK/musH3QV5NTnn8qwDdcKifa6ujvg61ldXx9AEgaJwa8Qg5/D4TQaBHfnzHI2HixFV9GcdUaGFwgCQhmf0SVhwaKGjdGhyAqF2AaN0eG6Lo2FtdM0D6KVjbG9zZcQgQOk0koglZMvOnFmmm2dUJonpocOiqepbZabopEIf/FejZmVlzQPoomZ2zfMVo2dlbqxkZXZuZXQtdjM4LjCiZ2jEIP6zbDkQFDkAw9pVQsoYNrAP0vgZWRJXzSP2BC+YyDadomx2zfb9pG5vdGXECEUmIgAYUob7o3JjdsQge2ziT+tbrMCxZOKcIixX9fY9w4fUOQSCWEEcX+EPfAKjc25kxCCNkrSJkAFzoE36Q1mjZmpq/OosQqBd2cH3PuulR4A36aR0eXBlo3BheQ==', + 'base64' + ); + assert.deepStrictEqual(Buffer.from(blob), expectedBlob); + + const mergedBlob = algosdk.mergeMultisigTransactions([blob, oneSigTxn]); + + const expectedMergedBlob = Buffer.from( 'gqRtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RAuLAFE0oma0skOoAmOzEwfPuLYpEWl4LINtsiLrUqWQkDxh4WHb29//YCpj4MFbiSgD2jKYt0XKRD86zKCF4RDYKicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxoXPEQBAhuyRjsOrnHp3s/xI+iMKiL7QPsh8iJZ22YOJJP0aFUwedMr+a6wfdBXk1OefyrAN1wqJ9rq6O+DrWV1fH0ASBonBrxCDn8PhNBoEd+fMcjYeLEVX0Zx1RoYXCAJCGZ/RJWHBooaN0aHICoXYBo3R4boujYW10zQPopWNsb3NlxCBA6TSSiCVky86cWaabZ1Qmiemhw6Kp6ltlpuikQh/8V6NmZWXNA+iiZnbN8xWjZ2VurGRldm5ldC12MzguMKJnaMQg/rNsORAUOQDD2lVCyhg2sA/S+BlZElfNI/YEL5jINp2ibHbN9v2kbm90ZcQIRSYiABhShvujcmN2xCB7bOJP61uswLFk4pwiLFf19j3Dh9Q5BIJYQRxf4Q98AqNzbmTEII2StImQAXOgTfpDWaNmamr86ixCoF3Zwfc+66VHgDfppHR5cGWjcGF5', 'base64' ); - assert.deepStrictEqual(Buffer.from(finMsigBlob), goldenExpected); + assert.deepStrictEqual(Buffer.from(mergedBlob), expectedMergedBlob); }); }); describe('should sign keyreg transaction types', () => { it('first partial sig should match golden main repo result', () => { - // prettier-ignore - const rawTxBlob = Buffer.from([129, 163, 116, 120, 110, 140, 163, 102, 101, 101, 206, 0, 3, 200, 192, 162, 102, 118, 206, 0, 14, 249, 218, 163, 103, 101, 110, 172, 100, 101, 118, 110, 101, 116, 45, 118, 51, 56, 46, 48, 162, 103, 104, 196, 32, 254, 179, 108, 57, 16, 20, 57, 0, 195, 218, 85, 66, 202, 24, 54, 176, 15, 210, 248, 25, 89, 18, 87, 205, 35, 246, 4, 47, 152, 200, 54, 157, 162, 108, 118, 206, 0, 14, 253, 194, 166, 115, 101, 108, 107, 101, 121, 196, 32, 50, 18, 43, 43, 214, 61, 220, 83, 49, 150, 23, 165, 170, 83, 196, 177, 194, 111, 227, 220, 202, 242, 141, 54, 34, 181, 105, 119, 161, 64, 92, 134, 163, 115, 110, 100, 196, 32, 141, 146, 180, 137, 144, 1, 115, 160, 77, 250, 67, 89, 163, 102, 106, 106, 252, 234, 44, 66, 160, 93, 217, 193, 247, 62, 235, 165, 71, 128, 55, 233, 164, 116, 121, 112, 101, 166, 107, 101, 121, 114, 101, 103, 167, 118, 111, 116, 101, 102, 115, 116, 206, 0, 13, 187, 160, 166, 118, 111, 116, 101, 107, 100, 205, 39, 16, 167, 118, 111, 116, 101, 107, 101, 121, 196, 32, 112, 27, 215, 251, 145, 43, 7, 179, 8, 17, 255, 40, 29, 159, 238, 149, 99, 229, 128, 46, 32, 38, 137, 35, 25, 37, 143, 119, 250, 147, 30, 136, 167, 118, 111, 116, 101, 108, 115, 116, 206, 0, 15, 66, 64]); - // prettier-ignore - const oneSigTxBlob = Buffer.from([130, 164, 109, 115, 105, 103, 131, 166, 115, 117, 98, 115, 105, 103, 147, 130, 162, 112, 107, 196, 32, 27, 126, 192, 176, 75, 234, 97, 183, 150, 144, 151, 230, 203, 244, 7, 225, 8, 167, 5, 53, 29, 11, 201, 138, 190, 177, 34, 9, 168, 171, 129, 120, 161, 115, 196, 64, 113, 61, 44, 215, 188, 9, 110, 249, 243, 107, 227, 105, 200, 124, 12, 209, 21, 155, 67, 225, 240, 42, 107, 19, 212, 242, 236, 251, 14, 157, 232, 202, 93, 76, 125, 237, 173, 175, 178, 41, 145, 52, 43, 74, 132, 202, 20, 132, 237, 142, 122, 248, 31, 104, 105, 253, 168, 172, 70, 227, 115, 249, 227, 13, 129, 162, 112, 107, 196, 32, 9, 99, 50, 9, 83, 115, 137, 240, 117, 103, 17, 119, 57, 145, 199, 208, 62, 27, 115, 200, 196, 245, 43, 246, 175, 240, 26, 162, 92, 249, 194, 113, 129, 162, 112, 107, 196, 32, 231, 240, 248, 77, 6, 129, 29, 249, 243, 28, 141, 135, 139, 17, 85, 244, 103, 29, 81, 161, 133, 194, 0, 144, 134, 103, 244, 73, 88, 112, 104, 161, 163, 116, 104, 114, 2, 161, 118, 1, 163, 116, 120, 110, 140, 163, 102, 101, 101, 206, 0, 3, 200, 192, 162, 102, 118, 206, 0, 14, 249, 218, 163, 103, 101, 110, 172, 100, 101, 118, 110, 101, 116, 45, 118, 51, 56, 46, 48, 162, 103, 104, 196, 32, 254, 179, 108, 57, 16, 20, 57, 0, 195, 218, 85, 66, 202, 24, 54, 176, 15, 210, 248, 25, 89, 18, 87, 205, 35, 246, 4, 47, 152, 200, 54, 157, 162, 108, 118, 206, 0, 14, 253, 194, 166, 115, 101, 108, 107, 101, 121, 196, 32, 50, 18, 43, 43, 214, 61, 220, 83, 49, 150, 23, 165, 170, 83, 196, 177, 194, 111, 227, 220, 202, 242, 141, 54, 34, 181, 105, 119, 161, 64, 92, 134, 163, 115, 110, 100, 196, 32, 141, 146, 180, 137, 144, 1, 115, 160, 77, 250, 67, 89, 163, 102, 106, 106, 252, 234, 44, 66, 160, 93, 217, 193, 247, 62, 235, 165, 71, 128, 55, 233, 164, 116, 121, 112, 101, 166, 107, 101, 121, 114, 101, 103, 167, 118, 111, 116, 101, 102, 115, 116, 206, 0, 13, 187, 160, 166, 118, 111, 116, 101, 107, 100, 205, 39, 16, 167, 118, 111, 116, 101, 107, 101, 121, 196, 32, 112, 27, 215, 251, 145, 43, 7, 179, 8, 17, 255, 40, 29, 159, 238, 149, 99, 229, 128, 46, 32, 38, 137, 35, 25, 37, 143, 119, 250, 147, 30, 136, 167, 118, 111, 116, 101, 108, 115, 116, 206, 0, 15, 66, 64]); - const params = { - version: 1, - threshold: 2, - pks: [ - algosdk.decodeAddress( - 'DN7MBMCL5JQ3PFUQS7TMX5AH4EEKOBJVDUF4TCV6WERATKFLQF4MQUPZTA' - ).publicKey, - algosdk.decodeAddress( - 'BFRTECKTOOE7A5LHCF3TTEOH2A7BW46IYT2SX5VP6ANKEXHZYJY77SJTVM' - ).publicKey, - algosdk.decodeAddress( - '47YPQTIGQEO7T4Y4RWDYWEKV6RTR2UNBQXBABEEGM72ESWDQNCQ52OPASU' - ).publicKey, - ], - }; - const decRawTx = algosdk.decodeObj(rawTxBlob).txn; - const msigTxn = multisig.MultisigTransaction.from_obj_for_encoding( - decRawTx + const rawTxBlob = Buffer.from( + 'jKNmZWXOAAPIwKJmds4ADvnao2dlbqxkZXZuZXQtdjM4LjCiZ2jEIP6zbDkQFDkAw9pVQsoYNrAP0vgZWRJXzSP2BC+YyDadomx2zgAO/cKmc2Vsa2V5xCAyEisr1j3cUzGWF6WqU8Sxwm/j3MryjTYitWl3oUBchqNzbmTEII2StImQAXOgTfpDWaNmamr86ixCoF3Zwfc+66VHgDfppHR5cGWma2V5cmVnp3ZvdGVmc3TOAA27oKZ2b3Rla2TNJxCndm90ZWtlecQgcBvX+5ErB7MIEf8oHZ/ulWPlgC4gJokjGSWPd/qTHoindm90ZWxzdM4AD0JA', + 'base64' + ); + const decRawTx = algosdk.decodeUnsignedTransaction(rawTxBlob); + + const { txID, blob } = algosdk.signMultisigTransaction( + decRawTx, + sampleMultisigParams, + sampleAccount1.sk + ); + + const expectedTxID = + 'E7DA7WTJCWWFQMKSVU5HOIJ5F5HGVGMOZGBIHRJRYGIX7FIJ5VWA'; + assert.strictEqual(txID, expectedTxID); + + const oneSigTxBlob = Buffer.from( + 'gqRtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RAcT0s17wJbvnza+NpyHwM0RWbQ+HwKmsT1PLs+w6d6MpdTH3tra+yKZE0K0qEyhSE7Y56+B9oaf2orEbjc/njDYGicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxgaJwa8Qg5/D4TQaBHfnzHI2HixFV9GcdUaGFwgCQhmf0SVhwaKGjdGhyAqF2AaN0eG6Mo2ZlZc4AA8jAomZ2zgAO+dqjZ2VurGRldm5ldC12MzguMKJnaMQg/rNsORAUOQDD2lVCyhg2sA/S+BlZElfNI/YEL5jINp2ibHbOAA79wqZzZWxrZXnEIDISKyvWPdxTMZYXpapTxLHCb+PcyvKNNiK1aXehQFyGo3NuZMQgjZK0iZABc6BN+kNZo2ZqavzqLEKgXdnB9z7rpUeAN+mkdHlwZaZrZXlyZWendm90ZWZzdM4ADbugpnZvdGVrZM0nEKd2b3Rla2V5xCBwG9f7kSsHswgR/ygdn+6VY+WALiAmiSMZJY93+pMeiKd2b3RlbHN0zgAPQkA=', + 'base64' ); - const mnem1 = - 'auction inquiry lava second expand liberty glass involve ginger illness length room item discover ahead table doctor term tackle cement bonus profit right above catch'; - const { sk } = algosdk.mnemonicToSecretKey(mnem1); - const msigBlob = msigTxn.partialSignTxn(params, sk); - assert.deepStrictEqual(Buffer.from(msigBlob), oneSigTxBlob); + assert.deepStrictEqual(Buffer.from(blob), oneSigTxBlob); }); it('second partial sig with 3rd pk should match golden main repo result', () => { - // prettier-ignore - const rawOneSigTxBlob = Buffer.from([130, 164, 109, 115, 105, 103, 131, 166, 115, 117, 98, 115, 105, 103, 147, 130, 162, 112, 107, 196, 32, 27, 126, 192, 176, 75, 234, 97, 183, 150, 144, 151, 230, 203, 244, 7, 225, 8, 167, 5, 53, 29, 11, 201, 138, 190, 177, 34, 9, 168, 171, 129, 120, 161, 115, 196, 64, 113, 61, 44, 215, 188, 9, 110, 249, 243, 107, 227, 105, 200, 124, 12, 209, 21, 155, 67, 225, 240, 42, 107, 19, 212, 242, 236, 251, 14, 157, 232, 202, 93, 76, 125, 237, 173, 175, 178, 41, 145, 52, 43, 74, 132, 202, 20, 132, 237, 142, 122, 248, 31, 104, 105, 253, 168, 172, 70, 227, 115, 249, 227, 13, 129, 162, 112, 107, 196, 32, 9, 99, 50, 9, 83, 115, 137, 240, 117, 103, 17, 119, 57, 145, 199, 208, 62, 27, 115, 200, 196, 245, 43, 246, 175, 240, 26, 162, 92, 249, 194, 113, 129, 162, 112, 107, 196, 32, 231, 240, 248, 77, 6, 129, 29, 249, 243, 28, 141, 135, 139, 17, 85, 244, 103, 29, 81, 161, 133, 194, 0, 144, 134, 103, 244, 73, 88, 112, 104, 161, 163, 116, 104, 114, 2, 161, 118, 1, 163, 116, 120, 110, 140, 163, 102, 101, 101, 206, 0, 3, 200, 192, 162, 102, 118, 206, 0, 14, 249, 218, 163, 103, 101, 110, 172, 100, 101, 118, 110, 101, 116, 45, 118, 51, 56, 46, 48, 162, 103, 104, 196, 32, 254, 179, 108, 57, 16, 20, 57, 0, 195, 218, 85, 66, 202, 24, 54, 176, 15, 210, 248, 25, 89, 18, 87, 205, 35, 246, 4, 47, 152, 200, 54, 157, 162, 108, 118, 206, 0, 14, 253, 194, 166, 115, 101, 108, 107, 101, 121, 196, 32, 50, 18, 43, 43, 214, 61, 220, 83, 49, 150, 23, 165, 170, 83, 196, 177, 194, 111, 227, 220, 202, 242, 141, 54, 34, 181, 105, 119, 161, 64, 92, 134, 163, 115, 110, 100, 196, 32, 141, 146, 180, 137, 144, 1, 115, 160, 77, 250, 67, 89, 163, 102, 106, 106, 252, 234, 44, 66, 160, 93, 217, 193, 247, 62, 235, 165, 71, 128, 55, 233, 164, 116, 121, 112, 101, 166, 107, 101, 121, 114, 101, 103, 167, 118, 111, 116, 101, 102, 115, 116, 206, 0, 13, 187, 160, 166, 118, 111, 116, 101, 107, 100, 205, 39, 16, 167, 118, 111, 116, 101, 107, 101, 121, 196, 32, 112, 27, 215, 251, 145, 43, 7, 179, 8, 17, 255, 40, 29, 159, 238, 149, 99, 229, 128, 46, 32, 38, 137, 35, 25, 37, 143, 119, 250, 147, 30, 136, 167, 118, 111, 116, 101, 108, 115, 116, 206, 0, 15, 66, 64]); - // prettier-ignore - const twoSigTxBlob = Buffer.from([130, 164, 109, 115, 105, 103, 131, 166, 115, 117, 98, 115, 105, 103, 147, 130, 162, 112, 107, 196, 32, 27, 126, 192, 176, 75, 234, 97, 183, 150, 144, 151, 230, 203, 244, 7, 225, 8, 167, 5, 53, 29, 11, 201, 138, 190, 177, 34, 9, 168, 171, 129, 120, 161, 115, 196, 64, 113, 61, 44, 215, 188, 9, 110, 249, 243, 107, 227, 105, 200, 124, 12, 209, 21, 155, 67, 225, 240, 42, 107, 19, 212, 242, 236, 251, 14, 157, 232, 202, 93, 76, 125, 237, 173, 175, 178, 41, 145, 52, 43, 74, 132, 202, 20, 132, 237, 142, 122, 248, 31, 104, 105, 253, 168, 172, 70, 227, 115, 249, 227, 13, 129, 162, 112, 107, 196, 32, 9, 99, 50, 9, 83, 115, 137, 240, 117, 103, 17, 119, 57, 145, 199, 208, 62, 27, 115, 200, 196, 245, 43, 246, 175, 240, 26, 162, 92, 249, 194, 113, 130, 162, 112, 107, 196, 32, 231, 240, 248, 77, 6, 129, 29, 249, 243, 28, 141, 135, 139, 17, 85, 244, 103, 29, 81, 161, 133, 194, 0, 144, 134, 103, 244, 73, 88, 112, 104, 161, 161, 115, 196, 64, 125, 39, 23, 127, 48, 75, 104, 78, 54, 53, 177, 125, 33, 29, 42, 49, 173, 205, 5, 9, 225, 99, 169, 16, 177, 95, 186, 134, 218, 129, 179, 15, 219, 90, 103, 54, 188, 25, 90, 235, 144, 137, 45, 35, 66, 53, 45, 183, 232, 27, 20, 50, 91, 219, 194, 187, 55, 146, 113, 126, 233, 186, 161, 15, 163, 116, 104, 114, 2, 161, 118, 1, 163, 116, 120, 110, 140, 163, 102, 101, 101, 206, 0, 3, 200, 192, 162, 102, 118, 206, 0, 14, 249, 218, 163, 103, 101, 110, 172, 100, 101, 118, 110, 101, 116, 45, 118, 51, 56, 46, 48, 162, 103, 104, 196, 32, 254, 179, 108, 57, 16, 20, 57, 0, 195, 218, 85, 66, 202, 24, 54, 176, 15, 210, 248, 25, 89, 18, 87, 205, 35, 246, 4, 47, 152, 200, 54, 157, 162, 108, 118, 206, 0, 14, 253, 194, 166, 115, 101, 108, 107, 101, 121, 196, 32, 50, 18, 43, 43, 214, 61, 220, 83, 49, 150, 23, 165, 170, 83, 196, 177, 194, 111, 227, 220, 202, 242, 141, 54, 34, 181, 105, 119, 161, 64, 92, 134, 163, 115, 110, 100, 196, 32, 141, 146, 180, 137, 144, 1, 115, 160, 77, 250, 67, 89, 163, 102, 106, 106, 252, 234, 44, 66, 160, 93, 217, 193, 247, 62, 235, 165, 71, 128, 55, 233, 164, 116, 121, 112, 101, 166, 107, 101, 121, 114, 101, 103, 167, 118, 111, 116, 101, 102, 115, 116, 206, 0, 13, 187, 160, 166, 118, 111, 116, 101, 107, 100, 205, 39, 16, 167, 118, 111, 116, 101, 107, 101, 121, 196, 32, 112, 27, 215, 251, 145, 43, 7, 179, 8, 17, 255, 40, 29, 159, 238, 149, 99, 229, 128, 46, 32, 38, 137, 35, 25, 37, 143, 119, 250, 147, 30, 136, 167, 118, 111, 116, 101, 108, 115, 116, 206, 0, 15, 66, 64]); - const params = { - version: 1, - threshold: 2, - pks: [ - algosdk.decodeAddress( - 'DN7MBMCL5JQ3PFUQS7TMX5AH4EEKOBJVDUF4TCV6WERATKFLQF4MQUPZTA' - ).publicKey, - algosdk.decodeAddress( - 'BFRTECKTOOE7A5LHCF3TTEOH2A7BW46IYT2SX5VP6ANKEXHZYJY77SJTVM' - ).publicKey, - algosdk.decodeAddress( - '47YPQTIGQEO7T4Y4RWDYWEKV6RTR2UNBQXBABEEGM72ESWDQNCQ52OPASU' - ).publicKey, - ], - }; - const decRawTx = algosdk.decodeObj(rawOneSigTxBlob).txn; - const msigTxn = multisig.MultisigTransaction.from_obj_for_encoding( - decRawTx + const rawOneSigTxBlob = Buffer.from( + 'gqRtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RAcT0s17wJbvnza+NpyHwM0RWbQ+HwKmsT1PLs+w6d6MpdTH3tra+yKZE0K0qEyhSE7Y56+B9oaf2orEbjc/njDYGicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxgaJwa8Qg5/D4TQaBHfnzHI2HixFV9GcdUaGFwgCQhmf0SVhwaKGjdGhyAqF2AaN0eG6Mo2ZlZc4AA8jAomZ2zgAO+dqjZ2VurGRldm5ldC12MzguMKJnaMQg/rNsORAUOQDD2lVCyhg2sA/S+BlZElfNI/YEL5jINp2ibHbOAA79wqZzZWxrZXnEIDISKyvWPdxTMZYXpapTxLHCb+PcyvKNNiK1aXehQFyGo3NuZMQgjZK0iZABc6BN+kNZo2ZqavzqLEKgXdnB9z7rpUeAN+mkdHlwZaZrZXlyZWendm90ZWZzdM4ADbugpnZvdGVrZM0nEKd2b3Rla2V5xCBwG9f7kSsHswgR/ygdn+6VY+WALiAmiSMZJY93+pMeiKd2b3RlbHN0zgAPQkA=', + 'base64' ); - const mnem3 = - 'advice pudding treat near rule blouse same whisper inner electric quit surface sunny dismiss leader blood seat clown cost exist hospital century reform able sponsor'; - const { sk } = algosdk.mnemonicToSecretKey(mnem3); - const msigBlob = msigTxn.partialSignTxn(params, sk); - const finMsigBlob = multisig.mergeMultisigTransactions([ - msigBlob, + const decRawTx = algosdk.decodeSignedTransaction(rawOneSigTxBlob).txn; + + const { txID, blob } = algosdk.signMultisigTransaction( + decRawTx, + sampleMultisigParams, + sampleAccount3.sk + ); + + const expectedTxID = + 'E7DA7WTJCWWFQMKSVU5HOIJ5F5HGVGMOZGBIHRJRYGIX7FIJ5VWA'; + assert.strictEqual(txID, expectedTxID); + + const finMsigBlob = algosdk.mergeMultisigTransactions([ + blob, new Uint8Array(rawOneSigTxBlob), ]); + + const twoSigTxBlob = Buffer.from( + 'gqRtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RAcT0s17wJbvnza+NpyHwM0RWbQ+HwKmsT1PLs+w6d6MpdTH3tra+yKZE0K0qEyhSE7Y56+B9oaf2orEbjc/njDYGicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxgqJwa8Qg5/D4TQaBHfnzHI2HixFV9GcdUaGFwgCQhmf0SVhwaKGhc8RAfScXfzBLaE42NbF9IR0qMa3NBQnhY6kQsV+6htqBsw/bWmc2vBla65CJLSNCNS236BsUMlvbwrs3knF+6bqhD6N0aHICoXYBo3R4boyjZmVlzgADyMCiZnbOAA752qNnZW6sZGV2bmV0LXYzOC4womdoxCD+s2w5EBQ5AMPaVULKGDawD9L4GVkSV80j9gQvmMg2naJsds4ADv3CpnNlbGtlecQgMhIrK9Y93FMxlhelqlPEscJv49zK8o02IrVpd6FAXIajc25kxCCNkrSJkAFzoE36Q1mjZmpq/OosQqBd2cH3PuulR4A36aR0eXBlpmtleXJlZ6d2b3RlZnN0zgANu6Cmdm90ZWtkzScQp3ZvdGVrZXnEIHAb1/uRKwezCBH/KB2f7pVj5YAuICaJIxklj3f6kx6Ip3ZvdGVsc3TOAA9CQA==', + 'base64' + ); + assert.deepStrictEqual(Buffer.from(finMsigBlob), twoSigTxBlob); }); @@ -226,11 +197,11 @@ describe('Multisig Functionality', () => { // prettier-ignore const allThreeBlob = Buffer.from([130, 164, 109, 115, 105, 103, 131, 166, 115, 117, 98, 115, 105, 103, 147, 130, 162, 112, 107, 196, 32, 27, 126, 192, 176, 75, 234, 97, 183, 150, 144, 151, 230, 203, 244, 7, 225, 8, 167, 5, 53, 29, 11, 201, 138, 190, 177, 34, 9, 168, 171, 129, 120, 161, 115, 196, 64, 113, 61, 44, 215, 188, 9, 110, 249, 243, 107, 227, 105, 200, 124, 12, 209, 21, 155, 67, 225, 240, 42, 107, 19, 212, 242, 236, 251, 14, 157, 232, 202, 93, 76, 125, 237, 173, 175, 178, 41, 145, 52, 43, 74, 132, 202, 20, 132, 237, 142, 122, 248, 31, 104, 105, 253, 168, 172, 70, 227, 115, 249, 227, 13, 130, 162, 112, 107, 196, 32, 9, 99, 50, 9, 83, 115, 137, 240, 117, 103, 17, 119, 57, 145, 199, 208, 62, 27, 115, 200, 196, 245, 43, 246, 175, 240, 26, 162, 92, 249, 194, 113, 161, 115, 196, 64, 227, 199, 17, 26, 50, 149, 36, 250, 241, 222, 56, 188, 127, 140, 131, 144, 167, 224, 18, 230, 61, 37, 113, 136, 156, 116, 104, 237, 140, 138, 121, 215, 140, 159, 38, 64, 106, 111, 177, 108, 51, 233, 152, 250, 233, 207, 138, 116, 61, 55, 89, 204, 6, 164, 2, 114, 128, 230, 199, 130, 136, 25, 207, 1, 130, 162, 112, 107, 196, 32, 231, 240, 248, 77, 6, 129, 29, 249, 243, 28, 141, 135, 139, 17, 85, 244, 103, 29, 81, 161, 133, 194, 0, 144, 134, 103, 244, 73, 88, 112, 104, 161, 161, 115, 196, 64, 125, 39, 23, 127, 48, 75, 104, 78, 54, 53, 177, 125, 33, 29, 42, 49, 173, 205, 5, 9, 225, 99, 169, 16, 177, 95, 186, 134, 218, 129, 179, 15, 219, 90, 103, 54, 188, 25, 90, 235, 144, 137, 45, 35, 66, 53, 45, 183, 232, 27, 20, 50, 91, 219, 194, 187, 55, 146, 113, 126, 233, 186, 161, 15, 163, 116, 104, 114, 2, 161, 118, 1, 163, 116, 120, 110, 140, 163, 102, 101, 101, 206, 0, 3, 200, 192, 162, 102, 118, 206, 0, 14, 249, 218, 163, 103, 101, 110, 172, 100, 101, 118, 110, 101, 116, 45, 118, 51, 56, 46, 48, 162, 103, 104, 196, 32, 254, 179, 108, 57, 16, 20, 57, 0, 195, 218, 85, 66, 202, 24, 54, 176, 15, 210, 248, 25, 89, 18, 87, 205, 35, 246, 4, 47, 152, 200, 54, 157, 162, 108, 118, 206, 0, 14, 253, 194, 166, 115, 101, 108, 107, 101, 121, 196, 32, 50, 18, 43, 43, 214, 61, 220, 83, 49, 150, 23, 165, 170, 83, 196, 177, 194, 111, 227, 220, 202, 242, 141, 54, 34, 181, 105, 119, 161, 64, 92, 134, 163, 115, 110, 100, 196, 32, 141, 146, 180, 137, 144, 1, 115, 160, 77, 250, 67, 89, 163, 102, 106, 106, 252, 234, 44, 66, 160, 93, 217, 193, 247, 62, 235, 165, 71, 128, 55, 233, 164, 116, 121, 112, 101, 166, 107, 101, 121, 114, 101, 103, 167, 118, 111, 116, 101, 102, 115, 116, 206, 0, 13, 187, 160, 166, 118, 111, 116, 101, 107, 100, 205, 39, 16, 167, 118, 111, 116, 101, 107, 101, 121, 196, 32, 112, 27, 215, 251, 145, 43, 7, 179, 8, 17, 255, 40, 29, 159, 238, 149, 99, 229, 128, 46, 32, 38, 137, 35, 25, 37, 143, 119, 250, 147, 30, 136, 167, 118, 111, 116, 101, 108, 115, 116, 206, 0, 15, 66, 64]); - const finMsigBlob = multisig.mergeMultisigTransactions([ + const finMsigBlob = algosdk.mergeMultisigTransactions([ new Uint8Array(twoAndThreeBlob), new Uint8Array(oneAndThreeBlob), ]); - const finMsigBlobTwo = multisig.mergeMultisigTransactions([ + const finMsigBlobTwo = algosdk.mergeMultisigTransactions([ new Uint8Array(oneAndThreeBlob), new Uint8Array(twoAndThreeBlob), ]); @@ -278,9 +249,7 @@ describe('Multisig Functionality', () => { }; stdPaymentTxn = algosdk.Transaction.from_obj_for_encoding(paymentTxnObj); - msigPaymentTxn = multisig.MultisigTransaction.from_obj_for_encoding( - paymentTxnObj - ); + msigPaymentTxn = MultisigTransaction.from_obj_for_encoding(paymentTxnObj); const keyregTxnObj = { snd: Buffer.from( @@ -292,9 +261,18 @@ describe('Multisig Functionality', () => { fv: 51, lv: 61, note: Buffer.from([123, 12, 200]), - gh: 'JgsgCaCTqIaLeVhyL6XlRu3n7Rfk2FxMeK+wRSaQ7dI=', - votekey: '5/D4TQaBHfnzHI2HixFV9GcdUaGFwgCQhmf0SVhwaKE=', - selkey: 'oImqaSLjuZj63/bNSAjd+eAh5JROOJ6j1cY4eGaJGX4=', + gh: Buffer.from( + 'JgsgCaCTqIaLeVhyL6XlRu3n7Rfk2FxMeK+wRSaQ7dI=', + 'base64' + ), + votekey: Buffer.from( + '5/D4TQaBHfnzHI2HixFV9GcdUaGFwgCQhmf0SVhwaKE=', + 'base64' + ), + selkey: Buffer.from( + 'oImqaSLjuZj63/bNSAjd+eAh5JROOJ6j1cY4eGaJGX4=', + 'base64' + ), votefst: 123, votelst: 456, votekd: 1234, @@ -303,9 +281,7 @@ describe('Multisig Functionality', () => { }; stdKeyregTxn = algosdk.Transaction.from_obj_for_encoding(keyregTxnObj); - msigKeyregTxn = multisig.MultisigTransaction.from_obj_for_encoding( - keyregTxnObj - ); + msigKeyregTxn = MultisigTransaction.from_obj_for_encoding(keyregTxnObj); }); it('`estimateSize` method should match expected result', () => { @@ -375,9 +351,18 @@ describe('Multisig Functionality', () => { fv: 51, lv: 61, note: Buffer.from([123, 12, 200]), - gh: 'JgsgCaCTqIaLeVhyL6XlRu3n7Rfk2FxMeK+wRSaQ7dI=', - votekey: '5/D4TQaBHfnzHI2HixFV9GcdUaGFwgCQhmf0SVhwaKE=', - selkey: 'oImqaSLjuZj63/bNSAjd+eAh5JROOJ6j1cY4eGaJGX4=', + gh: Buffer.from( + 'JgsgCaCTqIaLeVhyL6XlRu3n7Rfk2FxMeK+wRSaQ7dI=', + 'base64' + ), + votekey: Buffer.from( + '5/D4TQaBHfnzHI2HixFV9GcdUaGFwgCQhmf0SVhwaKE=', + 'base64' + ), + selkey: Buffer.from( + 'oImqaSLjuZj63/bNSAjd+eAh5JROOJ6j1cY4eGaJGX4=', + 'base64' + ), votefst: 123, votelst: 456, votekd: 1234, @@ -385,33 +370,29 @@ describe('Multisig Functionality', () => { type: 'keyreg', }; - msigPaymentTxn = multisig.MultisigTransaction.from_obj_for_encoding( - paymentTxnObj - ); - msigKeyregTxn = multisig.MultisigTransaction.from_obj_for_encoding( - keyregTxnObj - ); + msigPaymentTxn = MultisigTransaction.from_obj_for_encoding(paymentTxnObj); + msigKeyregTxn = MultisigTransaction.from_obj_for_encoding(keyregTxnObj); }); it('error should be thrown when attempting to add a lease to a transaction', () => { assert.throws( msigPaymentTxn.addLease, - (err) => err.message === multisig.MULTISIG_NO_MUTATE_ERROR_MSG + (err) => err.message === MULTISIG_NO_MUTATE_ERROR_MSG ); assert.throws( msigKeyregTxn.addLease, - (err) => err.message === multisig.MULTISIG_NO_MUTATE_ERROR_MSG + (err) => err.message === MULTISIG_NO_MUTATE_ERROR_MSG ); }); it('error should be thrown when attempting to add a rekey to a transaction', () => { assert.throws( msigPaymentTxn.addRekey, - (err) => err.message === multisig.MULTISIG_NO_MUTATE_ERROR_MSG + (err) => err.message === MULTISIG_NO_MUTATE_ERROR_MSG ); assert.throws( msigKeyregTxn.addRekey, - (err) => err.message === multisig.MULTISIG_NO_MUTATE_ERROR_MSG + (err) => err.message === MULTISIG_NO_MUTATE_ERROR_MSG ); }); }); @@ -461,9 +442,18 @@ describe('Multisig Functionality', () => { fv: 51, lv: 61, note: Buffer.from([123, 12, 200]), - gh: 'JgsgCaCTqIaLeVhyL6XlRu3n7Rfk2FxMeK+wRSaQ7dI=', - votekey: '5/D4TQaBHfnzHI2HixFV9GcdUaGFwgCQhmf0SVhwaKE=', - selkey: 'oImqaSLjuZj63/bNSAjd+eAh5JROOJ6j1cY4eGaJGX4=', + gh: Buffer.from( + 'JgsgCaCTqIaLeVhyL6XlRu3n7Rfk2FxMeK+wRSaQ7dI=', + 'base64' + ), + votekey: Buffer.from( + '5/D4TQaBHfnzHI2HixFV9GcdUaGFwgCQhmf0SVhwaKE=', + 'base64' + ), + selkey: Buffer.from( + 'oImqaSLjuZj63/bNSAjd+eAh5JROOJ6j1cY4eGaJGX4=', + 'base64' + ), votefst: 123, votelst: 456, votekd: 1234, @@ -471,22 +461,18 @@ describe('Multisig Functionality', () => { type: 'keyreg', }; - msigPaymentTxn = multisig.MultisigTransaction.from_obj_for_encoding( - paymentTxnObj - ); - msigKeyregTxn = multisig.MultisigTransaction.from_obj_for_encoding( - keyregTxnObj - ); + msigPaymentTxn = MultisigTransaction.from_obj_for_encoding(paymentTxnObj); + msigKeyregTxn = MultisigTransaction.from_obj_for_encoding(keyregTxnObj); }); it('signTxn method should throw an error', () => { assert.throws( msigPaymentTxn.signTxn, - (err) => err.message === multisig.MULTISIG_USE_PARTIAL_SIGN_ERROR_MSG + (err) => err.message === MULTISIG_USE_PARTIAL_SIGN_ERROR_MSG ); assert.throws( msigKeyregTxn.signTxn, - (err) => err.message === multisig.MULTISIG_USE_PARTIAL_SIGN_ERROR_MSG + (err) => err.message === MULTISIG_USE_PARTIAL_SIGN_ERROR_MSG ); }); }); From 169d1d82b4aecd7173c119f646c0fa11a9de3e8e Mon Sep 17 00:00:00 2001 From: Algo-devops-service <80971703+Algo-devops-service@users.noreply.github.com> Date: Mon, 19 Jul 2021 16:11:25 -0400 Subject: [PATCH 8/9] Regenerate code from specification file (#405) --- src/client/v2/algod/models/types.ts | 57 ++++++++++++++++++++++++++--- 1 file changed, 51 insertions(+), 6 deletions(-) diff --git a/src/client/v2/algod/models/types.ts b/src/client/v2/algod/models/types.ts index 4f964dace..962a2c7cb 100644 --- a/src/client/v2/algod/models/types.ts +++ b/src/client/v2/algod/models/types.ts @@ -691,25 +691,43 @@ export class AssetParams extends BaseModel { public metadataHash?: Uint8Array; /** - * (an) Name of this asset, as supplied by the creator. + * (an) Name of this asset, as supplied by the creator. Included only when the + * asset name is composed of printable utf-8 characters. */ public name?: string; + /** + * Base64 encoded name of this asset, as supplied by the creator. + */ + public nameB64?: Uint8Array; + /** * (r) Address of account holding reserve (non-minted) units of this asset. */ public reserve?: string; /** - * (un) Name of a unit of this asset, as supplied by the creator. + * (un) Name of a unit of this asset, as supplied by the creator. Included only + * when the name of a unit of this asset is composed of printable utf-8 characters. */ public unitName?: string; /** - * (au) URL where more information about the asset can be retrieved. + * Base64 encoded name of a unit of this asset, as supplied by the creator. + */ + public unitNameB64?: Uint8Array; + + /** + * (au) URL where more information about the asset can be retrieved. Included only + * when the URL is composed of printable utf-8 characters. */ public url?: string; + /** + * Base64 encoded URL where more information about the asset can be retrieved. + */ + public urlB64?: Uint8Array; + /** * Creates a new `AssetParams` object. * @param creator - The address that created this asset. This is the address where the parameters @@ -728,10 +746,16 @@ export class AssetParams extends BaseModel { * @param manager - (m) Address of account used to manage the keys of this asset and to destroy it. * @param metadataHash - (am) A commitment to some unspecified asset metadata. The format of this * metadata is up to the application. - * @param name - (an) Name of this asset, as supplied by the creator. + * @param name - (an) Name of this asset, as supplied by the creator. Included only when the + * asset name is composed of printable utf-8 characters. + * @param nameB64 - Base64 encoded name of this asset, as supplied by the creator. * @param reserve - (r) Address of account holding reserve (non-minted) units of this asset. - * @param unitName - (un) Name of a unit of this asset, as supplied by the creator. - * @param url - (au) URL where more information about the asset can be retrieved. + * @param unitName - (un) Name of a unit of this asset, as supplied by the creator. Included only + * when the name of a unit of this asset is composed of printable utf-8 characters. + * @param unitNameB64 - Base64 encoded name of a unit of this asset, as supplied by the creator. + * @param url - (au) URL where more information about the asset can be retrieved. Included only + * when the URL is composed of printable utf-8 characters. + * @param urlB64 - Base64 encoded URL where more information about the asset can be retrieved. */ constructor({ creator, @@ -743,9 +767,12 @@ export class AssetParams extends BaseModel { manager, metadataHash, name, + nameB64, reserve, unitName, + unitNameB64, url, + urlB64, }: { creator: string; decimals: number | bigint; @@ -756,9 +783,12 @@ export class AssetParams extends BaseModel { manager?: string; metadataHash?: string | Uint8Array; name?: string; + nameB64?: string | Uint8Array; reserve?: string; unitName?: string; + unitNameB64?: string | Uint8Array; url?: string; + urlB64?: string | Uint8Array; }) { super(); this.creator = creator; @@ -773,9 +803,21 @@ export class AssetParams extends BaseModel { ? new Uint8Array(Buffer.from(metadataHash, 'base64')) : metadataHash; this.name = name; + this.nameB64 = + typeof nameB64 === 'string' + ? new Uint8Array(Buffer.from(nameB64, 'base64')) + : nameB64; this.reserve = reserve; this.unitName = unitName; + this.unitNameB64 = + typeof unitNameB64 === 'string' + ? new Uint8Array(Buffer.from(unitNameB64, 'base64')) + : unitNameB64; this.url = url; + this.urlB64 = + typeof urlB64 === 'string' + ? new Uint8Array(Buffer.from(urlB64, 'base64')) + : urlB64; this.attribute_map = { creator: 'creator', @@ -787,9 +829,12 @@ export class AssetParams extends BaseModel { manager: 'manager', metadataHash: 'metadata-hash', name: 'name', + nameB64: 'name-b64', reserve: 'reserve', unitName: 'unit-name', + unitNameB64: 'unit-name-b64', url: 'url', + urlB64: 'url-b64', }; } } From dba255364fc2b496263f689f1bf9ef5f67714a2e Mon Sep 17 00:00:00 2001 From: Jason Paulos Date: Mon, 19 Jul 2021 16:32:42 -0700 Subject: [PATCH 9/9] v1.10.1 --- CHANGELOG.md | 16 ++++++++++++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a0c3693f..3246331c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,19 @@ +# 1.10.1 + +## Added + +- Add missing fields `msig` and `lsig` to `EncodedSignedTransaction` type +- Add the missing type `SignedTransaction`, which helped fix the `any` return value for `Transaction.from_obj_for_encoding` +- More internal types are now exported +- Support the new base64 asset fields in algod models +- Add ability to install the package from a git URL with npm + +## Fixed + +- Remove BigInt literals from package +- Support encoding transactions with a first round of zero +- Fix msgpack encoding of dryrun objects + # 1.10.0 ## Added diff --git a/package-lock.json b/package-lock.json index b1381d74b..332f76c5f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "algosdk", - "version": "1.10.0", + "version": "1.10.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "algosdk", - "version": "1.10.0", + "version": "1.10.1", "license": "MIT", "dependencies": { "algo-msgpack-with-bigint": "^2.1.1", diff --git a/package.json b/package.json index 489659509..7826468c5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "algosdk", - "version": "1.10.0", + "version": "1.10.1", "description": "The official JavaScript SDK for Algorand", "main": "dist/cjs/index.js", "module": "dist/esm/index.js",