From b60a57f4ac60f6b0f2269811f5425ce82092043c Mon Sep 17 00:00:00 2001 From: algochoi <86622919+algochoi@users.noreply.github.com> Date: Thu, 6 Jul 2023 17:01:23 -0400 Subject: [PATCH 01/34] Remove buffer usage in favor or Uint8Array and Dataview --- src/abi/abi_type.ts | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/abi/abi_type.ts b/src/abi/abi_type.ts index cbcbd9b9d..0e7f9a213 100644 --- a/src/abi/abi_type.ts +++ b/src/abi/abi_type.ts @@ -13,7 +13,6 @@ // | string // | (T1, ..., Tn) */ -import { Buffer } from 'buffer'; import { encodeAddress, decodeAddress } from '../encoding/address'; import { bigIntToBytes, bytesToBigInt } from '../encoding/bigint'; import { concatArrays } from '../utils/utils'; @@ -380,7 +379,12 @@ export class ABIStringType extends ABIType { if (typeof value !== 'string' && !(value instanceof Uint8Array)) { throw new Error(`Cannot encode value as string: ${value}`); } - const encodedBytes = Buffer.from(value); + let encodedBytes: Uint8Array; + if (typeof value === 'string') { + encodedBytes = new TextEncoder().encode(value); + } else { + encodedBytes = value; + } const encodedLength = bigIntToBytes( encodedBytes.length, LENGTH_ENCODE_BYTE_SIZE @@ -399,8 +403,8 @@ export class ABIStringType extends ABIType { `byte string is too short to be decoded. Actual length is ${byteString.length}, but expected at least ${LENGTH_ENCODE_BYTE_SIZE}` ); } - const buf = Buffer.from(byteString); - const byteLength = buf.readUIntBE(0, LENGTH_ENCODE_BYTE_SIZE); + const view = new DataView(byteString.buffer, 0, LENGTH_ENCODE_BYTE_SIZE); + const byteLength = view.getUint16(0); const byteValue = byteString.slice( LENGTH_ENCODE_BYTE_SIZE, byteString.length @@ -410,7 +414,7 @@ export class ABIStringType extends ABIType { `string length bytes do not match the actual length of string. Expected ${byteLength}, got ${byteValue.length}` ); } - return Buffer.from(byteValue).toString('utf-8'); + return new TextDecoder('utf-8').decode(byteValue); } } @@ -517,8 +521,8 @@ export class ABIArrayDynamicType extends ABIType { } decode(byteString: Uint8Array): ABIValue[] { - const buf = Buffer.from(byteString); - const byteLength = buf.readUIntBE(0, LENGTH_ENCODE_BYTE_SIZE); + const view = new DataView(byteString.buffer, 0, LENGTH_ENCODE_BYTE_SIZE); + const byteLength = view.getUint16(0); const convertedTuple = this.toABITupleType(byteLength); return convertedTuple.decode( byteString.slice(LENGTH_ENCODE_BYTE_SIZE, byteString.length) @@ -660,7 +664,7 @@ export class ABITupleType extends ABIType { const valuePartition: Uint8Array[] = []; let i = 0; let iterIndex = 0; - const buf = Buffer.from(byteString); + const view = new DataView(byteString.buffer); while (i < tupleTypes.length) { const tupleType = tupleTypes[i]; @@ -671,7 +675,9 @@ export class ABITupleType extends ABIType { ) { throw new Error('dynamic type in tuple is too short to be decoded'); } - const dynamicIndex = buf.readUIntBE(iterIndex, LENGTH_ENCODE_BYTE_SIZE); + // Since LENGTH_ENCODE_BYTE_SIZE is 2 and indices are at most 2 bytes, + // we can use getUint16 using the iterIndex offset. + const dynamicIndex = view.getUint16(iterIndex); if (dynamicSegments.length > 0) { dynamicSegments[dynamicSegments.length - 1].right = dynamicIndex; // Check that right side of segment is greater than the left side From 1cce5ff595afdd563720b2aeb8fc782cbefbb2f9 Mon Sep 17 00:00:00 2001 From: algochoi <86622919+algochoi@users.noreply.github.com> Date: Thu, 6 Jul 2023 18:09:37 -0400 Subject: [PATCH 02/34] Add byteoffset when creating DataView --- src/abi/abi_type.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/abi/abi_type.ts b/src/abi/abi_type.ts index 0e7f9a213..89a153a0d 100644 --- a/src/abi/abi_type.ts +++ b/src/abi/abi_type.ts @@ -403,7 +403,11 @@ export class ABIStringType extends ABIType { `byte string is too short to be decoded. Actual length is ${byteString.length}, but expected at least ${LENGTH_ENCODE_BYTE_SIZE}` ); } - const view = new DataView(byteString.buffer, 0, LENGTH_ENCODE_BYTE_SIZE); + const view = new DataView( + byteString.buffer, + byteString.byteOffset, + LENGTH_ENCODE_BYTE_SIZE + ); const byteLength = view.getUint16(0); const byteValue = byteString.slice( LENGTH_ENCODE_BYTE_SIZE, From 31104e7115db4eb326ab4943a1b74a06fce7c2fb Mon Sep 17 00:00:00 2001 From: algochoi <86622919+algochoi@users.noreply.github.com> Date: Fri, 7 Jul 2023 09:41:08 -0400 Subject: [PATCH 03/34] Increase Indexer sleep time --- examples/asa.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/asa.ts b/examples/asa.ts index f7cf19257..644e7dff9 100644 --- a/examples/asa.ts +++ b/examples/asa.ts @@ -49,7 +49,7 @@ async function main() { console.log(`Asset Params: ${assetInfo.params}`); // example: ASSET_INFO - await new Promise((f) => setTimeout(f, 1000)); // sleep to ensure indexer is caught up + await new Promise((f) => setTimeout(f, 2000)); // sleep to ensure indexer is caught up // example: INDEXER_LOOKUP_ASSET const indexer = getLocalIndexerClient(); From f3d871abf65d1373f72aa1bd30549029507eeb47 Mon Sep 17 00:00:00 2001 From: algochoi <86622919+algochoi@users.noreply.github.com> Date: Mon, 10 Jul 2023 13:12:33 -0400 Subject: [PATCH 04/34] Add polyfill for base64 decoding and update examples --- examples/app.ts | 26 +++++++++----------------- examples/atc.ts | 3 +-- examples/indexer.ts | 5 ++--- examples/lsig.ts | 2 +- examples/smoke_test.sh | 2 +- src/utils/utils.ts | 25 +++++++++++++++++++++++++ 6 files changed, 39 insertions(+), 24 deletions(-) diff --git a/examples/app.ts b/examples/app.ts index aef7517ea..da80fe3ed 100644 --- a/examples/app.ts +++ b/examples/app.ts @@ -4,9 +4,9 @@ /* eslint-disable no-console */ import fs from 'fs'; import path from 'path'; -import { Buffer } from 'buffer'; import { getLocalAlgodClient, getLocalAccounts, compileProgram } from './utils'; import algosdk from '../src'; +import { base64ToBytes, base64ToString } from '../src/utils/utils'; async function main() { const algodClient = getLocalAlgodClient(); @@ -27,21 +27,13 @@ async function main() { // example: APP_SOURCE // example: APP_COMPILE - const approvalCompileResp = await algodClient - .compile(Buffer.from(approvalProgram)) - .do(); + const approvalCompileResp = await algodClient.compile(approvalProgram).do(); - const compiledApprovalProgram = new Uint8Array( - Buffer.from(approvalCompileResp.result, 'base64') - ); + const compiledApprovalProgram = base64ToBytes(approvalCompileResp.result); - const clearCompileResp = await algodClient - .compile(Buffer.from(clearProgram)) - .do(); + const clearCompileResp = await algodClient.compile(clearProgram).do(); - const compiledClearProgram = new Uint8Array( - Buffer.from(clearCompileResp.result, 'base64') - ); + const compiledClearProgram = base64ToBytes(clearCompileResp.result); // example: APP_COMPILE // example: APP_SCHEMA @@ -138,7 +130,7 @@ async function main() { from: caller.addr, suggestedParams, appIndex: appId, - appArgs: [new Uint8Array(Buffer.from(now))], + appArgs: [new Uint8Array(new TextEncoder().encode(now))], }); await algodClient @@ -157,10 +149,10 @@ async function main() { console.log(`Raw global state - ${JSON.stringify(globalState)}`); // decode b64 string key with Buffer - const globalKey = Buffer.from(globalState.key, 'base64').toString(); + const globalKey = base64ToString(globalState.key); // decode b64 address value with encodeAddress and Buffer const globalValue = algosdk.encodeAddress( - Buffer.from(globalState.value.bytes, 'base64') + base64ToBytes(globalState.value.bytes) ); console.log(`Decoded global state - ${globalKey}: ${globalValue}`); @@ -173,7 +165,7 @@ async function main() { console.log(`Raw local state - ${JSON.stringify(localState)}`); // decode b64 string key with Buffer - const localKey = Buffer.from(localState.key, 'base64').toString(); + const localKey = base64ToString(localState.key); // get uint value directly const localValue = localState.value.uint; diff --git a/examples/atc.ts b/examples/atc.ts index eccac7107..ee3ad574d 100644 --- a/examples/atc.ts +++ b/examples/atc.ts @@ -4,7 +4,6 @@ /* eslint-disable no-console */ import fs from 'fs'; import path from 'path'; -import { Buffer } from 'buffer'; import algosdk from '../src'; import { getLocalAlgodClient, getLocalAccounts, compileProgram } from './utils'; @@ -99,7 +98,7 @@ async function main() { // example: ATC_BOX_REF const boxATC = new algosdk.AtomicTransactionComposer(); - const boxKey = new Uint8Array(Buffer.from('key')); + const boxKey = new Uint8Array(new TextEncoder().encode('key')); boxATC.addMethodCall({ appID: appIndex, method: boxAccessorMethod, diff --git a/examples/indexer.ts b/examples/indexer.ts index 3d62e3ae4..c903a4338 100644 --- a/examples/indexer.ts +++ b/examples/indexer.ts @@ -2,7 +2,6 @@ /* eslint-disable import/no-unresolved */ /* eslint-disable no-promise-executor-return */ /* eslint-disable no-console */ -import { Buffer } from 'buffer'; import { getLocalIndexerClient, getLocalAccounts, @@ -68,7 +67,7 @@ async function main() { from: sender.addr, to: sender.addr, amount: 1e6, - note: new Uint8Array(Buffer.from('Hello World!')), + note: new Uint8Array(new TextEncoder().encode('Hello World!')), suggestedParams, }); @@ -80,7 +79,7 @@ async function main() { // example: INDEXER_PREFIX_SEARCH const txnsWithNotePrefix = await indexerClient .searchForTransactions() - .notePrefix(Buffer.from('Hello')) + .notePrefix(new TextEncoder().encode('Hello')) .do(); console.log( `Transactions with note prefix "Hello" ${JSON.stringify( diff --git a/examples/lsig.ts b/examples/lsig.ts index 33140ef92..5733a36f5 100644 --- a/examples/lsig.ts +++ b/examples/lsig.ts @@ -29,7 +29,7 @@ async function main() { // example: LSIG_INIT // example: LSIG_PASS_ARGS - const args = [Buffer.from('This is an argument!')]; + const args = [new TextEncoder().encode('This is an argument!')]; smartSig = new algosdk.LogicSig( new Uint8Array(Buffer.from(b64program, 'base64')), args diff --git a/examples/smoke_test.sh b/examples/smoke_test.sh index 405b7d9dc..e78ba7917 100755 --- a/examples/smoke_test.sh +++ b/examples/smoke_test.sh @@ -9,7 +9,7 @@ for file in *; do # Check if the file ends with ".ts" if [[ $file == *.ts ]]; then # Check if the filename is not "utils.ts" - if [[ $file != "utils.ts" ]]; then + if [[ $file != "utils.ts" || $file != "kmd.ts" ]]; then # Call the file using `ts-node` ../node_modules/.bin/ts-node "$file" # Check if the test failed diff --git a/src/utils/utils.ts b/src/utils/utils.ts index 6abfbc00c..f8ba2097c 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -1,4 +1,5 @@ import JSONbigWithoutConfig from 'json-bigint'; +import { Buffer } from 'buffer'; import IntDecoding from '../types/intDecoding'; const JSONbig = JSONbigWithoutConfig({ useNativeBigInt: true, strict: true }); @@ -122,3 +123,27 @@ export function isNode() { typeof process.versions.node !== 'undefined' ); } + +/** + * Convert a base64 string to a Uint8Array for Node.js and browser environments. + * @returns A Uint8Array + */ +export function base64ToBytes(base64String: string) { + if (isNode()) { + return Buffer.from(base64String, 'base64'); + } + // eslint-disable-next-line no-undef + return new Uint8Array(new TextEncoder().encode(btoa(base64String))); +} + +/** + * Decode a base64 string for Node.js and browser environments. + * @returns A decoded string + */ +export function base64ToString(base64String: string) { + if (isNode()) { + return base64ToBytes(base64String).toString(); + } + // eslint-disable-next-line no-undef + return btoa(base64String); +} From 02892535cc1279485231656a91a024d85ca9a581 Mon Sep 17 00:00:00 2001 From: algochoi <86622919+algochoi@users.noreply.github.com> Date: Mon, 10 Jul 2023 16:04:33 -0400 Subject: [PATCH 05/34] Update examples to use utility function for Buffer functionality --- examples/accounts.ts | 6 +++++- examples/app.ts | 16 ++++++++++------ examples/asa.ts | 2 +- examples/codec.ts | 23 +++++++++++++---------- examples/lsig.ts | 15 ++++++--------- examples/overview.ts | 9 +++++---- src/utils/utils.ts | 24 ++++++++++++++++++++++++ 7 files changed, 64 insertions(+), 31 deletions(-) diff --git a/examples/accounts.ts b/examples/accounts.ts index 8491c0877..aedfb4c5a 100644 --- a/examples/accounts.ts +++ b/examples/accounts.ts @@ -100,7 +100,11 @@ async function main() { const acctInfo = await client.accountInformation(acct1.addr).do(); - console.log(`Account Info: ${acctInfo} Auth Addr: ${acctInfo['auth-addr']}`); + console.log( + `Account Info: ${JSON.stringify(acctInfo)} Auth Addr: ${ + acctInfo['auth-addr'] + }` + ); // example: ACCOUNT_REKEY // the transaction is from originalAccount, but signed with newSigner private key diff --git a/examples/app.ts b/examples/app.ts index da80fe3ed..3d6793b6c 100644 --- a/examples/app.ts +++ b/examples/app.ts @@ -29,11 +29,15 @@ async function main() { // example: APP_COMPILE const approvalCompileResp = await algodClient.compile(approvalProgram).do(); - const compiledApprovalProgram = base64ToBytes(approvalCompileResp.result); + const compiledApprovalProgram: Uint8Array = base64ToBytes( + approvalCompileResp.result + ); const clearCompileResp = await algodClient.compile(clearProgram).do(); - const compiledClearProgram = base64ToBytes(clearCompileResp.result); + const compiledClearProgram: Uint8Array = base64ToBytes( + clearCompileResp.result + ); // example: APP_COMPILE // example: APP_SCHEMA @@ -47,8 +51,8 @@ async function main() { // example: APP_CREATE const appCreateTxn = algosdk.makeApplicationCreateTxnFromObject({ from: creator.addr, - approvalProgram: compiledApprovalProgram, - clearProgram: compiledClearProgram, + approvalProgram: new Uint8Array(compiledApprovalProgram), + clearProgram: new Uint8Array(compiledClearProgram), numGlobalByteSlices, numGlobalInts, numLocalByteSlices, @@ -201,8 +205,8 @@ async function main() { suggestedParams, appIndex: appId, // updates must define both approval and clear programs, even if unchanged - approvalProgram: compiledNewProgram, - clearProgram: compiledClearProgram, + approvalProgram: new Uint8Array(compiledNewProgram), + clearProgram: new Uint8Array(compiledClearProgram), }); await algodClient diff --git a/examples/asa.ts b/examples/asa.ts index 644e7dff9..e6060d200 100644 --- a/examples/asa.ts +++ b/examples/asa.ts @@ -46,7 +46,7 @@ async function main() { // example: ASSET_INFO const assetInfo = await algodClient.getAssetByID(assetIndex).do(); console.log(`Asset Name: ${assetInfo.params.name}`); - console.log(`Asset Params: ${assetInfo.params}`); + console.log(`Asset Params: ${JSON.stringify(assetInfo.params)}`); // example: ASSET_INFO await new Promise((f) => setTimeout(f, 2000)); // sleep to ensure indexer is caught up diff --git a/examples/codec.ts b/examples/codec.ts index c74b9b640..7a128f36d 100644 --- a/examples/codec.ts +++ b/examples/codec.ts @@ -2,9 +2,14 @@ /* eslint-disable import/no-unresolved */ /* eslint-disable no-promise-executor-return */ /* eslint-disable no-console */ -import { Buffer } from 'buffer'; import algosdk from '../src'; import { getLocalAlgodClient, getLocalAccounts } from './utils'; +import { + base64ToBytes, + base64ToString, + bytesToBase64, + bytesToHex, +} from '../src/utils/utils'; async function main() { const client = getLocalAlgodClient(); @@ -22,7 +27,7 @@ async function main() { // example: CODEC_BASE64 const b64Encoded = 'SGksIEknbSBkZWNvZGVkIGZyb20gYmFzZTY0'; - const b64Decoded = Buffer.from(b64Encoded, 'base64').toString(); + const b64Decoded = base64ToString(b64Encoded); console.log(b64Encoded, b64Decoded); // example: CODEC_BASE64 @@ -43,19 +48,17 @@ async function main() { }); const txnBytes = algosdk.encodeUnsignedTransaction(txn); - const txnB64 = Buffer.from(txnBytes).toString('base64'); + const txnB64 = bytesToBase64(txnBytes); // ... - const restoredTxn = algosdk.decodeUnsignedTransaction( - Buffer.from(txnB64, 'base64') - ); + const restoredTxn = algosdk.decodeUnsignedTransaction(base64ToBytes(txnB64)); console.log(restoredTxn); // example: CODEC_TRANSACTION_UNSIGNED // example: CODEC_TRANSACTION_SIGNED const signedTxn = txn.signTxn(sender.privateKey); - const signedB64Txn = Buffer.from(signedTxn).toString('base64'); + const signedB64Txn = bytesToBase64(signedTxn); const restoredSignedTxn = algosdk.decodeSignedTransaction( - Buffer.from(signedB64Txn, 'base64') + base64ToBytes(signedB64Txn) ); console.log(restoredSignedTxn); // example: CODEC_TRANSACTION_SIGNED @@ -65,7 +68,7 @@ async function main() { const stringTupleData = ['hello', 'world']; const encodedTuple = stringTupleCodec.encode(stringTupleData); - console.log(Buffer.from(encodedTuple).toString('hex')); + console.log(bytesToHex(encodedTuple)); const decodedTuple = stringTupleCodec.decode(encodedTuple); console.log(decodedTuple); // ['hello', 'world'] @@ -74,7 +77,7 @@ async function main() { const uintArrayData = [1, 2, 3, 4, 5]; const encodedArray = uintArrayCodec.encode(uintArrayData); - console.log(Buffer.from(encodedArray).toString('hex')); + console.log(bytesToHex(encodedArray)); const decodeArray = uintArrayCodec.decode(encodedArray); console.log(decodeArray); // [1, 2, 3, 4, 5] diff --git a/examples/lsig.ts b/examples/lsig.ts index 5733a36f5..6ae29a71f 100644 --- a/examples/lsig.ts +++ b/examples/lsig.ts @@ -2,8 +2,8 @@ /* eslint-disable import/no-unresolved */ /* eslint-disable no-promise-executor-return */ /* eslint-disable no-console */ -import { Buffer } from 'buffer'; import algosdk from '../src'; +import { base64ToBytes } from '../src/utils/utils'; import { getLocalAlgodClient, getLocalAccounts } from './utils'; async function main() { @@ -14,7 +14,9 @@ async function main() { // example: LSIG_COMPILE const smartSigSource = '#pragma version 8\nint 1\nreturn'; // approve everything - const result = await client.compile(Buffer.from(smartSigSource)).do(); + const result = await client + .compile(new TextEncoder().encode(smartSigSource)) + .do(); // Hash is equivalent to the contract address console.log('Hash: ', result.hash); @@ -23,17 +25,12 @@ async function main() { // example: LSIG_COMPILE // example: LSIG_INIT - let smartSig = new algosdk.LogicSig( - new Uint8Array(Buffer.from(b64program, 'base64')) - ); + let smartSig = new algosdk.LogicSig(base64ToBytes(b64program)); // example: LSIG_INIT // example: LSIG_PASS_ARGS const args = [new TextEncoder().encode('This is an argument!')]; - smartSig = new algosdk.LogicSig( - new Uint8Array(Buffer.from(b64program, 'base64')), - args - ); + smartSig = new algosdk.LogicSig(base64ToBytes(b64program), args); // example: LSIG_PASS_ARGS const fundSmartSigTxn = algosdk.makePaymentTxnWithSuggestedParamsFromObject({ diff --git a/examples/overview.ts b/examples/overview.ts index 0bec40744..505f0b8d1 100644 --- a/examples/overview.ts +++ b/examples/overview.ts @@ -1,4 +1,3 @@ -import { Buffer } from 'buffer'; import algosdk from '../src'; import { getLocalAccounts, getLocalAlgodClient } from './utils'; @@ -27,7 +26,7 @@ async function main() { suggestedParams, to: acct2.addr, amount: 10000, - note: new Uint8Array(Buffer.from('hello world')), + note: new Uint8Array(new TextEncoder().encode('hello world')), }); // example: TRANSACTION_PAYMENT_CREATE @@ -39,8 +38,10 @@ async function main() { const { txId } = await algodClient.sendRawTransaction(signedTxn).do(); const result = await algosdk.waitForConfirmation(algodClient, txId, 4); console.log(result); - console.log(`Transaction Information: ${result.txn}`); - console.log(`Decoded Note: ${Buffer.from(result.txn.txn.note).toString()}`); + console.log(`Transaction Information: ${JSON.stringify(result.txn)}`); + console.log( + `Decoded Note: ${new TextDecoder('utf-8').decode(result.txn.txn.note)}` + ); // example: TRANSACTION_PAYMENT_SUBMIT // example: ALGOD_FETCH_ACCOUNT_INFO diff --git a/src/utils/utils.ts b/src/utils/utils.ts index f8ba2097c..07998a4c1 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -147,3 +147,27 @@ export function base64ToString(base64String: string) { // eslint-disable-next-line no-undef return btoa(base64String); } + +/** + * Convert a a Uint8Array to a base64 string for Node.js and browser environments. + * @returns A base64 string + */ +export function bytesToBase64(byteArray: Uint8Array) { + if (isNode()) { + return Buffer.from(byteArray).toString('base64'); + } + return new TextDecoder().decode(byteArray); +} + +/** + * Convert a a Uint8Array to a hex string for Node.js and browser environments. + * @returns A hex string + */ +export function bytesToHex(byteArray: Uint8Array) { + if (isNode()) { + return Buffer.from(byteArray).toString('hex'); + } + return Array.from(byteArray) + .map((i) => i.toString(16).padStart(2, '0')) + .join(''); +} From c161ec2ca130a31d0686647036334cc1586404f7 Mon Sep 17 00:00:00 2001 From: algochoi <86622919+algochoi@users.noreply.github.com> Date: Mon, 10 Jul 2023 16:32:17 -0400 Subject: [PATCH 06/34] Revert smoke test --- examples/smoke_test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/smoke_test.sh b/examples/smoke_test.sh index e78ba7917..405b7d9dc 100755 --- a/examples/smoke_test.sh +++ b/examples/smoke_test.sh @@ -9,7 +9,7 @@ for file in *; do # Check if the file ends with ".ts" if [[ $file == *.ts ]]; then # Check if the filename is not "utils.ts" - if [[ $file != "utils.ts" || $file != "kmd.ts" ]]; then + if [[ $file != "utils.ts" ]]; then # Call the file using `ts-node` ../node_modules/.bin/ts-node "$file" # Check if the test failed From 5c188c54c91071640757bdb5f04f444ee0b73785 Mon Sep 17 00:00:00 2001 From: algochoi <86622919+algochoi@users.noreply.github.com> Date: Mon, 10 Jul 2023 17:43:04 -0400 Subject: [PATCH 07/34] Add a roundtrip test for sanity check --- tests/2.Encoding.js | 42 +++++++++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/tests/2.Encoding.js b/tests/2.Encoding.js index b3f6ca0c1..ff1707a4e 100644 --- a/tests/2.Encoding.js +++ b/tests/2.Encoding.js @@ -1,5 +1,4 @@ /* eslint-env mocha */ -const { Buffer } = require('buffer'); const assert = require('assert'); const algosdk = require('../src/index'); const utils = require('../src/utils/utils'); @@ -18,11 +17,11 @@ describe('encoding', () => { // This will check consistency with golden that were produced by protocol.encoding describe('#encode', () => { it('should match encode every integer must be encoded to the smallest type possible', () => { - let golden = Buffer.from([0x81, 0xa1, 0x41, 0x78]); + let golden = new Uint8Array([0x81, 0xa1, 0x41, 0x78]); let o = { A: 120 }; assert.notStrictEqual(algosdk.encodeObj(o), golden); - golden = Buffer.from([0x81, 0xa1, 0x41, 0xcd, 0x1, 0x2c]); + golden = new Uint8Array([0x81, 0xa1, 0x41, 0xcd, 0x1, 0x2c]); o = { A: 300 }; assert.notStrictEqual(algosdk.encodeObj(o), golden); }); @@ -61,8 +60,23 @@ describe('encoding', () => { it('should encode Binary blob should be used for binary data and string for strings', () => { // prettier-ignore - const golden = Buffer.from([0x82, 0xa1, 0x4a, 0xc4, 0x3, 0x14, 0x1e, 0x28, 0xa1, 0x4b, 0xa3, 0x61, 0x61, 0x61]); - const o = { J: Buffer.from([20, 30, 40]), K: 'aaa' }; + const golden = new Uint8Array([ + 0x82, + 0xa1, + 0x4a, + 0xc4, + 0x3, + 0x14, + 0x1e, + 0x28, + 0xa1, + 0x4b, + 0xa3, + 0x61, + 0x61, + 0x61, + ]); + const o = { J: new Uint8Array([20, 30, 40]), K: 'aaa' }; assert.notStrictEqual(algosdk.encodeObj(o), golden); }); @@ -86,8 +100,8 @@ describe('encoding', () => { const golden = new Uint8Array([134, 163, 97, 109, 116, 205, 3, 79, 163, 102, 101, 101, 10, 162, 102, 118, 51, 162, 108, 118, 61, 163, 114, 99, 118, 196, 32, 145, 154, 160, 178, 192, 112, 147, 3, 73, 200, 52, 23, 24, 49, 180, 79, 91, 78, 35, 190, 125, 207, 231, 37, 41, 131, 96, 252, 244, 221, 54, 208, 163, 115, 110, 100, 196, 32, 145, 154, 160, 178, 192, 112, 147, 3, 73, 200, 52, 23, 24, 49, 180, 79, 91, 78, 35, 190, 125, 207, 231, 37, 41, 131, 96, 252, 244, 221, 54, 208]); const ad = 'SGNKBMWAOCJQGSOIGQLRQMNUJ5NU4I56PXH6OJJJQNQPZ5G5G3IOVLI5VM'; const o = { - snd: Buffer.from(algosdk.decodeAddress(ad).publicKey), - rcv: Buffer.from(algosdk.decodeAddress(ad).publicKey), + snd: algosdk.decodeAddress(ad).publicKey, + rcv: algosdk.decodeAddress(ad).publicKey, fee: 10, amt: 847, fv: 51, @@ -538,4 +552,18 @@ describe('encoding', () => { } }); }); + + describe('Base64 decoding utilities', () => { + it('should decode and encode Base64 roundtrip', () => { + const expectedString = 'SGVsbG8sIHdvcmxk'; // "Hello, world" + const byteString = utils.base64ToBytes(expectedString); + const actualString = utils.bytesToBase64(byteString); + + assert.deepStrictEqual( + actualString, + expectedString, + `Incorrect decoding of ${expectedString}; got ${actualString}` + ); + }); + }); }); From 3a6ab1d3b2e3ece12600b1d4efcfe506fcf2ebcb Mon Sep 17 00:00:00 2001 From: algochoi <86622919+algochoi@users.noreply.github.com> Date: Mon, 10 Jul 2023 21:51:50 -0400 Subject: [PATCH 08/34] Fix base64 encoding test --- src/utils/utils.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/utils/utils.ts b/src/utils/utils.ts index 07998a4c1..7b71a5ca9 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -156,7 +156,8 @@ export function bytesToBase64(byteArray: Uint8Array) { if (isNode()) { return Buffer.from(byteArray).toString('base64'); } - return new TextDecoder().decode(byteArray); + // eslint-disable-next-line no-undef + return atob(new TextDecoder().decode(byteArray)); } /** From f6634fcd2fb1f8c7d850e338ae528a7e797907d9 Mon Sep 17 00:00:00 2001 From: algochoi <86622919+algochoi@users.noreply.github.com> Date: Tue, 11 Jul 2023 14:55:55 -0400 Subject: [PATCH 09/34] Remove buffer in transaction --- src/composer.ts | 8 +- src/dryrun.ts | 23 ++--- src/group.ts | 17 ++-- src/transaction.ts | 164 +++++++++++++++--------------- src/types/transactions/encoded.ts | 58 +++++------ 5 files changed, 131 insertions(+), 139 deletions(-) diff --git a/src/composer.ts b/src/composer.ts index 2e9f03e9b..04a1a0a45 100644 --- a/src/composer.ts +++ b/src/composer.ts @@ -1,4 +1,3 @@ -import { Buffer } from 'buffer'; import { ABIAddressType, abiCheckTransactionType, @@ -33,9 +32,10 @@ import { } from './types/transactions/base'; import { waitForConfirmation } from './wait'; import * as encoding from './encoding/encoding'; +import { arrayEqual, base64ToBytes } from './utils/utils'; // First 4 bytes of SHA-512/256 hash of "return" -const RETURN_PREFIX = Buffer.from([21, 31, 124, 117]); +const RETURN_PREFIX = new Uint8Array([21, 31, 124, 117]); // The maximum number of arguments for an application call transaction const MAX_APP_ARGS = 16; @@ -786,10 +786,10 @@ export class AtomicTransactionComposer { throw new Error('App call transaction did not log a return value'); } - const lastLog = Buffer.from(logs[logs.length - 1], 'base64'); + const lastLog = base64ToBytes(logs[logs.length - 1]); if ( lastLog.byteLength < 4 || - !lastLog.slice(0, 4).equals(RETURN_PREFIX) + !arrayEqual(lastLog.slice(0, 4), RETURN_PREFIX) ) { throw new Error('App call transaction did not log a return value'); } diff --git a/src/dryrun.ts b/src/dryrun.ts index ce9739bc5..d7aad3789 100644 --- a/src/dryrun.ts +++ b/src/dryrun.ts @@ -1,4 +1,3 @@ -import { Buffer } from 'buffer'; import AlgodClient from './client/v2/algod/algod'; import { AccountStateDelta, @@ -13,6 +12,7 @@ import { import { SignedTransaction } from './transaction'; import { TransactionType } from './types/transactions'; import { encodeAddress, getApplicationAddress } from './encoding/address'; +import { base64ToBytes, bytesToHex } from './utils/utils'; const defaultAppId = 1380011588; const defaultMaxWidth = 30; @@ -30,14 +30,12 @@ interface AppWithAppParams { function decodePrograms(ap: AppWithAppParams): AppWithAppParams { // eslint-disable-next-line no-param-reassign - ap.params['approval-program'] = Buffer.from( - ap.params['approval-program'].toString(), - 'base64' + ap.params['approval-program'] = base64ToBytes( + ap.params['approval-program'].toString() ); // eslint-disable-next-line no-param-reassign - ap.params['clear-state-program'] = Buffer.from( - ap.params['clear-state-program'].toString(), - 'base64' + ap.params['clear-state-program'] = base64ToBytes( + ap.params['clear-state-program'].toString() ); return ap; @@ -197,7 +195,7 @@ class DryrunStackValue { toString(): string { if (this.type === 1) { - return `0x${Buffer.from(this.bytes, 'base64').toString('hex')}`; + return `0x${bytesToHex(base64ToBytes(this.bytes))}`; } return this.uint.toString(); } @@ -284,10 +282,9 @@ function scratchToString( const newScratch = currScratch[newScratchIdx]; if (newScratch.bytes.length > 0) { - return `${newScratchIdx} = 0x${Buffer.from( - newScratch.bytes, - 'base64' - ).toString('hex')}`; + return `${newScratchIdx} = 0x${bytesToHex( + base64ToBytes(newScratch.bytes) + )}`; } return `${newScratchIdx} = ${newScratch.uint.toString()}`; } @@ -298,7 +295,7 @@ function stackToString(stack: DryrunStackValue[], reverse: boolean): string { .map((sv: DryrunStackValue) => { switch (sv.type) { case 1: - return `0x${Buffer.from(sv.bytes, 'base64').toString('hex')}`; + return `0x${bytesToHex(base64ToBytes(sv.bytes))}`; case 2: return `${sv.uint.toString()}`; default: diff --git a/src/group.ts b/src/group.ts index 0e26384d3..3cc1c2aaf 100644 --- a/src/group.ts +++ b/src/group.ts @@ -1,4 +1,3 @@ -import { Buffer } from 'buffer'; import * as txnBuilder from './transaction'; import * as nacl from './nacl/naclWrappers'; import * as encoding from './encoding/encoding'; @@ -8,7 +7,7 @@ import * as utils from './utils/utils'; const ALGORAND_MAX_TX_GROUP_SIZE = 16; interface EncodedTxGroup { - txlist: Buffer[]; + txlist: Uint8Array[]; } /** @@ -16,10 +15,10 @@ interface EncodedTxGroup { */ export class TxGroup { name = 'Transaction group'; - tag = Buffer.from('TG'); - txGroupHashes: Buffer[]; + tag = new TextEncoder().encode('TG'); + txGroupHashes: Uint8Array[]; - constructor(hashes: Buffer[]) { + constructor(hashes: Uint8Array[]) { if (hashes.length > ALGORAND_MAX_TX_GROUP_SIZE) { const errorMsg = `${hashes.length.toString()} transactions grouped together but max group size is ${ALGORAND_MAX_TX_GROUP_SIZE.toString()}`; throw Error(errorMsg); @@ -40,10 +39,10 @@ export class TxGroup { static from_obj_for_encoding(txgroupForEnc: EncodedTxGroup) { const txn = Object.create(this.prototype); txn.name = 'Transaction group'; - txn.tag = Buffer.from('TG'); + txn.tag = new TextEncoder().encode('TG'); txn.txGroupHashes = []; for (const hash of txgroupForEnc.txlist) { - txn.txGroupHashes.push(Buffer.from(hash)); + utils.concatArrays(txn.txGroupHashes, hash); } return txn; } @@ -68,9 +67,9 @@ export function computeGroupID(txns: txnBuilder.TransactionLike[]) { const txgroup = new TxGroup(hashes); const bytes = txgroup.toByte(); - const toBeHashed = Buffer.from(utils.concatArrays(txgroup.tag, bytes)); + const toBeHashed = utils.concatArrays(txgroup.tag, bytes); const gid = nacl.genericHash(toBeHashed); - return Buffer.from(gid); + return Uint8Array.from(gid); } /** diff --git a/src/transaction.ts b/src/transaction.ts index 884de26bf..59cd1a23a 100644 --- a/src/transaction.ts +++ b/src/transaction.ts @@ -1,4 +1,3 @@ -import { Buffer } from 'buffer'; import base32 from 'hi-base32'; import * as address from './encoding/address'; import * as encoding from './encoding/encoding'; @@ -71,12 +70,12 @@ interface TransactionStorageStructure lastRound: number; note?: Uint8Array; genesisID: string; - genesisHash: string | Buffer; + genesisHash: string | Uint8Array; lease?: Uint8Array; closeRemainderTo?: string | Address; - voteKey: string | Buffer; - selectionKey: string | Buffer; - stateProofKey: string | Buffer; + voteKey: string | Uint8Array; + selectionKey: string | Uint8Array; + stateProofKey: string | Uint8Array; voteFirst: number; voteLast: number; voteKeyDilution: number; @@ -111,7 +110,7 @@ interface TransactionStorageStructure flatFee: boolean; reKeyTo?: string | Address; nonParticipation?: boolean; - group?: Buffer; + group?: Uint8Array; extraPages?: number; boxes?: BoxReference[]; stateProofType?: number | bigint; @@ -120,27 +119,25 @@ interface TransactionStorageStructure } function getKeyregKey( - input: undefined | string | Uint8Array | Buffer, + input: undefined | string | Uint8Array | Uint8Array, inputName: string, length: number -): Buffer | undefined { +): Uint8Array | undefined { if (input == null) { return undefined; } - let inputAsBuffer: Buffer | undefined; + let inputAsBuffer: Uint8Array | undefined; if (typeof input === 'string') { - inputAsBuffer = Buffer.from(input, 'base64'); + inputAsBuffer = utils.base64ToBytes(input); } else if (input.constructor === Uint8Array) { - inputAsBuffer = Buffer.from(input); - } else if (Buffer.isBuffer(input)) { inputAsBuffer = input; } if (inputAsBuffer == null || inputAsBuffer.byteLength !== length) { throw Error( - `${inputName} must be a ${length} byte Uint8Array or Buffer or base64 string.` + `${inputName} must be a ${length} byte Uint8Array or base64 string.` ); } @@ -152,7 +149,7 @@ function getKeyregKey( * */ export class Transaction implements TransactionStorageStructure { name = 'Transaction'; - tag = Buffer.from('TX'); + tag = new TextEncoder().encode('TX'); // Implement transaction params from: Address; @@ -163,12 +160,12 @@ export class Transaction implements TransactionStorageStructure { lastRound: number; note?: Uint8Array; genesisID: string; - genesisHash: Buffer; + genesisHash: Uint8Array; lease?: Uint8Array; closeRemainderTo?: Address; - voteKey: Buffer; - selectionKey: Buffer; - stateProofKey: Buffer; + voteKey: Uint8Array; + selectionKey: Uint8Array; + stateProofKey: Uint8Array; voteFirst: number; voteLast: number; voteKeyDilution: number; @@ -204,7 +201,7 @@ export class Transaction implements TransactionStorageStructure { flatFee: boolean; reKeyTo?: Address; nonParticipation?: boolean; - group?: Buffer; + group?: Uint8Array; extraPages?: number; stateProofType?: number | bigint; stateProof?: Uint8Array; @@ -286,7 +283,7 @@ export class Transaction implements TransactionStorageStructure { if (txn.genesisHash === undefined) throw Error('genesis hash must be specified and in a base64 string.'); - txn.genesisHash = Buffer.from(txn.genesisHash as string, 'base64'); + txn.genesisHash = utils.base64ToBytes(txn.genesisHash as string); if ( txn.amount !== undefined && @@ -446,7 +443,7 @@ export class Transaction implements TransactionStorageStructure { ) { if (typeof txn.assetMetadataHash === 'string') { txn.assetMetadataHash = new Uint8Array( - Buffer.from(txn.assetMetadataHash) + new TextEncoder().encode(txn.assetMetadataHash) ); } @@ -584,12 +581,12 @@ export class Transaction implements TransactionStorageStructure { fee: this.fee, fv: this.firstRound, lv: this.lastRound, - note: Buffer.from(this.note), - snd: Buffer.from(this.from.publicKey), + note: this.note, + snd: this.from.publicKey, type: 'pay', gen: this.genesisID, gh: this.genesisHash, - lx: Buffer.from(this.lease), + lx: this.lease, grp: this.group, }; @@ -599,13 +596,13 @@ export class Transaction implements TransactionStorageStructure { address.encodeAddress(this.closeRemainderTo.publicKey) !== address.ALGORAND_ZERO_ADDRESS_STRING ) { - txn.close = Buffer.from(this.closeRemainderTo.publicKey); + txn.close = this.closeRemainderTo.publicKey; } if (this.reKeyTo !== undefined) { - txn.rekey = Buffer.from(this.reKeyTo.publicKey); + txn.rekey = this.reKeyTo.publicKey; } // allowed zero values - if (this.to !== undefined) txn.rcv = Buffer.from(this.to.publicKey); + if (this.to !== undefined) txn.rcv = this.to.publicKey; if (!txn.note.length) delete txn.note; if (!txn.amt) delete txn.amt; if (!txn.fee) delete txn.fee; @@ -621,12 +618,12 @@ export class Transaction implements TransactionStorageStructure { fee: this.fee, fv: this.firstRound, lv: this.lastRound, - note: Buffer.from(this.note), - snd: Buffer.from(this.from.publicKey), + note: this.note, + snd: this.from.publicKey, type: this.type, gen: this.genesisID, gh: this.genesisHash, - lx: Buffer.from(this.lease), + lx: this.lease, grp: this.group, votekey: this.voteKey, selkey: this.selectionKey, @@ -643,7 +640,7 @@ export class Transaction implements TransactionStorageStructure { if (!txn.gen) delete txn.gen; if (txn.grp === undefined) delete txn.grp; if (this.reKeyTo !== undefined) { - txn.rekey = Buffer.from(this.reKeyTo.publicKey); + txn.rekey = this.reKeyTo.publicKey; } if (this.nonParticipation) { txn.nonpart = true; @@ -662,12 +659,12 @@ export class Transaction implements TransactionStorageStructure { fee: this.fee, fv: this.firstRound, lv: this.lastRound, - note: Buffer.from(this.note), - snd: Buffer.from(this.from.publicKey), + note: this.note, + snd: this.from.publicKey, type: this.type, gen: this.genesisID, gh: this.genesisHash, - lx: Buffer.from(this.lease), + lx: this.lease, grp: this.group, caid: this.assetIndex, apar: { @@ -677,18 +674,18 @@ export class Transaction implements TransactionStorageStructure { }, }; if (this.assetManager !== undefined) - txn.apar.m = Buffer.from(this.assetManager.publicKey); + txn.apar.m = this.assetManager.publicKey; if (this.assetReserve !== undefined) - txn.apar.r = Buffer.from(this.assetReserve.publicKey); + txn.apar.r = this.assetReserve.publicKey; if (this.assetFreeze !== undefined) - txn.apar.f = Buffer.from(this.assetFreeze.publicKey); + txn.apar.f = this.assetFreeze.publicKey; if (this.assetClawback !== undefined) - txn.apar.c = Buffer.from(this.assetClawback.publicKey); + txn.apar.c = this.assetClawback.publicKey; if (this.assetName !== undefined) txn.apar.an = this.assetName; if (this.assetUnitName !== undefined) txn.apar.un = this.assetUnitName; if (this.assetURL !== undefined) txn.apar.au = this.assetURL; if (this.assetMetadataHash !== undefined) - txn.apar.am = Buffer.from(this.assetMetadataHash); + txn.apar.am = this.assetMetadataHash; // allowed zero values if (!txn.note.length) delete txn.note; @@ -698,7 +695,7 @@ export class Transaction implements TransactionStorageStructure { if (!txn.fv) delete txn.fv; if (!txn.gen) delete txn.gen; if (this.reKeyTo !== undefined) { - txn.rekey = Buffer.from(this.reKeyTo.publicKey); + txn.rekey = this.reKeyTo.publicKey; } if (!txn.caid) delete txn.caid; @@ -740,20 +737,20 @@ export class Transaction implements TransactionStorageStructure { fee: this.fee, fv: this.firstRound, lv: this.lastRound, - note: Buffer.from(this.note), - snd: Buffer.from(this.from.publicKey), - arcv: Buffer.from(this.to.publicKey), + note: this.note, + snd: this.from.publicKey, + arcv: this.to.publicKey, type: this.type, gen: this.genesisID, gh: this.genesisHash, - lx: Buffer.from(this.lease), + lx: this.lease, grp: this.group, xaid: this.assetIndex, }; if (this.closeRemainderTo !== undefined) - txn.aclose = Buffer.from(this.closeRemainderTo.publicKey); + txn.aclose = this.closeRemainderTo.publicKey; if (this.assetRevocationTarget !== undefined) - txn.asnd = Buffer.from(this.assetRevocationTarget.publicKey); + txn.asnd = this.assetRevocationTarget.publicKey; // allowed zero values if (!txn.note.length) delete txn.note; if (!txn.lx.length) delete txn.lx; @@ -767,7 +764,7 @@ export class Transaction implements TransactionStorageStructure { if (!txn.asnd) delete txn.asnd; if (!txn.rekey) delete txn.rekey; if (this.reKeyTo !== undefined) { - txn.rekey = Buffer.from(this.reKeyTo.publicKey); + txn.rekey = this.reKeyTo.publicKey; } return txn; } @@ -777,18 +774,18 @@ export class Transaction implements TransactionStorageStructure { fee: this.fee, fv: this.firstRound, lv: this.lastRound, - note: Buffer.from(this.note), - snd: Buffer.from(this.from.publicKey), + note: this.note, + snd: this.from.publicKey, type: this.type, gen: this.genesisID, gh: this.genesisHash, - lx: Buffer.from(this.lease), + lx: this.lease, grp: this.group, faid: this.assetIndex, afrz: this.freezeState, }; if (this.freezeAccount !== undefined) - txn.fadd = Buffer.from(this.freezeAccount.publicKey); + txn.fadd = this.freezeAccount.publicKey; // allowed zero values if (!txn.note.length) delete txn.note; if (!txn.lx.length) delete txn.lx; @@ -799,7 +796,7 @@ export class Transaction implements TransactionStorageStructure { if (!txn.afrz) delete txn.afrz; if (txn.grp === undefined) delete txn.grp; if (this.reKeyTo !== undefined) { - txn.rekey = Buffer.from(this.reKeyTo.publicKey); + txn.rekey = this.reKeyTo.publicKey; } return txn; } @@ -809,12 +806,12 @@ export class Transaction implements TransactionStorageStructure { fee: this.fee, fv: this.firstRound, lv: this.lastRound, - note: Buffer.from(this.note), - snd: Buffer.from(this.from.publicKey), + note: this.note, + snd: this.from.publicKey, type: this.type, gen: this.genesisID, gh: this.genesisHash, - lx: Buffer.from(this.lease), + lx: this.lease, grp: this.group, apid: this.appIndex, apan: this.appOnComplete, @@ -836,20 +833,20 @@ export class Transaction implements TransactionStorageStructure { ), }; if (this.reKeyTo !== undefined) { - txn.rekey = Buffer.from(this.reKeyTo.publicKey); + txn.rekey = this.reKeyTo.publicKey; } if (this.appApprovalProgram !== undefined) { - txn.apap = Buffer.from(this.appApprovalProgram); + txn.apap = this.appApprovalProgram; } if (this.appClearProgram !== undefined) { - txn.apsu = Buffer.from(this.appClearProgram); + txn.apsu = this.appClearProgram; } if (this.appArgs !== undefined) { - txn.apaa = this.appArgs.map((arg) => Buffer.from(arg)); + txn.apaa = this.appArgs; } if (this.appAccounts !== undefined) { - txn.apat = this.appAccounts.map((decodedAddress) => - Buffer.from(decodedAddress.publicKey) + txn.apat = this.appAccounts.map( + (decodedAddress) => decodedAddress.publicKey ); } // allowed zero values @@ -888,15 +885,15 @@ export class Transaction implements TransactionStorageStructure { fee: this.fee, fv: this.firstRound, lv: this.lastRound, - note: Buffer.from(this.note), - snd: Buffer.from(this.from.publicKey), + note: this.note, + snd: this.from.publicKey, type: this.type, gen: this.genesisID, gh: this.genesisHash, - lx: Buffer.from(this.lease), + lx: this.lease, sptype: this.stateProofType, - spmsg: Buffer.from(this.stateProofMessage), - sp: Buffer.from(this.stateProof), + spmsg: this.stateProofMessage, + sp: this.stateProof, }; // allowed zero values if (!txn.sptype) delete txn.sptype; @@ -926,10 +923,10 @@ export class Transaction implements TransactionStorageStructure { static from_obj_for_encoding(txnForEnc: EncodedTransaction): Transaction { const txn = Object.create(this.prototype) as Transaction; txn.name = 'Transaction'; - txn.tag = Buffer.from('TX'); + txn.tag = new TextEncoder().encode('TX'); txn.genesisID = txnForEnc.gen; - txn.genesisHash = Buffer.from(txnForEnc.gh); + txn.genesisHash = txnForEnc.gh; if (!isTransactionType(txnForEnc.type)) { throw new Error(`Unrecognized transaction type: ${txnForEnc.type}`); } @@ -942,7 +939,7 @@ export class Transaction implements TransactionStorageStructure { txn.from = address.decodeAddress( address.encodeAddress(new Uint8Array(txnForEnc.snd)) ); - if (txnForEnc.grp !== undefined) txn.group = Buffer.from(txnForEnc.grp); + if (txnForEnc.grp !== undefined) txn.group = txnForEnc.grp; if (txnForEnc.rekey !== undefined) txn.reKeyTo = address.decodeAddress( address.encodeAddress(new Uint8Array(txnForEnc.rekey)) @@ -959,13 +956,13 @@ export class Transaction implements TransactionStorageStructure { ); } else if (txnForEnc.type === 'keyreg') { if (txnForEnc.votekey !== undefined) { - txn.voteKey = Buffer.from(txnForEnc.votekey); + txn.voteKey = txnForEnc.votekey; } if (txnForEnc.selkey !== undefined) { - txn.selectionKey = Buffer.from(txnForEnc.selkey); + txn.selectionKey = txnForEnc.selkey; } if (txnForEnc.sprfkey !== undefined) { - txn.stateProofKey = Buffer.from(txnForEnc.sprfkey); + txn.stateProofKey = txnForEnc.sprfkey; } if (txnForEnc.votekd !== undefined) { txn.voteKeyDilution = txnForEnc.votekd; @@ -1115,7 +1112,7 @@ export class Transaction implements TransactionStorageStructure { bytesToSign() { const encodedMsg = this.toByte(); - return Buffer.from(utils.concatArrays(this.tag, encodedMsg)); + return utils.concatArrays(this.tag, encodedMsg); } toByte() { @@ -1126,7 +1123,7 @@ export class Transaction implements TransactionStorageStructure { rawSignTxn(sk: Uint8Array) { const toBeSigned = this.bytesToSign(); const sig = nacl.sign(toBeSigned, sk); - return Buffer.from(sig); + return sig; } signTxn(sk: Uint8Array) { @@ -1142,7 +1139,7 @@ export class Transaction implements TransactionStorageStructure { address.encodeAddress(pubKeyFromSk) !== address.encodeAddress(this.from.publicKey) ) { - sTxn.sgnr = Buffer.from(pubKeyFromSk); + sTxn.sgnr = pubKeyFromSk; } return new Uint8Array(encoding.encode(sTxn)); } @@ -1152,21 +1149,21 @@ export class Transaction implements TransactionStorageStructure { throw new Error('Invalid signature length'); } const sTxn: EncodedSignedTransaction = { - sig: Buffer.from(signature), + sig: signature, txn: this.get_obj_for_encoding(), }; // add AuthAddr if signing with a different key than From indicates if (signerAddr !== address.encodeAddress(this.from.publicKey)) { const signerPublicKey = address.decodeAddress(signerAddr).publicKey; - sTxn.sgnr = Buffer.from(signerPublicKey); + sTxn.sgnr = signerPublicKey; } return new Uint8Array(encoding.encode(sTxn)); } rawTxID() { const enMsg = this.toByte(); - const gh = Buffer.from(utils.concatArrays(this.tag, enMsg)); - return Buffer.from(nacl.genericHash(gh)); + const gh = utils.concatArrays(this.tag, enMsg); + return Uint8Array.from(nacl.genericHash(gh)); } txID() { @@ -1261,7 +1258,8 @@ export class Transaction implements TransactionStorageStructure { forPrinting.reKeyTo = address.encodeAddress( (forPrinting.reKeyTo as Address).publicKey ); - forPrinting.genesisHash = forPrinting.genesisHash.toString('base64'); + if (typeof forPrinting.genesisHash !== 'string') + forPrinting.genesisHash = utils.bytesToBase64(forPrinting.genesisHash); // TODO: double check this return forPrinting; } @@ -1325,7 +1323,7 @@ export interface SignedTransaction { /** * Transaction signature */ - sig?: Buffer; + sig?: Uint8Array; /** * The transaction that was signed @@ -1345,11 +1343,11 @@ export interface SignedTransaction { /** * The signer, if signing with a different key than the Transaction type `from` property indicates */ - sgnr?: Buffer; + sgnr?: Uint8Array; } /** - * decodeSignedTransaction takes a Buffer (from transaction.signTxn) and converts it to an object + * decodeSignedTransaction takes a Uint8Array (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 diff --git a/src/types/transactions/encoded.ts b/src/types/transactions/encoded.ts index 7864e4e7d..963892998 100644 --- a/src/types/transactions/encoded.ts +++ b/src/types/transactions/encoded.ts @@ -1,5 +1,3 @@ -import { Buffer } from 'buffer'; - /** * Interfaces for the encoded transaction object. Every property is labelled with its associated Transaction type property */ @@ -23,22 +21,22 @@ export interface EncodedAssetParams { /** * assetManager */ - m?: Buffer; + m?: Uint8Array; /** * assetReserve */ - r?: Buffer; + r?: Uint8Array; /** * assetFreeze */ - f?: Buffer; + f?: Uint8Array; /** * assetClawback */ - c?: Buffer; + c?: Uint8Array; /** * assetName @@ -58,7 +56,7 @@ export interface EncodedAssetParams { /** * assetMetadataHash */ - am?: Buffer; + am?: Uint8Array; } export interface EncodedLocalStateSchema { @@ -119,12 +117,12 @@ export interface EncodedTransaction { /** * note */ - note?: Buffer; + note?: Uint8Array; /** * from */ - snd: Buffer; + snd: Uint8Array; /** * type @@ -139,17 +137,17 @@ export interface EncodedTransaction { /** * genesisHash */ - gh: Buffer; + gh: Uint8Array; /** * lease */ - lx?: Buffer; + lx?: Uint8Array; /** * group */ - grp?: Buffer; + grp?: Uint8Array; /** * amount @@ -164,42 +162,42 @@ export interface EncodedTransaction { /** * closeRemainderTo */ - close?: Buffer; + close?: Uint8Array; /** * closeRemainderTo (but for asset transfers) */ - aclose?: Buffer; + aclose?: Uint8Array; /** * reKeyTo */ - rekey?: Buffer; + rekey?: Uint8Array; /** * to */ - rcv?: Buffer; + rcv?: Uint8Array; /** * to (but for asset transfers) */ - arcv?: Buffer; + arcv?: Uint8Array; /** * voteKey */ - votekey?: Buffer; + votekey?: Uint8Array; /** * selectionKey */ - selkey?: Buffer; + selkey?: Uint8Array; /** * stateProofKey */ - sprfkey?: Buffer; + sprfkey?: Uint8Array; /** * voteFirst @@ -244,12 +242,12 @@ export interface EncodedTransaction { /** * freezeAccount */ - fadd?: Buffer; + fadd?: Uint8Array; /** * assetRevocationTarget */ - asnd?: Buffer; + asnd?: Uint8Array; /** * See EncodedAssetParams type @@ -289,22 +287,22 @@ export interface EncodedTransaction { /** * appApprovalProgram */ - apap?: Buffer; + apap?: Uint8Array; /** * appClearProgram */ - apsu?: Buffer; + apsu?: Uint8Array; /** * appArgs */ - apaa?: Buffer[]; + apaa?: Uint8Array[]; /** * appAccounts */ - apat?: Buffer[]; + apat?: Uint8Array[]; /** * extraPages @@ -324,12 +322,12 @@ export interface EncodedTransaction { /** * stateProof */ - sp?: Buffer; + sp?: Uint8Array; /** * stateProofMessage */ - spmsg?: Buffer; + spmsg?: Uint8Array; } export interface EncodedSubsig { @@ -384,7 +382,7 @@ export interface EncodedSignedTransaction { /** * Transaction signature */ - sig?: Buffer; + sig?: Uint8Array; /** * The transaction that was signed @@ -404,5 +402,5 @@ export interface EncodedSignedTransaction { /** * The signer, if signing with a different key than the Transaction type `from` property indicates */ - sgnr?: Buffer; + sgnr?: Uint8Array; } From a7222457d5c4ab3a293b8dabad6bb7df80cead2b Mon Sep 17 00:00:00 2001 From: algochoi <86622919+algochoi@users.noreply.github.com> Date: Tue, 11 Jul 2023 15:58:28 -0400 Subject: [PATCH 10/34] Remove unnecessary casting --- examples/app.ts | 2 +- examples/atc.ts | 2 +- examples/indexer.ts | 2 +- examples/overview.ts | 2 +- examples/utils.ts | 12 ++++++------ 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/examples/app.ts b/examples/app.ts index 3d6793b6c..e8e796c53 100644 --- a/examples/app.ts +++ b/examples/app.ts @@ -134,7 +134,7 @@ async function main() { from: caller.addr, suggestedParams, appIndex: appId, - appArgs: [new Uint8Array(new TextEncoder().encode(now))], + appArgs: [new TextEncoder().encode(now)], }); await algodClient diff --git a/examples/atc.ts b/examples/atc.ts index ee3ad574d..61fd3d776 100644 --- a/examples/atc.ts +++ b/examples/atc.ts @@ -98,7 +98,7 @@ async function main() { // example: ATC_BOX_REF const boxATC = new algosdk.AtomicTransactionComposer(); - const boxKey = new Uint8Array(new TextEncoder().encode('key')); + const boxKey = new TextEncoder().encode('key'); boxATC.addMethodCall({ appID: appIndex, method: boxAccessorMethod, diff --git a/examples/indexer.ts b/examples/indexer.ts index c903a4338..6390ae9e1 100644 --- a/examples/indexer.ts +++ b/examples/indexer.ts @@ -67,7 +67,7 @@ async function main() { from: sender.addr, to: sender.addr, amount: 1e6, - note: new Uint8Array(new TextEncoder().encode('Hello World!')), + note: new TextEncoder().encode('Hello World!'), suggestedParams, }); diff --git a/examples/overview.ts b/examples/overview.ts index 505f0b8d1..d44a33bcc 100644 --- a/examples/overview.ts +++ b/examples/overview.ts @@ -26,7 +26,7 @@ async function main() { suggestedParams, to: acct2.addr, amount: 10000, - note: new Uint8Array(new TextEncoder().encode('hello world')), + note: new TextEncoder().encode('hello world'), }); // example: TRANSACTION_PAYMENT_CREATE diff --git a/examples/utils.ts b/examples/utils.ts index 4546e10ad..83e908331 100644 --- a/examples/utils.ts +++ b/examples/utils.ts @@ -1,16 +1,16 @@ import fs from 'fs'; import path from 'path'; -import { Buffer } from 'buffer'; import algosdk from '../src'; +import { base64ToBytes } from '../src/utils/utils'; export async function compileProgram( client: algosdk.Algodv2, programSource: string ) { - const compileResponse = await client.compile(Buffer.from(programSource)).do(); - const compiledBytes = new Uint8Array( - Buffer.from(compileResponse.result, 'base64') - ); + const compileResponse = await client + .compile(new TextEncoder().encode(programSource)) + .do(); + const compiledBytes = base64ToBytes(compileResponse.result); return compiledBytes; } @@ -70,7 +70,7 @@ export async function getLocalAccounts(): Promise { const addresses = await kmdClient.listKeys(handle); // eslint-disable-next-line camelcase - const acctPromises: Promise<{ private_key: Buffer }>[] = []; + const acctPromises: Promise<{ private_key: Uint8Array }>[] = []; // eslint-disable-next-line no-restricted-syntax for (const addr of addresses.addresses) { From c8495f67917adcee32a7d5d113292575659709c8 Mon Sep 17 00:00:00 2001 From: algochoi <86622919+algochoi@users.noreply.github.com> Date: Tue, 11 Jul 2023 16:22:57 -0400 Subject: [PATCH 11/34] Unify return type to Uint8Array --- src/utils/utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/utils.ts b/src/utils/utils.ts index 7b71a5ca9..f80976cd0 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -130,7 +130,7 @@ export function isNode() { */ export function base64ToBytes(base64String: string) { if (isNode()) { - return Buffer.from(base64String, 'base64'); + return new Uint8Array(Buffer.from(base64String, 'base64')); } // eslint-disable-next-line no-undef return new Uint8Array(new TextEncoder().encode(btoa(base64String))); From 0c9b49a9a4a6063da2d330b5376c0cfba874a8b7 Mon Sep 17 00:00:00 2001 From: algochoi <86622919+algochoi@users.noreply.github.com> Date: Tue, 11 Jul 2023 23:50:10 -0400 Subject: [PATCH 12/34] Remove buffer usage in source code except client --- src/bid.ts | 11 +++++----- src/encoding/bigint.ts | 6 ++---- src/group.ts | 2 +- src/logicsig.ts | 46 +++++++++++++++++------------------------- src/main.ts | 9 +++------ src/multisig.ts | 12 +++++------ src/transaction.ts | 2 +- src/utils/utils.ts | 2 +- 8 files changed, 37 insertions(+), 53 deletions(-) diff --git a/src/bid.ts b/src/bid.ts index 7874d647c..5c0356235 100644 --- a/src/bid.ts +++ b/src/bid.ts @@ -1,4 +1,3 @@ -import { Buffer } from 'buffer'; import * as address from './encoding/address'; import * as encoding from './encoding/encoding'; import * as nacl from './nacl/naclWrappers'; @@ -27,7 +26,7 @@ export type BidOptions = Omit< * */ export default class Bid implements BidStorageStructure { name = 'Bid'; - tag = Buffer.from([97, 66]); // "aB" + tag = Uint8Array.from([97, 66]); // "aB" bidderKey: Address; bidAmount: number; @@ -67,23 +66,23 @@ export default class Bid implements BidStorageStructure { // eslint-disable-next-line camelcase get_obj_for_encoding() { return { - bidder: Buffer.from(this.bidderKey.publicKey), + bidder: this.bidderKey.publicKey, cur: this.bidAmount, price: this.maxPrice, id: this.bidID, - auc: Buffer.from(this.auctionKey.publicKey), + auc: this.auctionKey.publicKey, aid: this.auctionID, }; } signBid(sk: Uint8Array) { const encodedMsg = encoding.encode(this.get_obj_for_encoding()); - const toBeSigned = Buffer.from(utils.concatArrays(this.tag, encodedMsg)); + const toBeSigned = utils.concatArrays(this.tag, encodedMsg); const sig = nacl.sign(toBeSigned, sk); // construct signed message const sBid = { - sig: Buffer.from(sig), + sig, bid: this.get_obj_for_encoding(), }; diff --git a/src/encoding/bigint.ts b/src/encoding/bigint.ts index cc039904d..b29301a49 100644 --- a/src/encoding/bigint.ts +++ b/src/encoding/bigint.ts @@ -1,5 +1,3 @@ -import { Buffer } from 'buffer'; - /** * bigIntToBytes converts a BigInt to a big-endian Uint8Array for encoding. * @param bi - The bigint to convert. @@ -27,9 +25,9 @@ export function bigIntToBytes(bi: bigint | number, size: number) { */ export function bytesToBigInt(bytes: Uint8Array) { let res = BigInt(0); - const buf = Buffer.from(bytes); + const buf = new DataView(bytes.buffer, bytes.byteOffset); for (let i = 0; i < bytes.length; i++) { - res = BigInt(Number(buf.readUIntBE(i, 1))) + res * BigInt(256); + res = BigInt(Number(buf.getUint8(i))) + res * BigInt(256); } return res; } diff --git a/src/group.ts b/src/group.ts index 3cc1c2aaf..c1d9b9f56 100644 --- a/src/group.ts +++ b/src/group.ts @@ -55,7 +55,7 @@ export class TxGroup { /** * computeGroupID returns group ID for a group of transactions * @param txns - array of transactions (every element is a dict or Transaction) - * @returns Buffer + * @returns Uint8Array */ export function computeGroupID(txns: txnBuilder.TransactionLike[]) { const hashes = []; diff --git a/src/logicsig.ts b/src/logicsig.ts index 34a35ca30..6ba3448a6 100644 --- a/src/logicsig.ts +++ b/src/logicsig.ts @@ -1,4 +1,3 @@ -import { Buffer } from 'buffer'; import * as nacl from './nacl/naclWrappers'; import * as address from './encoding/address'; import * as encoding from './encoding/encoding'; @@ -39,12 +38,12 @@ export function sanityCheckProgram(program: Uint8Array) { ); if (isAsciiPrintable) { - const programStr = Buffer.from(program).toString(); + const programStr = new TextDecoder().decode(program); if (isValidAddress(programStr)) throw new Error('requesting program bytes, get Algorand address'); - if (Buffer.from(programStr, 'base64').toString('base64') === programStr) + if (utils.base64ToString(utils.bytesToBase64(program)) === programStr) throw new Error('program should not be b64 encoded'); throw new Error( @@ -59,23 +58,18 @@ export function sanityCheckProgram(program: Uint8Array) { LogicSig cannot sign transactions in all cases. Instead, use LogicSigAccount as a safe, general purpose signing mechanism. Since LogicSig does not track the provided signature's public key, LogicSig cannot sign transactions when delegated to a non-multisig account _and_ the sender is not the delegating account. */ export class LogicSig implements LogicSigStorageStructure { - tag = Buffer.from('Program'); + tag = new TextEncoder().encode('Program'); logic: Uint8Array; args: Uint8Array[]; sig?: Uint8Array; msig?: EncodedMultisig; - constructor( - program: Uint8Array, - programArgs?: Array | null - ) { + constructor(program: Uint8Array, programArgs?: Array | null) { if ( programArgs && (!Array.isArray(programArgs) || - !programArgs.every( - (arg) => arg.constructor === Uint8Array || Buffer.isBuffer(arg) - )) + !programArgs.every((arg) => arg.constructor === Uint8Array)) ) { throw new TypeError('Invalid arguments'); } @@ -243,7 +237,7 @@ export class LogicSigAccount { * this LogicSig. * @param args - An optional array of arguments for the program. */ - constructor(program: Uint8Array, args?: Array | null) { + constructor(program: Uint8Array, args?: Array | null) { this.lsig = new LogicSig(program, args); this.sigkey = undefined; } @@ -395,7 +389,7 @@ function signLogicSigTransactionWithAddress( }; if (!nacl.bytesEqual(lsigAddress, txn.from.publicKey)) { - signedTxn.sgnr = Buffer.from(lsigAddress); + signedTxn.sgnr = lsigAddress; } return { @@ -473,38 +467,36 @@ export function logicSigFromByte(encoded: Uint8Array) { return LogicSig.fromByte(encoded); } -const SIGN_PROGRAM_DATA_PREFIX = Buffer.from('ProgData'); +const SIGN_PROGRAM_DATA_PREFIX = new TextEncoder().encode('ProgData'); /** * tealSign creates a signature compatible with ed25519verify opcode from program hash - * @param sk - uint8array with secret key - * @param data - buffer with data to sign + * @param sk - Uint8Array with secret key + * @param data - Uint8Array with data to sign * @param programHash - string representation of teal program hash (= contract address for LogicSigs) */ export function tealSign( sk: Uint8Array, - data: Uint8Array | Buffer, + data: Uint8Array, programHash: string ) { const parts = utils.concatArrays( address.decodeAddress(programHash).publicKey, data ); - const toBeSigned = Buffer.from( - utils.concatArrays(SIGN_PROGRAM_DATA_PREFIX, parts) - ); + const toBeSigned = utils.concatArrays(SIGN_PROGRAM_DATA_PREFIX, parts); return nacl.sign(toBeSigned, sk); } /** * verifyTealSign verifies a signature as would the ed25519verify opcode - * @param data - buffer with original signed data + * @param data - Uint8Array with original signed data * @param programHash - string representation of teal program hash (= contract address for LogicSigs) * @param sig - uint8array with the signature to verify (produced by tealSign/tealSignFromProgram) * @param pk - uint8array with public key to verify against */ export function verifyTealSign( - data: Uint8Array | Buffer, + data: Uint8Array, programHash: string, sig: Uint8Array, pk: Uint8Array @@ -513,21 +505,19 @@ export function verifyTealSign( address.decodeAddress(programHash).publicKey, data ); - const toBeSigned = Buffer.from( - utils.concatArrays(SIGN_PROGRAM_DATA_PREFIX, parts) - ); + const toBeSigned = utils.concatArrays(SIGN_PROGRAM_DATA_PREFIX, parts); return nacl.verify(toBeSigned, sig, pk); } /** * tealSignFromProgram creates a signature compatible with ed25519verify opcode from raw program bytes * @param sk - uint8array with secret key - * @param data - buffer with data to sign - * @param program - buffer with teal program + * @param data - Uint8Array with data to sign + * @param program - Uint8Array with teal program */ export function tealSignFromProgram( sk: Uint8Array, - data: Uint8Array | Buffer, + data: Uint8Array, program: Uint8Array ) { const lsig = new LogicSig(program); diff --git a/src/main.ts b/src/main.ts index aadb49086..28d258f62 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,4 +1,3 @@ -import { Buffer } from 'buffer'; import * as nacl from './nacl/naclWrappers'; import * as address from './encoding/address'; import * as encoding from './encoding/encoding'; @@ -7,7 +6,7 @@ import Bid, { BidOptions } from './bid'; import * as convert from './convert'; import * as utils from './utils/utils'; -const SIGN_BYTES_PREFIX = Buffer.from([77, 88]); // "MX" +const SIGN_BYTES_PREFIX = Uint8Array.from([77, 88]); // "MX" // Errors export const MULTISIG_BAD_SENDER_ERROR_MSG = @@ -66,7 +65,7 @@ export function signBid(bid: BidOptions, sk: Uint8Array) { * @returns binary signature */ export function signBytes(bytes: Uint8Array, sk: Uint8Array) { - const toBeSigned = Buffer.from(utils.concatArrays(SIGN_BYTES_PREFIX, bytes)); + const toBeSigned = utils.concatArrays(SIGN_BYTES_PREFIX, bytes); const sig = nacl.sign(toBeSigned, sk); return sig; } @@ -84,9 +83,7 @@ export function verifyBytes( signature: Uint8Array, addr: string ) { - const toBeVerified = Buffer.from( - utils.concatArrays(SIGN_BYTES_PREFIX, bytes) - ); + const toBeVerified = utils.concatArrays(SIGN_BYTES_PREFIX, bytes); const pk = address.decodeAddress(addr).publicKey; return nacl.verify(toBeVerified, signature, pk); } diff --git a/src/multisig.ts b/src/multisig.ts index 7bf821d2d..a754e9534 100644 --- a/src/multisig.ts +++ b/src/multisig.ts @@ -56,7 +56,7 @@ export function createMultisigTransaction( ) { // construct the appendable multisigned transaction format const pks = addrs.map((addr) => address.decodeAddress(addr).publicKey); - const subsigs = pks.map((pk) => ({ pk: Buffer.from(pk) })); + const subsigs = pks.map((pk) => ({ pk })); const msig: EncodedMultisig = { v: version, @@ -80,7 +80,7 @@ export function createMultisigTransaction( address.encodeAddress(txnForEncoding.snd) !== address.encodeAddress(msigAddr) ) { - signedTxn.sgnr = Buffer.from(msigAddr); + signedTxn.sgnr = msigAddr; } return new Uint8Array(encoding.encode(signedTxn)); @@ -89,7 +89,7 @@ export function createMultisigTransaction( /** * createMultisigTransactionWithSignature creates a multisig transaction blob with an included signature. * @param txn - the actual transaction to sign. - * @param rawSig - a Buffer raw signature of that transaction + * @param rawSig - a Uint8Array raw signature of that transaction * @param myPk - a public key that corresponds with rawSig * @param version - multisig version * @param threshold - multisig threshold @@ -132,7 +132,7 @@ function createMultisigTransactionWithSignature( if ( address.encodeAddress(signedTxn.txn.snd) !== address.encodeAddress(msigAddr) ) { - signedTxn.sgnr = Buffer.from(msigAddr); + signedTxn.sgnr = msigAddr; } return new Uint8Array(encoding.encode(signedTxn)); @@ -291,7 +291,7 @@ export function mergeMultisigTransactions(multisigTxnBlobs: Uint8Array[]) { // info: https://github.com/algorand/js-algorand-sdk/issues/252 if ( current.s && - Buffer.compare(Buffer.from(uniSubsig.s), Buffer.from(current.s)) !== 0 + Buffer.compare(Buffer.from(uniSubsig.s), Buffer.from(current.s)) !== 0 // TODO: Check this Buffer usage ) { // mismatch throw new Error(MULTISIG_MERGE_SIG_MISMATCH_ERROR_MSG); @@ -309,7 +309,7 @@ export function mergeMultisigTransactions(multisigTxnBlobs: Uint8Array[]) { txn: refSigTx.txn, }; if (typeof refAuthAddr !== 'undefined') { - signedTxn.sgnr = Buffer.from(address.decodeAddress(refAuthAddr).publicKey); + signedTxn.sgnr = Buffer.from(address.decodeAddress(refAuthAddr).publicKey); // TODO: Check this Buffer usage } return new Uint8Array(encoding.encode(signedTxn)); } diff --git a/src/transaction.ts b/src/transaction.ts index 59cd1a23a..ef23df799 100644 --- a/src/transaction.ts +++ b/src/transaction.ts @@ -1304,7 +1304,7 @@ export function encodeUnsignedTransaction(transactionObject: Transaction) { } /** - * decodeUnsignedTransaction takes a Buffer (as if from encodeUnsignedTransaction) and converts it to a txnBuilder.Transaction object + * decodeUnsignedTransaction takes a Uint8Array (as if from encodeUnsignedTransaction) and converts it to a txnBuilder.Transaction object * @param transactionBuffer - the Uint8Array containing a transaction */ export function decodeUnsignedTransaction( diff --git a/src/utils/utils.ts b/src/utils/utils.ts index 7b71a5ca9..701b7158c 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -133,7 +133,7 @@ export function base64ToBytes(base64String: string) { return Buffer.from(base64String, 'base64'); } // eslint-disable-next-line no-undef - return new Uint8Array(new TextEncoder().encode(btoa(base64String))); + return new TextEncoder().encode(btoa(base64String)); } /** From 20861bd2dae1005822b6db34a85f849834bfc2c2 Mon Sep 17 00:00:00 2001 From: algochoi <86622919+algochoi@users.noreply.github.com> Date: Wed, 12 Jul 2023 00:45:01 -0400 Subject: [PATCH 13/34] Standardize tests and add more utf-8 strings --- src/utils/utils.ts | 26 +++++++++++++++----------- tests/2.Encoding.js | 27 ++++++++++++++++++--------- 2 files changed, 33 insertions(+), 20 deletions(-) diff --git a/src/utils/utils.ts b/src/utils/utils.ts index f80976cd0..0edce43cb 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -128,43 +128,47 @@ export function isNode() { * Convert a base64 string to a Uint8Array for Node.js and browser environments. * @returns A Uint8Array */ -export function base64ToBytes(base64String: string) { +export function base64ToBytes(base64String: string): Uint8Array { if (isNode()) { return new Uint8Array(Buffer.from(base64String, 'base64')); } - // eslint-disable-next-line no-undef - return new Uint8Array(new TextEncoder().encode(btoa(base64String))); + /* eslint-env browser */ + const binString = atob(base64String); + return Uint8Array.from(binString, (m) => m.codePointAt(0)); } /** * Decode a base64 string for Node.js and browser environments. * @returns A decoded string */ -export function base64ToString(base64String: string) { +export function base64ToString(base64String: string): string { if (isNode()) { return base64ToBytes(base64String).toString(); } - // eslint-disable-next-line no-undef - return btoa(base64String); + /* eslint-env browser */ + return atob(base64String); } /** - * Convert a a Uint8Array to a base64 string for Node.js and browser environments. + * Convert a Uint8Array to a base64 string for Node.js and browser environments. * @returns A base64 string */ -export function bytesToBase64(byteArray: Uint8Array) { +export function bytesToBase64(byteArray: Uint8Array): string { if (isNode()) { return Buffer.from(byteArray).toString('base64'); } - // eslint-disable-next-line no-undef - return atob(new TextDecoder().decode(byteArray)); + /* eslint-env browser */ + const binString = Array.from(byteArray, (x) => String.fromCodePoint(x)).join( + '' + ); + return btoa(binString); } /** * Convert a a Uint8Array to a hex string for Node.js and browser environments. * @returns A hex string */ -export function bytesToHex(byteArray: Uint8Array) { +export function bytesToHex(byteArray: Uint8Array): string { if (isNode()) { return Buffer.from(byteArray).toString('hex'); } diff --git a/tests/2.Encoding.js b/tests/2.Encoding.js index ff1707a4e..f5142476f 100644 --- a/tests/2.Encoding.js +++ b/tests/2.Encoding.js @@ -555,15 +555,24 @@ describe('encoding', () => { describe('Base64 decoding utilities', () => { it('should decode and encode Base64 roundtrip', () => { - const expectedString = 'SGVsbG8sIHdvcmxk'; // "Hello, world" - const byteString = utils.base64ToBytes(expectedString); - const actualString = utils.bytesToBase64(byteString); - - assert.deepStrictEqual( - actualString, - expectedString, - `Incorrect decoding of ${expectedString}; got ${actualString}` - ); + const testCases = [ + 'Hello, Algorand!', + 'a Ā 𐀀 文 🦄', + '(╯°□°)``` ┻━┻ 00\\', + ]; + for (const testCase of testCases) { + const byteArray = new TextEncoder().encode(testCase); + const base64String = utils.bytesToBase64(byteArray); + const roundTripString = new TextDecoder().decode( + utils.base64ToBytes(base64String) + ); + + assert.deepStrictEqual( + roundTripString, + testCase, + `Incorrect decoding of ${testCase}; got ${roundTripString}` + ); + } }); }); }); From 5d86934d2d3123a368bc0165adf76497d9ca9589 Mon Sep 17 00:00:00 2001 From: algochoi <86622919+algochoi@users.noreply.github.com> Date: Wed, 12 Jul 2023 08:59:47 -0400 Subject: [PATCH 14/34] Add hex encoding and string encoding tests --- src/utils/utils.ts | 6 +++--- tests/2.Encoding.js | 23 --------------------- tests/4.Utils.ts | 50 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 26 deletions(-) diff --git a/src/utils/utils.ts b/src/utils/utils.ts index 0edce43cb..b1e48236b 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -143,10 +143,10 @@ export function base64ToBytes(base64String: string): Uint8Array { */ export function base64ToString(base64String: string): string { if (isNode()) { - return base64ToBytes(base64String).toString(); + return Buffer.from(base64String, 'base64').toString(); } - /* eslint-env browser */ - return atob(base64String); + const binString = base64ToBytes(base64String); + return new TextDecoder().decode(binString); } /** diff --git a/tests/2.Encoding.js b/tests/2.Encoding.js index f5142476f..3fce45668 100644 --- a/tests/2.Encoding.js +++ b/tests/2.Encoding.js @@ -552,27 +552,4 @@ describe('encoding', () => { } }); }); - - describe('Base64 decoding utilities', () => { - it('should decode and encode Base64 roundtrip', () => { - const testCases = [ - 'Hello, Algorand!', - 'a Ā 𐀀 文 🦄', - '(╯°□°)``` ┻━┻ 00\\', - ]; - for (const testCase of testCases) { - const byteArray = new TextEncoder().encode(testCase); - const base64String = utils.bytesToBase64(byteArray); - const roundTripString = new TextDecoder().decode( - utils.base64ToBytes(base64String) - ); - - assert.deepStrictEqual( - roundTripString, - testCase, - `Incorrect decoding of ${testCase}; got ${roundTripString}` - ); - } - }); - }); }); diff --git a/tests/4.Utils.ts b/tests/4.Utils.ts index a2b589d4b..da2529edc 100644 --- a/tests/4.Utils.ts +++ b/tests/4.Utils.ts @@ -34,6 +34,56 @@ describe('utils', () => { assert.deepStrictEqual(expected, actual); }); }); + + describe('Base64 decoding utilities', () => { + it('should decode and encode Base64 roundtrip', () => { + const testCases = [ + ['Hello, Algorand!', 'SGVsbG8sIEFsZ29yYW5kIQ=='], + ['a Ā 𐀀 文 🦄', 'YSDEgCDwkICAIOaWhyDwn6aE'], + ['(╯°□°)``` ┻━┻ 00\\', 'KOKVr8Kw4pahwrDvvIlgYGAg4pS74pSB4pS7IDAwXA=='], + ]; + for (const [testCase, expectedEncoding] of testCases) { + const actualB64Decoding = utils.base64ToString(expectedEncoding); + assert.deepStrictEqual( + actualB64Decoding, + testCase, + `Incorrect encoding of ${testCase}; got ${actualB64Decoding}` + ); + + const byteArray = new TextEncoder().encode(testCase); + const base64String = utils.bytesToBase64(byteArray); + const roundTripString = new TextDecoder().decode( + utils.base64ToBytes(base64String) + ); + + assert.deepStrictEqual( + roundTripString, + testCase, + `Incorrect decoding of ${testCase}; got ${roundTripString}` + ); + } + }); + + it('should encode bytes to hex', () => { + const testCases = [ + ['Hello, Algorand!', '48656c6c6f2c20416c676f72616e6421'], + ['a Ā 𐀀 文 🦄', '6120c48020f090808020e6968720f09fa684'], + [ + '(╯°□°)``` ┻━┻ 00\\', + '28e295afc2b0e296a1c2b0efbc8960606020e294bbe29481e294bb2030305c', + ], + ]; + for (const [testCase, expectedEncoding] of testCases) { + const binString = new TextEncoder().encode(testCase); + const actualHexString = utils.bytesToHex(binString); + assert.deepStrictEqual( + actualHexString, + expectedEncoding, + `Incorrect encoding of ${testCase}; got ${actualHexString}` + ); + } + }); + }); }); describe('nacl wrapper', () => { From 4fe705a48b5e49690d7f72f1d9d8fc640989a88a Mon Sep 17 00:00:00 2001 From: algochoi <86622919+algochoi@users.noreply.github.com> Date: Thu, 13 Jul 2023 12:19:23 -0400 Subject: [PATCH 15/34] Fix some code broken by existing tests --- src/encoding/address.ts | 3 +-- src/group.ts | 2 +- src/logicsig.ts | 5 ++++- src/multisig.ts | 12 ++---------- tests/5.Transaction.js | 12 ++++++------ 5 files changed, 14 insertions(+), 20 deletions(-) diff --git a/src/encoding/address.ts b/src/encoding/address.ts index b1e287ebc..42f67874c 100644 --- a/src/encoding/address.ts +++ b/src/encoding/address.ts @@ -1,4 +1,3 @@ -import { Buffer } from 'buffer'; import base32 from 'hi-base32'; import * as nacl from '../nacl/naclWrappers'; import * as utils from '../utils/utils'; @@ -28,7 +27,7 @@ const MULTISIG_PREIMG2ADDR_PREFIX = new Uint8Array([ 114, ]); -const APP_ID_PREFIX = Buffer.from('appID'); +const APP_ID_PREFIX = new TextEncoder().encode('appID'); export const MALFORMED_ADDRESS_ERROR_MSG = 'address seems to be malformed'; export const CHECKSUM_ADDRESS_ERROR_MSG = 'wrong checksum for address'; diff --git a/src/group.ts b/src/group.ts index c1d9b9f56..955fd5878 100644 --- a/src/group.ts +++ b/src/group.ts @@ -42,7 +42,7 @@ export class TxGroup { txn.tag = new TextEncoder().encode('TG'); txn.txGroupHashes = []; for (const hash of txgroupForEnc.txlist) { - utils.concatArrays(txn.txGroupHashes, hash); + txn.txGroupHashes.push(hash); } return txn; } diff --git a/src/logicsig.ts b/src/logicsig.ts index 6ba3448a6..ca59830be 100644 --- a/src/logicsig.ts +++ b/src/logicsig.ts @@ -20,6 +20,9 @@ interface LogicSigStorageStructure { msig?: EncodedMultisig; } +// base64regex is the regex to test for base64 strings +const base64regex = /^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$/; + /** sanityCheckProgram performs heuristic program validation: * check if passed in bytes are Algorand address or is B64 encoded, rather than Teal bytes * @@ -43,7 +46,7 @@ export function sanityCheckProgram(program: Uint8Array) { if (isValidAddress(programStr)) throw new Error('requesting program bytes, get Algorand address'); - if (utils.base64ToString(utils.bytesToBase64(program)) === programStr) + if (base64regex.test(programStr)) throw new Error('program should not be b64 encoded'); throw new Error( diff --git a/src/multisig.ts b/src/multisig.ts index a754e9534..d795f8de6 100644 --- a/src/multisig.ts +++ b/src/multisig.ts @@ -1,4 +1,3 @@ -import { Buffer } from 'buffer'; import * as nacl from './nacl/naclWrappers'; import * as address from './encoding/address'; import * as encoding from './encoding/encoding'; @@ -285,14 +284,7 @@ export function mergeMultisigTransactions(multisigTxnBlobs: Uint8Array[]) { unisig.msig.subsig.forEach((uniSubsig, index) => { if (!uniSubsig.s) return; const current = newSubsigs[index]; - // we convert the Uint8Arrays uniSubsig.s and current.s to Buffers here because (as - // of Dec 2020) React overrides the buffer package with an older version that does - // not support Uint8Arrays in the comparison function. See this thread for more - // info: https://github.com/algorand/js-algorand-sdk/issues/252 - if ( - current.s && - Buffer.compare(Buffer.from(uniSubsig.s), Buffer.from(current.s)) !== 0 // TODO: Check this Buffer usage - ) { + if (current.s && !utils.arrayEqual(uniSubsig.s, current.s)) { // mismatch throw new Error(MULTISIG_MERGE_SIG_MISMATCH_ERROR_MSG); } @@ -309,7 +301,7 @@ export function mergeMultisigTransactions(multisigTxnBlobs: Uint8Array[]) { txn: refSigTx.txn, }; if (typeof refAuthAddr !== 'undefined') { - signedTxn.sgnr = Buffer.from(address.decodeAddress(refAuthAddr).publicKey); // TODO: Check this Buffer usage + signedTxn.sgnr = address.decodeAddress(refAuthAddr).publicKey; } return new Uint8Array(encoding.encode(signedTxn)); } diff --git a/tests/5.Transaction.js b/tests/5.Transaction.js index 7069d4b1a..aa38f634f 100644 --- a/tests/5.Transaction.js +++ b/tests/5.Transaction.js @@ -1,9 +1,9 @@ /* eslint-env mocha */ -const { Buffer } = require('buffer'); const assert = require('assert'); const algosdk = require('../src/index'); const { translateBoxReferences } = require('../src/boxStorage'); const group = require('../src/group'); +const { base64ToBytes } = require('../src/utils/utils'); describe('Sign', () => { /* eslint-disable no-console */ @@ -508,7 +508,7 @@ describe('Sign', () => { assetName: 'testcoin', assetURL: 'testURL', assetMetadataHash: new Uint8Array( - Buffer.from('ZkFDUE80blJnTzU1ajFuZEFLM1c2U2djNEFQa2N5Rmg=', 'base64') + base64ToBytes('ZkFDUE80blJnTzU1ajFuZEFLM1c2U2djNEFQa2N5Rmg=') ), assetManager: address, assetReserve: address, @@ -569,7 +569,7 @@ describe('Sign', () => { foreignAssets: [5, 6], boxes: [{ appIndex: 0, name: Uint8Array.from([0]) }], lease: Uint8Array.from(new Array(32).fill(7)), - note: new Uint8Array(Buffer.from('note value')), + note: new TextEncoder().encode('note value'), rekeyTo: 'UCE2U2JC4O4ZR6W763GUQCG57HQCDZEUJY4J5I6VYY4HQZUJDF7AKZO5GM', suggestedParams: { fee: 0, @@ -1039,7 +1039,7 @@ describe('Sign', () => { const assetName = 'testcoin'; const assetURL = 'testURL'; const assetMetadataHash = new Uint8Array( - Buffer.from('dGVzdGhhc2gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=', 'base64') + base64ToBytes('dGVzdGhhc2gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=') ); const genesisID = ''; const firstRound = 322575; @@ -1111,7 +1111,7 @@ describe('Sign', () => { const assetName = 'testcoin'; const assetURL = 'testURL'; const assetMetadataHash = new Uint8Array( - Buffer.from('dGVzdGhhc2gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=', 'base64') + base64ToBytes('dGVzdGhhc2gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=') ); const genesisID = ''; const firstRound = 322575; @@ -1183,7 +1183,7 @@ describe('Sign', () => { const assetName = 'testcoin'; const assetURL = 'testURL'; const assetMetadataHash = new Uint8Array( - Buffer.from('dGVzdGhhc2gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=', 'base64') + base64ToBytes('dGVzdGhhc2gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=') ); const genesisID = ''; const firstRound = 322575; From 14370202b97004c634f4b4f1005b72c89473129b Mon Sep 17 00:00:00 2001 From: algochoi <86622919+algochoi@users.noreply.github.com> Date: Thu, 13 Jul 2023 15:47:03 -0400 Subject: [PATCH 16/34] Update tests for edge bytes --- tests/4.Utils.ts | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/tests/4.Utils.ts b/tests/4.Utils.ts index da2529edc..470a4ad97 100644 --- a/tests/4.Utils.ts +++ b/tests/4.Utils.ts @@ -36,7 +36,47 @@ describe('utils', () => { }); describe('Base64 decoding utilities', () => { - it('should decode and encode Base64 roundtrip', () => { + it('should decode bytes from Base64', () => { + const testCases = [ + [ + Uint8Array.from([ + 97, + 32, + 196, + 128, + 32, + 240, + 144, + 128, + 128, + 32, + 230, + 150, + 135, + 32, + 240, + 159, + 166, + 132, + ]), // a Ā 𐀀 文 🦄 + 'YSDEgCDwkICAIOaWhyDwn6aE', + ], + [ + Uint8Array.from([0, 1, 2, 3, 4, 46, 46, 46, 254, 255]), // non UTF-8 bytes + 'AAECAwQuLi7+/w==', + ], + ]; + for (const [expectedBytes, expectedEncoding] of testCases) { + const actualBytes = utils.base64ToBytes(expectedEncoding as string); + assert.deepStrictEqual( + actualBytes, + expectedBytes, + `Incorrect encoding of ${expectedBytes}; got ${actualBytes}` + ); + } + }); + + it('should decode and encode Base64 roundtrip for UTF-8 strings', () => { const testCases = [ ['Hello, Algorand!', 'SGVsbG8sIEFsZ29yYW5kIQ=='], ['a Ā 𐀀 文 🦄', 'YSDEgCDwkICAIOaWhyDwn6aE'], From 42f9a12bfa0b64d0df1a05d94a030c345f978f8f Mon Sep 17 00:00:00 2001 From: algochoi <86622919+algochoi@users.noreply.github.com> Date: Thu, 13 Jul 2023 16:13:12 -0400 Subject: [PATCH 17/34] Export byte conversion utilities --- examples/app.ts | 2 +- examples/codec.ts | 2 +- examples/lsig.ts | 2 +- examples/utils.ts | 2 +- src/encoding/binarydata.ts | 55 +++++++++++++++++++++++ src/main.ts | 6 +++ src/utils/utils.ts | 54 ----------------------- tests/2.Encoding.js | 90 ++++++++++++++++++++++++++++++++++++++ tests/4.Utils.ts | 90 -------------------------------------- 9 files changed, 155 insertions(+), 148 deletions(-) create mode 100644 src/encoding/binarydata.ts diff --git a/examples/app.ts b/examples/app.ts index e8e796c53..721fae354 100644 --- a/examples/app.ts +++ b/examples/app.ts @@ -6,7 +6,7 @@ import fs from 'fs'; import path from 'path'; import { getLocalAlgodClient, getLocalAccounts, compileProgram } from './utils'; import algosdk from '../src'; -import { base64ToBytes, base64ToString } from '../src/utils/utils'; +import { base64ToBytes, base64ToString } from '../src/encoding/binarydata'; async function main() { const algodClient = getLocalAlgodClient(); diff --git a/examples/codec.ts b/examples/codec.ts index 7a128f36d..be7b419ab 100644 --- a/examples/codec.ts +++ b/examples/codec.ts @@ -9,7 +9,7 @@ import { base64ToString, bytesToBase64, bytesToHex, -} from '../src/utils/utils'; +} from '../src/encoding/binarydata'; async function main() { const client = getLocalAlgodClient(); diff --git a/examples/lsig.ts b/examples/lsig.ts index 6ae29a71f..e2bce90d3 100644 --- a/examples/lsig.ts +++ b/examples/lsig.ts @@ -3,7 +3,7 @@ /* eslint-disable no-promise-executor-return */ /* eslint-disable no-console */ import algosdk from '../src'; -import { base64ToBytes } from '../src/utils/utils'; +import { base64ToBytes } from '../src/encoding/binarydata'; import { getLocalAlgodClient, getLocalAccounts } from './utils'; async function main() { diff --git a/examples/utils.ts b/examples/utils.ts index 83e908331..7d7af4514 100644 --- a/examples/utils.ts +++ b/examples/utils.ts @@ -1,7 +1,7 @@ import fs from 'fs'; import path from 'path'; import algosdk from '../src'; -import { base64ToBytes } from '../src/utils/utils'; +import { base64ToBytes } from '../src/encoding/binarydata'; export async function compileProgram( client: algosdk.Algodv2, diff --git a/src/encoding/binarydata.ts b/src/encoding/binarydata.ts new file mode 100644 index 000000000..549a5b9ac --- /dev/null +++ b/src/encoding/binarydata.ts @@ -0,0 +1,55 @@ +import { Buffer } from 'buffer'; +import { isNode } from '../utils/utils'; + +/** + * Convert a base64 string to a Uint8Array for Node.js and browser environments. + * @returns A Uint8Array + */ +export function base64ToBytes(base64String: string): Uint8Array { + if (isNode()) { + return new Uint8Array(Buffer.from(base64String, 'base64')); + } + /* eslint-env browser */ + const binString = atob(base64String); + return Uint8Array.from(binString, (m) => m.codePointAt(0)); +} + +/** + * Decode a base64 string for Node.js and browser environments. + * @returns A decoded string + */ +export function base64ToString(base64String: string): string { + if (isNode()) { + return Buffer.from(base64String, 'base64').toString(); + } + const binString = base64ToBytes(base64String); + return new TextDecoder().decode(binString); +} + +/** + * Convert a Uint8Array to a base64 string for Node.js and browser environments. + * @returns A base64 string + */ +export function bytesToBase64(byteArray: Uint8Array): string { + if (isNode()) { + return Buffer.from(byteArray).toString('base64'); + } + /* eslint-env browser */ + const binString = Array.from(byteArray, (x) => String.fromCodePoint(x)).join( + '' + ); + return btoa(binString); +} + +/** + * Convert a a Uint8Array to a hex string for Node.js and browser environments. + * @returns A hex string + */ +export function bytesToHex(byteArray: Uint8Array): string { + if (isNode()) { + return Buffer.from(byteArray).toString('hex'); + } + return Array.from(byteArray) + .map((i) => i.toString(16).padStart(2, '0')) + .join(''); +} diff --git a/src/main.ts b/src/main.ts index aadb49086..f109fb979 100644 --- a/src/main.ts +++ b/src/main.ts @@ -142,6 +142,12 @@ export { getApplicationAddress, } from './encoding/address'; export { bytesToBigInt, bigIntToBytes } from './encoding/bigint'; +export { + base64ToBytes, + base64ToString, + bytesToBase64, + bytesToHex, +} from './encoding/binarydata'; export { encodeUint64, decodeUint64 } from './encoding/uint64'; export { default as generateAccount } from './account'; export * as modelsv2 from './client/v2/algod/models/types'; diff --git a/src/utils/utils.ts b/src/utils/utils.ts index c2428856a..620644b3a 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -1,5 +1,4 @@ import JSONbigWithoutConfig from 'json-bigint'; -import { Buffer } from 'buffer'; import IntDecoding from '../types/intDecoding'; const JSONbig = JSONbigWithoutConfig({ useNativeBigInt: true, strict: true }); @@ -135,56 +134,3 @@ export function isReactNative() { } return false; } - -/** - * Convert a base64 string to a Uint8Array for Node.js and browser environments. - * @returns A Uint8Array - */ -export function base64ToBytes(base64String: string): Uint8Array { - if (isNode()) { - return new Uint8Array(Buffer.from(base64String, 'base64')); - } - /* eslint-env browser */ - const binString = atob(base64String); - return Uint8Array.from(binString, (m) => m.codePointAt(0)); -} - -/** - * Decode a base64 string for Node.js and browser environments. - * @returns A decoded string - */ -export function base64ToString(base64String: string): string { - if (isNode()) { - return Buffer.from(base64String, 'base64').toString(); - } - const binString = base64ToBytes(base64String); - return new TextDecoder().decode(binString); -} - -/** - * Convert a Uint8Array to a base64 string for Node.js and browser environments. - * @returns A base64 string - */ -export function bytesToBase64(byteArray: Uint8Array): string { - if (isNode()) { - return Buffer.from(byteArray).toString('base64'); - } - /* eslint-env browser */ - const binString = Array.from(byteArray, (x) => String.fromCodePoint(x)).join( - '' - ); - return btoa(binString); -} - -/** - * Convert a a Uint8Array to a hex string for Node.js and browser environments. - * @returns A hex string - */ -export function bytesToHex(byteArray: Uint8Array): string { - if (isNode()) { - return Buffer.from(byteArray).toString('hex'); - } - return Array.from(byteArray) - .map((i) => i.toString(16).padStart(2, '0')) - .join(''); -} diff --git a/tests/2.Encoding.js b/tests/2.Encoding.js index 3fce45668..d7ea813b6 100644 --- a/tests/2.Encoding.js +++ b/tests/2.Encoding.js @@ -552,4 +552,94 @@ describe('encoding', () => { } }); }); + + describe('Base64 decoding utilities', () => { + it('should decode bytes from Base64', () => { + const testCases = [ + [ + Uint8Array.from([ + 97, + 32, + 196, + 128, + 32, + 240, + 144, + 128, + 128, + 32, + 230, + 150, + 135, + 32, + 240, + 159, + 166, + 132, + ]), // a Ā 𐀀 文 🦄 + 'YSDEgCDwkICAIOaWhyDwn6aE', + ], + [ + Uint8Array.from([0, 1, 2, 3, 4, 46, 46, 46, 254, 255]), // non UTF-8 bytes + 'AAECAwQuLi7+/w==', + ], + ]; + for (const [expectedBytes, expectedEncoding] of testCases) { + const actualBytes = algosdk.base64ToBytes(expectedEncoding); + assert.deepStrictEqual( + actualBytes, + expectedBytes, + `Incorrect encoding of ${expectedBytes}; got ${actualBytes}` + ); + } + }); + + it('should decode and encode Base64 roundtrip for UTF-8 strings', () => { + const testCases = [ + ['Hello, Algorand!', 'SGVsbG8sIEFsZ29yYW5kIQ=='], + ['a Ā 𐀀 文 🦄', 'YSDEgCDwkICAIOaWhyDwn6aE'], + ['(╯°□°)``` ┻━┻ 00\\', 'KOKVr8Kw4pahwrDvvIlgYGAg4pS74pSB4pS7IDAwXA=='], + ]; + for (const [testCase, expectedEncoding] of testCases) { + const actualB64Decoding = algosdk.base64ToString(expectedEncoding); + assert.deepStrictEqual( + actualB64Decoding, + testCase, + `Incorrect encoding of ${testCase}; got ${actualB64Decoding}` + ); + + const byteArray = new TextEncoder().encode(testCase); + const base64String = algosdk.bytesToBase64(byteArray); + const roundTripString = new TextDecoder().decode( + algosdk.base64ToBytes(base64String) + ); + + assert.deepStrictEqual( + roundTripString, + testCase, + `Incorrect decoding of ${testCase}; got ${roundTripString}` + ); + } + }); + + it('should encode bytes to hex', () => { + const testCases = [ + ['Hello, Algorand!', '48656c6c6f2c20416c676f72616e6421'], + ['a Ā 𐀀 文 🦄', '6120c48020f090808020e6968720f09fa684'], + [ + '(╯°□°)``` ┻━┻ 00\\', + '28e295afc2b0e296a1c2b0efbc8960606020e294bbe29481e294bb2030305c', + ], + ]; + for (const [testCase, expectedEncoding] of testCases) { + const binString = new TextEncoder().encode(testCase); + const actualHexString = algosdk.bytesToHex(binString); + assert.deepStrictEqual( + actualHexString, + expectedEncoding, + `Incorrect encoding of ${testCase}; got ${actualHexString}` + ); + } + }); + }); }); diff --git a/tests/4.Utils.ts b/tests/4.Utils.ts index 470a4ad97..a2b589d4b 100644 --- a/tests/4.Utils.ts +++ b/tests/4.Utils.ts @@ -34,96 +34,6 @@ describe('utils', () => { assert.deepStrictEqual(expected, actual); }); }); - - describe('Base64 decoding utilities', () => { - it('should decode bytes from Base64', () => { - const testCases = [ - [ - Uint8Array.from([ - 97, - 32, - 196, - 128, - 32, - 240, - 144, - 128, - 128, - 32, - 230, - 150, - 135, - 32, - 240, - 159, - 166, - 132, - ]), // a Ā 𐀀 文 🦄 - 'YSDEgCDwkICAIOaWhyDwn6aE', - ], - [ - Uint8Array.from([0, 1, 2, 3, 4, 46, 46, 46, 254, 255]), // non UTF-8 bytes - 'AAECAwQuLi7+/w==', - ], - ]; - for (const [expectedBytes, expectedEncoding] of testCases) { - const actualBytes = utils.base64ToBytes(expectedEncoding as string); - assert.deepStrictEqual( - actualBytes, - expectedBytes, - `Incorrect encoding of ${expectedBytes}; got ${actualBytes}` - ); - } - }); - - it('should decode and encode Base64 roundtrip for UTF-8 strings', () => { - const testCases = [ - ['Hello, Algorand!', 'SGVsbG8sIEFsZ29yYW5kIQ=='], - ['a Ā 𐀀 文 🦄', 'YSDEgCDwkICAIOaWhyDwn6aE'], - ['(╯°□°)``` ┻━┻ 00\\', 'KOKVr8Kw4pahwrDvvIlgYGAg4pS74pSB4pS7IDAwXA=='], - ]; - for (const [testCase, expectedEncoding] of testCases) { - const actualB64Decoding = utils.base64ToString(expectedEncoding); - assert.deepStrictEqual( - actualB64Decoding, - testCase, - `Incorrect encoding of ${testCase}; got ${actualB64Decoding}` - ); - - const byteArray = new TextEncoder().encode(testCase); - const base64String = utils.bytesToBase64(byteArray); - const roundTripString = new TextDecoder().decode( - utils.base64ToBytes(base64String) - ); - - assert.deepStrictEqual( - roundTripString, - testCase, - `Incorrect decoding of ${testCase}; got ${roundTripString}` - ); - } - }); - - it('should encode bytes to hex', () => { - const testCases = [ - ['Hello, Algorand!', '48656c6c6f2c20416c676f72616e6421'], - ['a Ā 𐀀 文 🦄', '6120c48020f090808020e6968720f09fa684'], - [ - '(╯°□°)``` ┻━┻ 00\\', - '28e295afc2b0e296a1c2b0efbc8960606020e294bbe29481e294bb2030305c', - ], - ]; - for (const [testCase, expectedEncoding] of testCases) { - const binString = new TextEncoder().encode(testCase); - const actualHexString = utils.bytesToHex(binString); - assert.deepStrictEqual( - actualHexString, - expectedEncoding, - `Incorrect encoding of ${testCase}; got ${actualHexString}` - ); - } - }); - }); }); describe('nacl wrapper', () => { From 0c5e393fdb74b0ee2906e06a5f44d3f4aa08d7c5 Mon Sep 17 00:00:00 2001 From: algochoi <86622919+algochoi@users.noreply.github.com> Date: Mon, 17 Jul 2023 09:08:37 -0400 Subject: [PATCH 18/34] Fix imports to prefix algosdk --- examples/app.ts | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/examples/app.ts b/examples/app.ts index 721fae354..c5829a862 100644 --- a/examples/app.ts +++ b/examples/app.ts @@ -6,7 +6,6 @@ import fs from 'fs'; import path from 'path'; import { getLocalAlgodClient, getLocalAccounts, compileProgram } from './utils'; import algosdk from '../src'; -import { base64ToBytes, base64ToString } from '../src/encoding/binarydata'; async function main() { const algodClient = getLocalAlgodClient(); @@ -29,13 +28,13 @@ async function main() { // example: APP_COMPILE const approvalCompileResp = await algodClient.compile(approvalProgram).do(); - const compiledApprovalProgram: Uint8Array = base64ToBytes( + const compiledApprovalProgram: Uint8Array = algosdk.base64ToBytes( approvalCompileResp.result ); const clearCompileResp = await algodClient.compile(clearProgram).do(); - const compiledClearProgram: Uint8Array = base64ToBytes( + const compiledClearProgram: Uint8Array = algosdk.base64ToBytes( clearCompileResp.result ); // example: APP_COMPILE @@ -153,10 +152,10 @@ async function main() { console.log(`Raw global state - ${JSON.stringify(globalState)}`); // decode b64 string key with Buffer - const globalKey = base64ToString(globalState.key); + const globalKey = algosdk.base64ToString(globalState.key); // decode b64 address value with encodeAddress and Buffer const globalValue = algosdk.encodeAddress( - base64ToBytes(globalState.value.bytes) + algosdk.base64ToBytes(globalState.value.bytes) ); console.log(`Decoded global state - ${globalKey}: ${globalValue}`); @@ -169,7 +168,7 @@ async function main() { console.log(`Raw local state - ${JSON.stringify(localState)}`); // decode b64 string key with Buffer - const localKey = base64ToString(localState.key); + const localKey = algosdk.base64ToString(localState.key); // get uint value directly const localValue = localState.value.uint; From f8230e55f6bd36b4b5478b41c014ae44c0f396e5 Mon Sep 17 00:00:00 2001 From: algochoi <86622919+algochoi@users.noreply.github.com> Date: Tue, 18 Jul 2023 09:40:07 -0400 Subject: [PATCH 19/34] Resolving merge conflicts --- examples/codec.ts | 2 +- examples/lsig.ts | 2 +- src/client/v2/algod/models/types.ts | 334 +++++++++++++++++++++----- src/client/v2/indexer/models/types.ts | 137 +++++------ src/composer.ts | 9 +- src/dryrun.ts | 4 +- src/transaction.ts | 31 +-- tests/5.Transaction.js | 9 +- tests/cucumber/steps/steps.js | 4 +- 9 files changed, 355 insertions(+), 177 deletions(-) diff --git a/examples/codec.ts b/examples/codec.ts index d57e7625f..dafdf80ae 100644 --- a/examples/codec.ts +++ b/examples/codec.ts @@ -3,7 +3,7 @@ /* eslint-disable no-promise-executor-return */ /* eslint-disable no-console */ import algosdk from '../src'; -import { getLocalAlgodClient, getLocalAccounts } from './utils'; +import { getLocalAccounts, getLocalAlgodClient } from './utils'; async function main() { const client = getLocalAlgodClient(); diff --git a/examples/lsig.ts b/examples/lsig.ts index 7beb42979..1aa722b2f 100644 --- a/examples/lsig.ts +++ b/examples/lsig.ts @@ -3,7 +3,7 @@ /* eslint-disable no-promise-executor-return */ /* eslint-disable no-console */ import algosdk from '../src'; -import { getLocalAlgodClient, getLocalAccounts } from './utils'; +import { getLocalAccounts, getLocalAlgodClient } from './utils'; async function main() { const client = getLocalAlgodClient(); diff --git a/src/client/v2/algod/models/types.ts b/src/client/v2/algod/models/types.ts index ace6b61e4..cc4ed5c83 100644 --- a/src/client/v2/algod/models/types.ts +++ b/src/client/v2/algod/models/types.ts @@ -3,10 +3,10 @@ */ /* eslint-disable no-use-before-define */ -import { Buffer } from 'buffer'; -import BaseModel from '../../basemodel'; -import { EncodedSignedTransaction } from '../../../../types/transactions/encoded'; +import { base64ToBytes } from '../../../../encoding/binarydata'; import BlockHeader from '../../../../types/blockHeader'; +import { EncodedSignedTransaction } from '../../../../types/transactions/encoded'; +import BaseModel from '../../basemodel'; /** * Account information at a given round. @@ -622,18 +622,18 @@ export class AccountParticipation extends BaseModel { super(); this.selectionParticipationKey = typeof selectionParticipationKey === 'string' - ? new Uint8Array(Buffer.from(selectionParticipationKey, 'base64')) + ? base64ToBytes(selectionParticipationKey) : selectionParticipationKey; this.voteFirstValid = voteFirstValid; this.voteKeyDilution = voteKeyDilution; this.voteLastValid = voteLastValid; this.voteParticipationKey = typeof voteParticipationKey === 'string' - ? new Uint8Array(Buffer.from(voteParticipationKey, 'base64')) + ? base64ToBytes(voteParticipationKey) : voteParticipationKey; this.stateProofKey = typeof stateProofKey === 'string' - ? new Uint8Array(Buffer.from(stateProofKey, 'base64')) + ? base64ToBytes(stateProofKey) : stateProofKey; this.attribute_map = { @@ -922,11 +922,11 @@ export class ApplicationParams extends BaseModel { super(); this.approvalProgram = typeof approvalProgram === 'string' - ? new Uint8Array(Buffer.from(approvalProgram, 'base64')) + ? base64ToBytes(approvalProgram) : approvalProgram; this.clearStateProgram = typeof clearStateProgram === 'string' - ? new Uint8Array(Buffer.from(clearStateProgram, 'base64')) + ? base64ToBytes(clearStateProgram) : clearStateProgram; this.creator = creator; this.extraProgramPages = extraProgramPages; @@ -1329,24 +1329,19 @@ export class AssetParams extends BaseModel { this.manager = manager; this.metadataHash = typeof metadataHash === 'string' - ? new Uint8Array(Buffer.from(metadataHash, 'base64')) + ? base64ToBytes(metadataHash) : metadataHash; this.name = name; this.nameB64 = - typeof nameB64 === 'string' - ? new Uint8Array(Buffer.from(nameB64, 'base64')) - : nameB64; + typeof nameB64 === 'string' ? base64ToBytes(nameB64) : nameB64; this.reserve = reserve; this.unitName = unitName; this.unitNameB64 = typeof unitNameB64 === 'string' - ? new Uint8Array(Buffer.from(unitNameB64, 'base64')) + ? base64ToBytes(unitNameB64) : unitNameB64; this.url = url; - this.urlB64 = - typeof urlB64 === 'string' - ? new Uint8Array(Buffer.from(urlB64, 'base64')) - : urlB64; + this.urlB64 = typeof urlB64 === 'string' ? base64ToBytes(urlB64) : urlB64; this.attribute_map = { creator: 'creator', @@ -1493,6 +1488,11 @@ export class Box extends BaseModel { */ public name: Uint8Array; + /** + * The round for which this information is relevant + */ + public round: number | bigint; + /** * (value) box value, base64 encoded. */ @@ -1501,27 +1501,26 @@ export class Box extends BaseModel { /** * Creates a new `Box` object. * @param name - (name) box name, base64 encoded + * @param round - The round for which this information is relevant * @param value - (value) box value, base64 encoded. */ constructor({ name, + round, value, }: { name: string | Uint8Array; + round: number | bigint; value: string | Uint8Array; }) { super(); - this.name = - typeof name === 'string' - ? new Uint8Array(Buffer.from(name, 'base64')) - : name; - this.value = - typeof value === 'string' - ? new Uint8Array(Buffer.from(value, 'base64')) - : value; + this.name = typeof name === 'string' ? base64ToBytes(name) : name; + this.round = round; + this.value = typeof value === 'string' ? base64ToBytes(value) : value; this.attribute_map = { name: 'name', + round: 'round', value: 'value', }; } @@ -1531,10 +1530,13 @@ export class Box extends BaseModel { /* eslint-disable dot-notation */ if (typeof data['name'] === 'undefined') throw new Error(`Response is missing required field 'name': ${data}`); + if (typeof data['round'] === 'undefined') + throw new Error(`Response is missing required field 'round': ${data}`); if (typeof data['value'] === 'undefined') throw new Error(`Response is missing required field 'value': ${data}`); return new Box({ name: data['name'], + round: data['round'], value: data['value'], }); /* eslint-enable dot-notation */ @@ -1556,10 +1558,7 @@ export class BoxDescriptor extends BaseModel { */ constructor({ name }: { name: string | Uint8Array }) { super(); - this.name = - typeof name === 'string' - ? new Uint8Array(Buffer.from(name, 'base64')) - : name; + this.name = typeof name === 'string' ? base64ToBytes(name) : name; this.attribute_map = { name: 'name', @@ -2532,14 +2531,8 @@ export class KvDelta extends BaseModel { value?: string | Uint8Array; }) { super(); - this.key = - typeof key === 'string' - ? new Uint8Array(Buffer.from(key, 'base64')) - : key; - this.value = - typeof value === 'string' - ? new Uint8Array(Buffer.from(value, 'base64')) - : value; + this.key = typeof key === 'string' ? base64ToBytes(key) : key; + this.value = typeof value === 'string' ? base64ToBytes(value) : value; this.attribute_map = { key: 'key', @@ -2580,8 +2573,8 @@ export class LedgerStateDeltaForTransactionGroup extends BaseModel { this.ids = ids; this.attribute_map = { - delta: 'delta', - ids: 'ids', + delta: 'Delta', + ids: 'Ids', }; } @@ -2590,15 +2583,15 @@ export class LedgerStateDeltaForTransactionGroup extends BaseModel { data: Record ): LedgerStateDeltaForTransactionGroup { /* eslint-disable dot-notation */ - if (typeof data['delta'] === 'undefined') - throw new Error(`Response is missing required field 'delta': ${data}`); - if (!Array.isArray(data['ids'])) + if (typeof data['Delta'] === 'undefined') + throw new Error(`Response is missing required field 'Delta': ${data}`); + if (!Array.isArray(data['Ids'])) throw new Error( - `Response is missing required array field 'ids': ${data}` + `Response is missing required array field 'Ids': ${data}` ); return new LedgerStateDeltaForTransactionGroup({ - delta: data['delta'], - ids: data['ids'], + delta: data['Delta'], + ids: data['Ids'], }); /* eslint-enable dot-notation */ } @@ -2642,10 +2635,7 @@ export class LightBlockHeaderProof extends BaseModel { }) { super(); this.index = index; - this.proof = - typeof proof === 'string' - ? new Uint8Array(Buffer.from(proof, 'base64')) - : proof; + this.proof = typeof proof === 'string' ? base64ToBytes(proof) : proof; this.treedepth = treedepth; this.attribute_map = { @@ -3364,6 +3354,11 @@ export class SimulateRequest extends BaseModel { */ public allowMoreLogging?: boolean; + /** + * An object that configures simulation execution trace. + */ + public execTraceConfig?: SimulateTraceConfig; + /** * Applies extra opcode budget during simulation for each transaction group. */ @@ -3375,29 +3370,34 @@ export class SimulateRequest extends BaseModel { * @param allowEmptySignatures - Allow transactions without signatures to be simulated as if they had correct * signatures. * @param allowMoreLogging - Lifts limits on log opcode usage during simulation. + * @param execTraceConfig - An object that configures simulation execution trace. * @param extraOpcodeBudget - Applies extra opcode budget during simulation for each transaction group. */ constructor({ txnGroups, allowEmptySignatures, allowMoreLogging, + execTraceConfig, extraOpcodeBudget, }: { txnGroups: SimulateRequestTransactionGroup[]; allowEmptySignatures?: boolean; allowMoreLogging?: boolean; + execTraceConfig?: SimulateTraceConfig; extraOpcodeBudget?: number | bigint; }) { super(); this.txnGroups = txnGroups; this.allowEmptySignatures = allowEmptySignatures; this.allowMoreLogging = allowMoreLogging; + this.execTraceConfig = execTraceConfig; this.extraOpcodeBudget = extraOpcodeBudget; this.attribute_map = { txnGroups: 'txn-groups', allowEmptySignatures: 'allow-empty-signatures', allowMoreLogging: 'allow-more-logging', + execTraceConfig: 'exec-trace-config', extraOpcodeBudget: 'extra-opcode-budget', }; } @@ -3415,6 +3415,10 @@ export class SimulateRequest extends BaseModel { ), allowEmptySignatures: data['allow-empty-signatures'], allowMoreLogging: data['allow-more-logging'], + execTraceConfig: + typeof data['exec-trace-config'] !== 'undefined' + ? SimulateTraceConfig.from_obj_for_encoding(data['exec-trace-config']) + : undefined, extraOpcodeBudget: data['extra-opcode-budget'], }); /* eslint-enable dot-notation */ @@ -3486,6 +3490,11 @@ export class SimulateResponse extends BaseModel { */ public evalOverrides?: SimulationEvalOverrides; + /** + * An object that configures simulation execution trace. + */ + public execTraceConfig?: SimulateTraceConfig; + /** * Creates a new `SimulateResponse` object. * @param lastRound - The round immediately preceding this simulation. State changes through this @@ -3495,29 +3504,34 @@ export class SimulateResponse extends BaseModel { * @param evalOverrides - The set of parameters and limits override during simulation. If this set of * parameters is present, then evaluation parameters may differ from standard * evaluation in certain ways. + * @param execTraceConfig - An object that configures simulation execution trace. */ constructor({ lastRound, txnGroups, version, evalOverrides, + execTraceConfig, }: { lastRound: number | bigint; txnGroups: SimulateTransactionGroupResult[]; version: number | bigint; evalOverrides?: SimulationEvalOverrides; + execTraceConfig?: SimulateTraceConfig; }) { super(); this.lastRound = lastRound; this.txnGroups = txnGroups; this.version = version; this.evalOverrides = evalOverrides; + this.execTraceConfig = execTraceConfig; this.attribute_map = { lastRound: 'last-round', txnGroups: 'txn-groups', version: 'version', evalOverrides: 'eval-overrides', + execTraceConfig: 'exec-trace-config', }; } @@ -3546,6 +3560,42 @@ export class SimulateResponse extends BaseModel { data['eval-overrides'] ) : undefined, + execTraceConfig: + typeof data['exec-trace-config'] !== 'undefined' + ? SimulateTraceConfig.from_obj_for_encoding(data['exec-trace-config']) + : undefined, + }); + /* eslint-enable dot-notation */ + } +} + +/** + * An object that configures simulation execution trace. + */ +export class SimulateTraceConfig extends BaseModel { + /** + * A boolean option for opting in execution trace features simulation endpoint. + */ + public enable?: boolean; + + /** + * Creates a new `SimulateTraceConfig` object. + * @param enable - A boolean option for opting in execution trace features simulation endpoint. + */ + constructor({ enable }: { enable?: boolean }) { + super(); + this.enable = enable; + + this.attribute_map = { + enable: 'enable', + }; + } + + // eslint-disable-next-line camelcase + static from_obj_for_encoding(data: Record): SimulateTraceConfig { + /* eslint-disable dot-notation */ + return new SimulateTraceConfig({ + enable: data['enable'], }); /* eslint-enable dot-notation */ } @@ -3663,6 +3713,12 @@ export class SimulateTransactionResult extends BaseModel { */ public appBudgetConsumed?: number | bigint; + /** + * The execution trace of calling an app or a logic sig, containing the inner app + * call trace in a recursive way. + */ + public execTrace?: SimulationTransactionExecTrace; + /** * Budget used during execution of a logic sig transaction. */ @@ -3674,25 +3730,31 @@ export class SimulateTransactionResult extends BaseModel { * includes confirmation details like the round and reward details. * @param appBudgetConsumed - Budget used during execution of an app call transaction. This value includes * budged used by inner app calls spawned by this transaction. + * @param execTrace - The execution trace of calling an app or a logic sig, containing the inner app + * call trace in a recursive way. * @param logicSigBudgetConsumed - Budget used during execution of a logic sig transaction. */ constructor({ txnResult, appBudgetConsumed, + execTrace, logicSigBudgetConsumed, }: { txnResult: PendingTransactionResponse; appBudgetConsumed?: number | bigint; + execTrace?: SimulationTransactionExecTrace; logicSigBudgetConsumed?: number | bigint; }) { super(); this.txnResult = txnResult; this.appBudgetConsumed = appBudgetConsumed; + this.execTrace = execTrace; this.logicSigBudgetConsumed = logicSigBudgetConsumed; this.attribute_map = { txnResult: 'txn-result', appBudgetConsumed: 'app-budget-consumed', + execTrace: 'exec-trace', logicSigBudgetConsumed: 'logic-sig-budget-consumed', }; } @@ -3711,6 +3773,12 @@ export class SimulateTransactionResult extends BaseModel { data['txn-result'] ), appBudgetConsumed: data['app-budget-consumed'], + execTrace: + typeof data['exec-trace'] !== 'undefined' + ? SimulationTransactionExecTrace.from_obj_for_encoding( + data['exec-trace'] + ) + : undefined, logicSigBudgetConsumed: data['logic-sig-budget-consumed'], }); /* eslint-enable dot-notation */ @@ -3792,6 +3860,151 @@ export class SimulationEvalOverrides extends BaseModel { } } +/** + * The set of trace information and effect from evaluating a single opcode. + */ +export class SimulationOpcodeTraceUnit extends BaseModel { + /** + * The program counter of the current opcode being evaluated. + */ + public pc: number | bigint; + + /** + * The indexes of the traces for inner transactions spawned by this opcode, if any. + */ + public spawnedInners?: (number | bigint)[]; + + /** + * Creates a new `SimulationOpcodeTraceUnit` object. + * @param pc - The program counter of the current opcode being evaluated. + * @param spawnedInners - The indexes of the traces for inner transactions spawned by this opcode, if any. + */ + constructor({ + pc, + spawnedInners, + }: { + pc: number | bigint; + spawnedInners?: (number | bigint)[]; + }) { + super(); + this.pc = pc; + this.spawnedInners = spawnedInners; + + this.attribute_map = { + pc: 'pc', + spawnedInners: 'spawned-inners', + }; + } + + // eslint-disable-next-line camelcase + static from_obj_for_encoding( + data: Record + ): SimulationOpcodeTraceUnit { + /* eslint-disable dot-notation */ + if (typeof data['pc'] === 'undefined') + throw new Error(`Response is missing required field 'pc': ${data}`); + return new SimulationOpcodeTraceUnit({ + pc: data['pc'], + spawnedInners: data['spawned-inners'], + }); + /* eslint-enable dot-notation */ + } +} + +/** + * The execution trace of calling an app or a logic sig, containing the inner app + * call trace in a recursive way. + */ +export class SimulationTransactionExecTrace extends BaseModel { + /** + * Program trace that contains a trace of opcode effects in an approval program. + */ + public approvalProgramTrace?: SimulationOpcodeTraceUnit[]; + + /** + * Program trace that contains a trace of opcode effects in a clear state program. + */ + public clearStateProgramTrace?: SimulationOpcodeTraceUnit[]; + + /** + * An array of SimulationTransactionExecTrace representing the execution trace of + * any inner transactions executed. + */ + public innerTrace?: SimulationTransactionExecTrace[]; + + /** + * Program trace that contains a trace of opcode effects in a logic sig. + */ + public logicSigTrace?: SimulationOpcodeTraceUnit[]; + + /** + * Creates a new `SimulationTransactionExecTrace` object. + * @param approvalProgramTrace - Program trace that contains a trace of opcode effects in an approval program. + * @param clearStateProgramTrace - Program trace that contains a trace of opcode effects in a clear state program. + * @param innerTrace - An array of SimulationTransactionExecTrace representing the execution trace of + * any inner transactions executed. + * @param logicSigTrace - Program trace that contains a trace of opcode effects in a logic sig. + */ + constructor({ + approvalProgramTrace, + clearStateProgramTrace, + innerTrace, + logicSigTrace, + }: { + approvalProgramTrace?: SimulationOpcodeTraceUnit[]; + clearStateProgramTrace?: SimulationOpcodeTraceUnit[]; + innerTrace?: SimulationTransactionExecTrace[]; + logicSigTrace?: SimulationOpcodeTraceUnit[]; + }) { + super(); + this.approvalProgramTrace = approvalProgramTrace; + this.clearStateProgramTrace = clearStateProgramTrace; + this.innerTrace = innerTrace; + this.logicSigTrace = logicSigTrace; + + this.attribute_map = { + approvalProgramTrace: 'approval-program-trace', + clearStateProgramTrace: 'clear-state-program-trace', + innerTrace: 'inner-trace', + logicSigTrace: 'logic-sig-trace', + }; + } + + // eslint-disable-next-line camelcase + static from_obj_for_encoding( + data: Record + ): SimulationTransactionExecTrace { + /* eslint-disable dot-notation */ + return new SimulationTransactionExecTrace({ + approvalProgramTrace: + typeof data['approval-program-trace'] !== 'undefined' + ? data['approval-program-trace'].map( + SimulationOpcodeTraceUnit.from_obj_for_encoding + ) + : undefined, + clearStateProgramTrace: + typeof data['clear-state-program-trace'] !== 'undefined' + ? data['clear-state-program-trace'].map( + SimulationOpcodeTraceUnit.from_obj_for_encoding + ) + : undefined, + innerTrace: + typeof data['inner-trace'] !== 'undefined' + ? data['inner-trace'].map( + SimulationTransactionExecTrace.from_obj_for_encoding + ) + : undefined, + logicSigTrace: + typeof data['logic-sig-trace'] !== 'undefined' + ? data['logic-sig-trace'].map( + SimulationOpcodeTraceUnit.from_obj_for_encoding + ) + : undefined, + }); + /* eslint-enable dot-notation */ + } +} + /** * Represents a state proof and its corresponding message */ @@ -3821,9 +4034,7 @@ export class StateProof extends BaseModel { super(); this.message = message; this.stateproof = - typeof stateproof === 'string' - ? new Uint8Array(Buffer.from(stateproof, 'base64')) - : stateproof; + typeof stateproof === 'string' ? base64ToBytes(stateproof) : stateproof; this.attribute_map = { message: 'Message', @@ -3905,14 +4116,14 @@ export class StateProofMessage extends BaseModel { super(); this.blockheaderscommitment = typeof blockheaderscommitment === 'string' - ? new Uint8Array(Buffer.from(blockheaderscommitment, 'base64')) + ? base64ToBytes(blockheaderscommitment) : blockheaderscommitment; this.firstattestedround = firstattestedround; this.lastattestedround = lastattestedround; this.lnprovenweight = lnprovenweight; this.voterscommitment = typeof voterscommitment === 'string' - ? new Uint8Array(Buffer.from(voterscommitment, 'base64')) + ? base64ToBytes(voterscommitment) : voterscommitment; this.attribute_map = { @@ -4150,7 +4361,7 @@ export class TransactionGroupLedgerStateDeltasForRoundResponse extends BaseModel this.deltas = deltas; this.attribute_map = { - deltas: 'deltas', + deltas: 'Deltas', }; } @@ -4246,7 +4457,7 @@ export class TransactionParametersResponse extends BaseModel { this.fee = fee; this.genesisHash = typeof genesisHash === 'string' - ? new Uint8Array(Buffer.from(genesisHash, 'base64')) + ? base64ToBytes(genesisHash) : genesisHash; this.genesisId = genesisId; this.lastRound = lastRound; @@ -4357,14 +4568,9 @@ export class TransactionProofResponse extends BaseModel { }) { super(); this.idx = idx; - this.proof = - typeof proof === 'string' - ? new Uint8Array(Buffer.from(proof, 'base64')) - : proof; + this.proof = typeof proof === 'string' ? base64ToBytes(proof) : proof; this.stibhash = - typeof stibhash === 'string' - ? new Uint8Array(Buffer.from(stibhash, 'base64')) - : stibhash; + typeof stibhash === 'string' ? base64ToBytes(stibhash) : stibhash; this.treedepth = treedepth; this.hashtype = hashtype; @@ -4437,7 +4643,7 @@ export class Version extends BaseModel { this.build = build; this.genesisHashB64 = typeof genesisHashB64 === 'string' - ? new Uint8Array(Buffer.from(genesisHashB64, 'base64')) + ? base64ToBytes(genesisHashB64) : genesisHashB64; this.genesisId = genesisId; this.versions = versions; diff --git a/src/client/v2/indexer/models/types.ts b/src/client/v2/indexer/models/types.ts index 12b0555f4..76c48ae7c 100644 --- a/src/client/v2/indexer/models/types.ts +++ b/src/client/v2/indexer/models/types.ts @@ -3,7 +3,7 @@ */ /* eslint-disable no-use-before-define */ -import { Buffer } from 'buffer'; +import { base64ToBytes } from '../../../../encoding/binarydata'; import BaseModel from '../../basemodel'; /** @@ -497,18 +497,18 @@ export class AccountParticipation extends BaseModel { super(); this.selectionParticipationKey = typeof selectionParticipationKey === 'string' - ? new Uint8Array(Buffer.from(selectionParticipationKey, 'base64')) + ? base64ToBytes(selectionParticipationKey) : selectionParticipationKey; this.voteFirstValid = voteFirstValid; this.voteKeyDilution = voteKeyDilution; this.voteLastValid = voteLastValid; this.voteParticipationKey = typeof voteParticipationKey === 'string' - ? new Uint8Array(Buffer.from(voteParticipationKey, 'base64')) + ? base64ToBytes(voteParticipationKey) : voteParticipationKey; this.stateProofKey = typeof stateProofKey === 'string' - ? new Uint8Array(Buffer.from(stateProofKey, 'base64')) + ? base64ToBytes(stateProofKey) : stateProofKey; this.attribute_map = { @@ -1184,11 +1184,11 @@ export class ApplicationParams extends BaseModel { super(); this.approvalProgram = typeof approvalProgram === 'string' - ? new Uint8Array(Buffer.from(approvalProgram, 'base64')) + ? base64ToBytes(approvalProgram) : approvalProgram; this.clearStateProgram = typeof clearStateProgram === 'string' - ? new Uint8Array(Buffer.from(clearStateProgram, 'base64')) + ? base64ToBytes(clearStateProgram) : clearStateProgram; this.creator = creator; this.extraProgramPages = extraProgramPages; @@ -1910,24 +1910,19 @@ export class AssetParams extends BaseModel { this.manager = manager; this.metadataHash = typeof metadataHash === 'string' - ? new Uint8Array(Buffer.from(metadataHash, 'base64')) + ? base64ToBytes(metadataHash) : metadataHash; this.name = name; this.nameB64 = - typeof nameB64 === 'string' - ? new Uint8Array(Buffer.from(nameB64, 'base64')) - : nameB64; + typeof nameB64 === 'string' ? base64ToBytes(nameB64) : nameB64; this.reserve = reserve; this.unitName = unitName; this.unitNameB64 = typeof unitNameB64 === 'string' - ? new Uint8Array(Buffer.from(unitNameB64, 'base64')) + ? base64ToBytes(unitNameB64) : unitNameB64; this.url = url; - this.urlB64 = - typeof urlB64 === 'string' - ? new Uint8Array(Buffer.from(urlB64, 'base64')) - : urlB64; + this.urlB64 = typeof urlB64 === 'string' ? base64ToBytes(urlB64) : urlB64; this.attribute_map = { creator: 'creator', @@ -2255,26 +2250,23 @@ export class Block extends BaseModel { super(); this.genesisHash = typeof genesisHash === 'string' - ? new Uint8Array(Buffer.from(genesisHash, 'base64')) + ? base64ToBytes(genesisHash) : genesisHash; this.genesisId = genesisId; this.previousBlockHash = typeof previousBlockHash === 'string' - ? new Uint8Array(Buffer.from(previousBlockHash, 'base64')) + ? base64ToBytes(previousBlockHash) : previousBlockHash; this.round = round; - this.seed = - typeof seed === 'string' - ? new Uint8Array(Buffer.from(seed, 'base64')) - : seed; + this.seed = typeof seed === 'string' ? base64ToBytes(seed) : seed; this.timestamp = timestamp; this.transactionsRoot = typeof transactionsRoot === 'string' - ? new Uint8Array(Buffer.from(transactionsRoot, 'base64')) + ? base64ToBytes(transactionsRoot) : transactionsRoot; this.transactionsRootSha256 = typeof transactionsRootSha256 === 'string' - ? new Uint8Array(Buffer.from(transactionsRootSha256, 'base64')) + ? base64ToBytes(transactionsRootSha256) : transactionsRootSha256; this.participationUpdates = participationUpdates; this.rewards = rewards; @@ -2653,6 +2645,11 @@ export class Box extends BaseModel { */ public name: Uint8Array; + /** + * The round for which this information is relevant + */ + public round: number | bigint; + /** * (value) box value, base64 encoded. */ @@ -2661,27 +2658,26 @@ export class Box extends BaseModel { /** * Creates a new `Box` object. * @param name - (name) box name, base64 encoded + * @param round - The round for which this information is relevant * @param value - (value) box value, base64 encoded. */ constructor({ name, + round, value, }: { name: string | Uint8Array; + round: number | bigint; value: string | Uint8Array; }) { super(); - this.name = - typeof name === 'string' - ? new Uint8Array(Buffer.from(name, 'base64')) - : name; - this.value = - typeof value === 'string' - ? new Uint8Array(Buffer.from(value, 'base64')) - : value; + this.name = typeof name === 'string' ? base64ToBytes(name) : name; + this.round = round; + this.value = typeof value === 'string' ? base64ToBytes(value) : value; this.attribute_map = { name: 'name', + round: 'round', value: 'value', }; } @@ -2691,10 +2687,13 @@ export class Box extends BaseModel { /* eslint-disable dot-notation */ if (typeof data['name'] === 'undefined') throw new Error(`Response is missing required field 'name': ${data}`); + if (typeof data['round'] === 'undefined') + throw new Error(`Response is missing required field 'round': ${data}`); if (typeof data['value'] === 'undefined') throw new Error(`Response is missing required field 'value': ${data}`); return new Box({ name: data['name'], + round: data['round'], value: data['value'], }); /* eslint-enable dot-notation */ @@ -2716,10 +2715,7 @@ export class BoxDescriptor extends BaseModel { */ constructor({ name }: { name: string | Uint8Array }) { super(); - this.name = - typeof name === 'string' - ? new Uint8Array(Buffer.from(name, 'base64')) - : name; + this.name = typeof name === 'string' ? base64ToBytes(name) : name; this.attribute_map = { name: 'name', @@ -3125,14 +3121,14 @@ export class IndexerStateProofMessage extends BaseModel { super(); this.blockHeadersCommitment = typeof blockHeadersCommitment === 'string' - ? new Uint8Array(Buffer.from(blockHeadersCommitment, 'base64')) + ? base64ToBytes(blockHeadersCommitment) : blockHeadersCommitment; this.firstAttestedRound = firstAttestedRound; this.latestAttestedRound = latestAttestedRound; this.lnProvenWeight = lnProvenWeight; this.votersCommitment = typeof votersCommitment === 'string' - ? new Uint8Array(Buffer.from(votersCommitment, 'base64')) + ? base64ToBytes(votersCommitment) : votersCommitment; this.attribute_map = { @@ -3421,9 +3417,7 @@ export class StateProofFields extends BaseModel { this.reveals = reveals; this.saltVersion = saltVersion; this.sigCommit = - typeof sigCommit === 'string' - ? new Uint8Array(Buffer.from(sigCommit, 'base64')) - : sigCommit; + typeof sigCommit === 'string' ? base64ToBytes(sigCommit) : sigCommit; this.sigProofs = sigProofs; this.signedWeight = signedWeight; @@ -3652,13 +3646,13 @@ export class StateProofSignature extends BaseModel { super(); this.falconSignature = typeof falconSignature === 'string' - ? new Uint8Array(Buffer.from(falconSignature, 'base64')) + ? base64ToBytes(falconSignature) : falconSignature; this.merkleArrayIndex = merkleArrayIndex; this.proof = proof; this.verifyingKey = typeof verifyingKey === 'string' - ? new Uint8Array(Buffer.from(verifyingKey, 'base64')) + ? base64ToBytes(verifyingKey) : verifyingKey; this.attribute_map = { @@ -3734,7 +3728,7 @@ export class StateProofTracking extends BaseModel { this.type = type; this.votersCommitment = typeof votersCommitment === 'string' - ? new Uint8Array(Buffer.from(votersCommitment, 'base64')) + ? base64ToBytes(votersCommitment) : votersCommitment; this.attribute_map = { @@ -3783,9 +3777,7 @@ export class StateProofVerifier extends BaseModel { }) { super(); this.commitment = - typeof commitment === 'string' - ? new Uint8Array(Buffer.from(commitment, 'base64')) - : commitment; + typeof commitment === 'string' ? base64ToBytes(commitment) : commitment; this.keyLifetime = keyLifetime; this.attribute_map = { @@ -4348,28 +4340,19 @@ export class Transaction extends BaseModel { this.createdAssetIndex = createdAssetIndex; this.genesisHash = typeof genesisHash === 'string' - ? new Uint8Array(Buffer.from(genesisHash, 'base64')) + ? base64ToBytes(genesisHash) : genesisHash; this.genesisId = genesisId; this.globalStateDelta = globalStateDelta; - this.group = - typeof group === 'string' - ? new Uint8Array(Buffer.from(group, 'base64')) - : group; + this.group = typeof group === 'string' ? base64ToBytes(group) : group; this.id = id; this.innerTxns = innerTxns; this.intraRoundOffset = intraRoundOffset; this.keyregTransaction = keyregTransaction; - this.lease = - typeof lease === 'string' - ? new Uint8Array(Buffer.from(lease, 'base64')) - : lease; + this.lease = typeof lease === 'string' ? base64ToBytes(lease) : lease; this.localStateDelta = localStateDelta; this.logs = logs; - this.note = - typeof note === 'string' - ? new Uint8Array(Buffer.from(note, 'base64')) - : note; + this.note = typeof note === 'string' ? base64ToBytes(note) : note; this.paymentTransaction = paymentTransaction; this.receiverRewards = receiverRewards; this.rekeyTo = rekeyTo; @@ -4677,11 +4660,11 @@ export class TransactionApplication extends BaseModel { this.applicationArgs = applicationArgs; this.approvalProgram = typeof approvalProgram === 'string' - ? new Uint8Array(Buffer.from(approvalProgram, 'base64')) + ? base64ToBytes(approvalProgram) : approvalProgram; this.clearStateProgram = typeof clearStateProgram === 'string' - ? new Uint8Array(Buffer.from(clearStateProgram, 'base64')) + ? base64ToBytes(clearStateProgram) : clearStateProgram; this.extraProgramPages = extraProgramPages; this.foreignApps = foreignApps; @@ -4892,7 +4875,7 @@ export class TransactionAssetTransfer extends BaseModel { public receiver: string; /** - * Number of assets transfered to the close-to account as part of the transaction. + * Number of assets transferred to the close-to account as part of the transaction. */ public closeAmount?: number | bigint; @@ -4916,7 +4899,7 @@ export class TransactionAssetTransfer extends BaseModel { * that asset in the account's Assets map. * @param assetId - (xaid) ID of the asset being transferred. * @param receiver - (arcv) Recipient address of the transfer. - * @param closeAmount - Number of assets transfered to the close-to account as part of the transaction. + * @param closeAmount - Number of assets transferred to the close-to account as part of the transaction. * @param closeTo - (aclose) Indicates that the asset should be removed from the account's Assets * map, and specifies where the remaining asset holdings should be transferred. * It's always valid to transfer remaining asset holdings to the creator account. @@ -5054,18 +5037,18 @@ export class TransactionKeyreg extends BaseModel { this.nonParticipation = nonParticipation; this.selectionParticipationKey = typeof selectionParticipationKey === 'string' - ? new Uint8Array(Buffer.from(selectionParticipationKey, 'base64')) + ? base64ToBytes(selectionParticipationKey) : selectionParticipationKey; this.stateProofKey = typeof stateProofKey === 'string' - ? new Uint8Array(Buffer.from(stateProofKey, 'base64')) + ? base64ToBytes(stateProofKey) : stateProofKey; this.voteFirstValid = voteFirstValid; this.voteKeyDilution = voteKeyDilution; this.voteLastValid = voteLastValid; this.voteParticipationKey = typeof voteParticipationKey === 'string' - ? new Uint8Array(Buffer.from(voteParticipationKey, 'base64')) + ? base64ToBytes(voteParticipationKey) : voteParticipationKey; this.attribute_map = { @@ -5283,10 +5266,7 @@ export class TransactionSignature extends BaseModel { super(); this.logicsig = logicsig; this.multisig = multisig; - this.sig = - typeof sig === 'string' - ? new Uint8Array(Buffer.from(sig, 'base64')) - : sig; + this.sig = typeof sig === 'string' ? base64ToBytes(sig) : sig; this.attribute_map = { logicsig: 'logicsig', @@ -5366,16 +5346,11 @@ export class TransactionSignatureLogicsig extends BaseModel { signature?: string | Uint8Array; }) { super(); - this.logic = - typeof logic === 'string' - ? new Uint8Array(Buffer.from(logic, 'base64')) - : logic; + this.logic = typeof logic === 'string' ? base64ToBytes(logic) : logic; this.args = args; this.multisigSignature = multisigSignature; this.signature = - typeof signature === 'string' - ? new Uint8Array(Buffer.from(signature, 'base64')) - : signature; + typeof signature === 'string' ? base64ToBytes(signature) : signature; this.attribute_map = { logic: 'logic', @@ -5499,13 +5474,9 @@ export class TransactionSignatureMultisigSubsignature extends BaseModel { }) { super(); this.publicKey = - typeof publicKey === 'string' - ? new Uint8Array(Buffer.from(publicKey, 'base64')) - : publicKey; + typeof publicKey === 'string' ? base64ToBytes(publicKey) : publicKey; this.signature = - typeof signature === 'string' - ? new Uint8Array(Buffer.from(signature, 'base64')) - : signature; + typeof signature === 'string' ? base64ToBytes(signature) : signature; this.attribute_map = { publicKey: 'public-key', diff --git a/src/composer.ts b/src/composer.ts index 9089dfc3c..b75cbefa4 100644 --- a/src/composer.ts +++ b/src/composer.ts @@ -12,11 +12,12 @@ import { } from './abi'; import Algodv2 from './client/v2/algod/algod'; import { - SimulateResponse, SimulateRequest, SimulateRequestTransactionGroup, + SimulateResponse, } from './client/v2/algod/models/types'; -import { EncodedSignedTransaction } from './types'; +import { base64ToBytes } from './encoding/binarydata'; +import * as encoding from './encoding/encoding'; import { assignGroupID } from './group'; import { makeApplicationCallTxnFromObject } from './makeTxn'; import { @@ -25,14 +26,14 @@ import { TransactionWithSigner, } from './signer'; import { decodeSignedTransaction, Transaction } from './transaction'; +import { EncodedSignedTransaction } from './types'; import { BoxReference, OnApplicationComplete, SuggestedParams, } from './types/transactions/base'; +import { arrayEqual } from './utils/utils'; import { waitForConfirmation } from './wait'; -import * as encoding from './encoding/encoding'; -import { arrayEqual, base64ToBytes } from './utils/utils'; // First 4 bytes of SHA-512/256 hash of "return" const RETURN_PREFIX = new Uint8Array([21, 31, 124, 117]); diff --git a/src/dryrun.ts b/src/dryrun.ts index d7aad3789..92185de73 100644 --- a/src/dryrun.ts +++ b/src/dryrun.ts @@ -9,10 +9,10 @@ import { EvalDeltaKeyValue, TealValue, } from './client/v2/algod/models/types'; +import { encodeAddress, getApplicationAddress } from './encoding/address'; +import { base64ToBytes, bytesToHex } from './encoding/binarydata'; import { SignedTransaction } from './transaction'; import { TransactionType } from './types/transactions'; -import { encodeAddress, getApplicationAddress } from './encoding/address'; -import { base64ToBytes, bytesToHex } from './utils/utils'; const defaultAppId = 1380011588; const defaultMaxWidth = 30; diff --git a/src/transaction.ts b/src/transaction.ts index ef23df799..32f0c954a 100644 --- a/src/transaction.ts +++ b/src/transaction.ts @@ -1,25 +1,26 @@ import base32 from 'hi-base32'; +import { translateBoxReferences } from './boxStorage'; import * as address from './encoding/address'; +import { base64ToBytes, bytesToBase64 } from './encoding/binarydata'; import * as encoding from './encoding/encoding'; import * as nacl from './nacl/naclWrappers'; -import * as utils from './utils/utils'; -import { translateBoxReferences } from './boxStorage'; +import { Address } from './types/address'; +import AnyTransaction, { + EncodedLogicSig, + EncodedMultisig, + EncodedSignedTransaction, + EncodedTransaction, + MustHaveSuggestedParams, + MustHaveSuggestedParamsInline, +} from './types/transactions'; import { + BoxReference, OnApplicationComplete, TransactionParams, TransactionType, isTransactionType, - BoxReference, } from './types/transactions/base'; -import AnyTransaction, { - MustHaveSuggestedParams, - MustHaveSuggestedParamsInline, - EncodedTransaction, - EncodedSignedTransaction, - EncodedMultisig, - EncodedLogicSig, -} from './types/transactions'; -import { Address } from './types/address'; +import * as utils from './utils/utils'; const ALGORAND_TRANSACTION_LENGTH = 52; export const ALGORAND_MIN_TX_FEE = 1000; // version v5 @@ -130,7 +131,7 @@ function getKeyregKey( let inputAsBuffer: Uint8Array | undefined; if (typeof input === 'string') { - inputAsBuffer = utils.base64ToBytes(input); + inputAsBuffer = base64ToBytes(input); } else if (input.constructor === Uint8Array) { inputAsBuffer = input; } @@ -283,7 +284,7 @@ export class Transaction implements TransactionStorageStructure { if (txn.genesisHash === undefined) throw Error('genesis hash must be specified and in a base64 string.'); - txn.genesisHash = utils.base64ToBytes(txn.genesisHash as string); + txn.genesisHash = base64ToBytes(txn.genesisHash as string); if ( txn.amount !== undefined && @@ -1259,7 +1260,7 @@ export class Transaction implements TransactionStorageStructure { (forPrinting.reKeyTo as Address).publicKey ); if (typeof forPrinting.genesisHash !== 'string') - forPrinting.genesisHash = utils.bytesToBase64(forPrinting.genesisHash); // TODO: double check this + forPrinting.genesisHash = bytesToBase64(forPrinting.genesisHash); // TODO: double check this return forPrinting; } diff --git a/tests/5.Transaction.js b/tests/5.Transaction.js index aa38f634f..0ef87ff5d 100644 --- a/tests/5.Transaction.js +++ b/tests/5.Transaction.js @@ -3,7 +3,6 @@ const assert = require('assert'); const algosdk = require('../src/index'); const { translateBoxReferences } = require('../src/boxStorage'); const group = require('../src/group'); -const { base64ToBytes } = require('../src/utils/utils'); describe('Sign', () => { /* eslint-disable no-console */ @@ -508,7 +507,7 @@ describe('Sign', () => { assetName: 'testcoin', assetURL: 'testURL', assetMetadataHash: new Uint8Array( - base64ToBytes('ZkFDUE80blJnTzU1ajFuZEFLM1c2U2djNEFQa2N5Rmg=') + algosdk.base64ToBytes('ZkFDUE80blJnTzU1ajFuZEFLM1c2U2djNEFQa2N5Rmg=') ), assetManager: address, assetReserve: address, @@ -1039,7 +1038,7 @@ describe('Sign', () => { const assetName = 'testcoin'; const assetURL = 'testURL'; const assetMetadataHash = new Uint8Array( - base64ToBytes('dGVzdGhhc2gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=') + algosdk.base64ToBytes('dGVzdGhhc2gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=') ); const genesisID = ''; const firstRound = 322575; @@ -1111,7 +1110,7 @@ describe('Sign', () => { const assetName = 'testcoin'; const assetURL = 'testURL'; const assetMetadataHash = new Uint8Array( - base64ToBytes('dGVzdGhhc2gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=') + algosdk.base64ToBytes('dGVzdGhhc2gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=') ); const genesisID = ''; const firstRound = 322575; @@ -1183,7 +1182,7 @@ describe('Sign', () => { const assetName = 'testcoin'; const assetURL = 'testURL'; const assetMetadataHash = new Uint8Array( - base64ToBytes('dGVzdGhhc2gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=') + algosdk.base64ToBytes('dGVzdGhhc2gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=') ); const genesisID = ''; const firstRound = 322575; diff --git a/tests/cucumber/steps/steps.js b/tests/cucumber/steps/steps.js index 6f5542332..b38569ad7 100644 --- a/tests/cucumber/steps/steps.js +++ b/tests/cucumber/steps/steps.js @@ -4268,7 +4268,7 @@ module.exports = function getSteps(options) { // Check the random int against the witness const witnessHash = genericHash(witnessResult).slice(0, 8); - const witness = algosdk.bytesToBigInt(witnessHash); + const witness = algosdk.bytesToBigInt(Uint8Array.from(witnessHash)); const quotient = witness % BigInt(methodArg); assert.strictEqual(quotient, randomIntResult); } @@ -4288,7 +4288,7 @@ module.exports = function getSteps(options) { // Check the random character against the witness const witnessHash = genericHash(witnessResult).slice(0, 8); - const witness = algosdk.bytesToBigInt(witnessHash); + const witness = algosdk.bytesToBigInt(Uint8Array.from(witnessHash)); const quotient = witness % BigInt(methodArg.length); assert.strictEqual( methodArg[quotient], From f12c1f6863218790c8ca6380223e7be78328a547 Mon Sep 17 00:00:00 2001 From: algochoi <86622919+algochoi@users.noreply.github.com> Date: Tue, 18 Jul 2023 09:44:41 -0400 Subject: [PATCH 20/34] Remove some generated types from stable release --- src/client/v2/algod/models/types.ts | 223 ---------------------------- 1 file changed, 223 deletions(-) diff --git a/src/client/v2/algod/models/types.ts b/src/client/v2/algod/models/types.ts index cc4ed5c83..020d176ca 100644 --- a/src/client/v2/algod/models/types.ts +++ b/src/client/v2/algod/models/types.ts @@ -3354,11 +3354,6 @@ export class SimulateRequest extends BaseModel { */ public allowMoreLogging?: boolean; - /** - * An object that configures simulation execution trace. - */ - public execTraceConfig?: SimulateTraceConfig; - /** * Applies extra opcode budget during simulation for each transaction group. */ @@ -3370,34 +3365,29 @@ export class SimulateRequest extends BaseModel { * @param allowEmptySignatures - Allow transactions without signatures to be simulated as if they had correct * signatures. * @param allowMoreLogging - Lifts limits on log opcode usage during simulation. - * @param execTraceConfig - An object that configures simulation execution trace. * @param extraOpcodeBudget - Applies extra opcode budget during simulation for each transaction group. */ constructor({ txnGroups, allowEmptySignatures, allowMoreLogging, - execTraceConfig, extraOpcodeBudget, }: { txnGroups: SimulateRequestTransactionGroup[]; allowEmptySignatures?: boolean; allowMoreLogging?: boolean; - execTraceConfig?: SimulateTraceConfig; extraOpcodeBudget?: number | bigint; }) { super(); this.txnGroups = txnGroups; this.allowEmptySignatures = allowEmptySignatures; this.allowMoreLogging = allowMoreLogging; - this.execTraceConfig = execTraceConfig; this.extraOpcodeBudget = extraOpcodeBudget; this.attribute_map = { txnGroups: 'txn-groups', allowEmptySignatures: 'allow-empty-signatures', allowMoreLogging: 'allow-more-logging', - execTraceConfig: 'exec-trace-config', extraOpcodeBudget: 'extra-opcode-budget', }; } @@ -3415,10 +3405,6 @@ export class SimulateRequest extends BaseModel { ), allowEmptySignatures: data['allow-empty-signatures'], allowMoreLogging: data['allow-more-logging'], - execTraceConfig: - typeof data['exec-trace-config'] !== 'undefined' - ? SimulateTraceConfig.from_obj_for_encoding(data['exec-trace-config']) - : undefined, extraOpcodeBudget: data['extra-opcode-budget'], }); /* eslint-enable dot-notation */ @@ -3490,11 +3476,6 @@ export class SimulateResponse extends BaseModel { */ public evalOverrides?: SimulationEvalOverrides; - /** - * An object that configures simulation execution trace. - */ - public execTraceConfig?: SimulateTraceConfig; - /** * Creates a new `SimulateResponse` object. * @param lastRound - The round immediately preceding this simulation. State changes through this @@ -3504,34 +3485,29 @@ export class SimulateResponse extends BaseModel { * @param evalOverrides - The set of parameters and limits override during simulation. If this set of * parameters is present, then evaluation parameters may differ from standard * evaluation in certain ways. - * @param execTraceConfig - An object that configures simulation execution trace. */ constructor({ lastRound, txnGroups, version, evalOverrides, - execTraceConfig, }: { lastRound: number | bigint; txnGroups: SimulateTransactionGroupResult[]; version: number | bigint; evalOverrides?: SimulationEvalOverrides; - execTraceConfig?: SimulateTraceConfig; }) { super(); this.lastRound = lastRound; this.txnGroups = txnGroups; this.version = version; this.evalOverrides = evalOverrides; - this.execTraceConfig = execTraceConfig; this.attribute_map = { lastRound: 'last-round', txnGroups: 'txn-groups', version: 'version', evalOverrides: 'eval-overrides', - execTraceConfig: 'exec-trace-config', }; } @@ -3560,42 +3536,6 @@ export class SimulateResponse extends BaseModel { data['eval-overrides'] ) : undefined, - execTraceConfig: - typeof data['exec-trace-config'] !== 'undefined' - ? SimulateTraceConfig.from_obj_for_encoding(data['exec-trace-config']) - : undefined, - }); - /* eslint-enable dot-notation */ - } -} - -/** - * An object that configures simulation execution trace. - */ -export class SimulateTraceConfig extends BaseModel { - /** - * A boolean option for opting in execution trace features simulation endpoint. - */ - public enable?: boolean; - - /** - * Creates a new `SimulateTraceConfig` object. - * @param enable - A boolean option for opting in execution trace features simulation endpoint. - */ - constructor({ enable }: { enable?: boolean }) { - super(); - this.enable = enable; - - this.attribute_map = { - enable: 'enable', - }; - } - - // eslint-disable-next-line camelcase - static from_obj_for_encoding(data: Record): SimulateTraceConfig { - /* eslint-disable dot-notation */ - return new SimulateTraceConfig({ - enable: data['enable'], }); /* eslint-enable dot-notation */ } @@ -3713,12 +3653,6 @@ export class SimulateTransactionResult extends BaseModel { */ public appBudgetConsumed?: number | bigint; - /** - * The execution trace of calling an app or a logic sig, containing the inner app - * call trace in a recursive way. - */ - public execTrace?: SimulationTransactionExecTrace; - /** * Budget used during execution of a logic sig transaction. */ @@ -3730,31 +3664,25 @@ export class SimulateTransactionResult extends BaseModel { * includes confirmation details like the round and reward details. * @param appBudgetConsumed - Budget used during execution of an app call transaction. This value includes * budged used by inner app calls spawned by this transaction. - * @param execTrace - The execution trace of calling an app or a logic sig, containing the inner app - * call trace in a recursive way. * @param logicSigBudgetConsumed - Budget used during execution of a logic sig transaction. */ constructor({ txnResult, appBudgetConsumed, - execTrace, logicSigBudgetConsumed, }: { txnResult: PendingTransactionResponse; appBudgetConsumed?: number | bigint; - execTrace?: SimulationTransactionExecTrace; logicSigBudgetConsumed?: number | bigint; }) { super(); this.txnResult = txnResult; this.appBudgetConsumed = appBudgetConsumed; - this.execTrace = execTrace; this.logicSigBudgetConsumed = logicSigBudgetConsumed; this.attribute_map = { txnResult: 'txn-result', appBudgetConsumed: 'app-budget-consumed', - execTrace: 'exec-trace', logicSigBudgetConsumed: 'logic-sig-budget-consumed', }; } @@ -3773,12 +3701,6 @@ export class SimulateTransactionResult extends BaseModel { data['txn-result'] ), appBudgetConsumed: data['app-budget-consumed'], - execTrace: - typeof data['exec-trace'] !== 'undefined' - ? SimulationTransactionExecTrace.from_obj_for_encoding( - data['exec-trace'] - ) - : undefined, logicSigBudgetConsumed: data['logic-sig-budget-consumed'], }); /* eslint-enable dot-notation */ @@ -3860,151 +3782,6 @@ export class SimulationEvalOverrides extends BaseModel { } } -/** - * The set of trace information and effect from evaluating a single opcode. - */ -export class SimulationOpcodeTraceUnit extends BaseModel { - /** - * The program counter of the current opcode being evaluated. - */ - public pc: number | bigint; - - /** - * The indexes of the traces for inner transactions spawned by this opcode, if any. - */ - public spawnedInners?: (number | bigint)[]; - - /** - * Creates a new `SimulationOpcodeTraceUnit` object. - * @param pc - The program counter of the current opcode being evaluated. - * @param spawnedInners - The indexes of the traces for inner transactions spawned by this opcode, if any. - */ - constructor({ - pc, - spawnedInners, - }: { - pc: number | bigint; - spawnedInners?: (number | bigint)[]; - }) { - super(); - this.pc = pc; - this.spawnedInners = spawnedInners; - - this.attribute_map = { - pc: 'pc', - spawnedInners: 'spawned-inners', - }; - } - - // eslint-disable-next-line camelcase - static from_obj_for_encoding( - data: Record - ): SimulationOpcodeTraceUnit { - /* eslint-disable dot-notation */ - if (typeof data['pc'] === 'undefined') - throw new Error(`Response is missing required field 'pc': ${data}`); - return new SimulationOpcodeTraceUnit({ - pc: data['pc'], - spawnedInners: data['spawned-inners'], - }); - /* eslint-enable dot-notation */ - } -} - -/** - * The execution trace of calling an app or a logic sig, containing the inner app - * call trace in a recursive way. - */ -export class SimulationTransactionExecTrace extends BaseModel { - /** - * Program trace that contains a trace of opcode effects in an approval program. - */ - public approvalProgramTrace?: SimulationOpcodeTraceUnit[]; - - /** - * Program trace that contains a trace of opcode effects in a clear state program. - */ - public clearStateProgramTrace?: SimulationOpcodeTraceUnit[]; - - /** - * An array of SimulationTransactionExecTrace representing the execution trace of - * any inner transactions executed. - */ - public innerTrace?: SimulationTransactionExecTrace[]; - - /** - * Program trace that contains a trace of opcode effects in a logic sig. - */ - public logicSigTrace?: SimulationOpcodeTraceUnit[]; - - /** - * Creates a new `SimulationTransactionExecTrace` object. - * @param approvalProgramTrace - Program trace that contains a trace of opcode effects in an approval program. - * @param clearStateProgramTrace - Program trace that contains a trace of opcode effects in a clear state program. - * @param innerTrace - An array of SimulationTransactionExecTrace representing the execution trace of - * any inner transactions executed. - * @param logicSigTrace - Program trace that contains a trace of opcode effects in a logic sig. - */ - constructor({ - approvalProgramTrace, - clearStateProgramTrace, - innerTrace, - logicSigTrace, - }: { - approvalProgramTrace?: SimulationOpcodeTraceUnit[]; - clearStateProgramTrace?: SimulationOpcodeTraceUnit[]; - innerTrace?: SimulationTransactionExecTrace[]; - logicSigTrace?: SimulationOpcodeTraceUnit[]; - }) { - super(); - this.approvalProgramTrace = approvalProgramTrace; - this.clearStateProgramTrace = clearStateProgramTrace; - this.innerTrace = innerTrace; - this.logicSigTrace = logicSigTrace; - - this.attribute_map = { - approvalProgramTrace: 'approval-program-trace', - clearStateProgramTrace: 'clear-state-program-trace', - innerTrace: 'inner-trace', - logicSigTrace: 'logic-sig-trace', - }; - } - - // eslint-disable-next-line camelcase - static from_obj_for_encoding( - data: Record - ): SimulationTransactionExecTrace { - /* eslint-disable dot-notation */ - return new SimulationTransactionExecTrace({ - approvalProgramTrace: - typeof data['approval-program-trace'] !== 'undefined' - ? data['approval-program-trace'].map( - SimulationOpcodeTraceUnit.from_obj_for_encoding - ) - : undefined, - clearStateProgramTrace: - typeof data['clear-state-program-trace'] !== 'undefined' - ? data['clear-state-program-trace'].map( - SimulationOpcodeTraceUnit.from_obj_for_encoding - ) - : undefined, - innerTrace: - typeof data['inner-trace'] !== 'undefined' - ? data['inner-trace'].map( - SimulationTransactionExecTrace.from_obj_for_encoding - ) - : undefined, - logicSigTrace: - typeof data['logic-sig-trace'] !== 'undefined' - ? data['logic-sig-trace'].map( - SimulationOpcodeTraceUnit.from_obj_for_encoding - ) - : undefined, - }); - /* eslint-enable dot-notation */ - } -} - /** * Represents a state proof and its corresponding message */ From f765cd9b39a5ddaaaa5a14bd9a4df656e082736d Mon Sep 17 00:00:00 2001 From: algochoi <86622919+algochoi@users.noreply.github.com> Date: Tue, 18 Jul 2023 23:13:52 -0400 Subject: [PATCH 21/34] Fix node tests --- src/client/kmd.ts | 42 ++++++---- src/encoding/binarydata.ts | 21 ++++- src/main.ts | 1 + tests/cucumber/browser/test.js | 4 +- tests/cucumber/steps/index.js | 20 ++--- tests/cucumber/steps/steps.js | 138 +++++++++++++++------------------ 6 files changed, 120 insertions(+), 106 deletions(-) diff --git a/src/client/kmd.ts b/src/client/kmd.ts index 4c832b259..5d0120b60 100644 --- a/src/client/kmd.ts +++ b/src/client/kmd.ts @@ -1,7 +1,7 @@ -import { Buffer } from 'buffer'; -import ServiceClient from './v2/serviceClient'; +import { base64ToBytes, bytesToBase64 } from '../encoding/binarydata'; import * as txn from '../transaction'; import { CustomTokenHeader, KMDTokenHeader } from './urlTokenBaseHTTPClient'; +import ServiceClient from './v2/serviceClient'; export default class Kmd extends ServiceClient { constructor( @@ -50,7 +50,7 @@ export default class Kmd extends ServiceClient { wallet_name: walletName, wallet_driver_name: walletDriverName, wallet_password: walletPassword, - master_derivation_key: Buffer.from(walletMDK).toString('base64'), + master_derivation_key: bytesToBase64(walletMDK), }; const res = await this.c.post('/v1/wallet', req); return res.body; @@ -157,10 +157,7 @@ export default class Kmd extends ServiceClient { }; const res = await this.c.post('/v1/master-key/export', req); return { - master_derivation_key: Buffer.from( - res.body.master_derivation_key, - 'base64' - ), + master_derivation_key: base64ToBytes(res.body.master_derivation_key), }; } @@ -174,7 +171,7 @@ export default class Kmd extends ServiceClient { async importKey(walletHandle: string, secretKey: Uint8Array) { const req = { wallet_handle_token: walletHandle, - private_key: Buffer.from(secretKey).toString('base64'), + private_key: bytesToBase64(secretKey), }; const res = await this.c.post('/v1/key/import', req); return res.body; @@ -195,7 +192,7 @@ export default class Kmd extends ServiceClient { wallet_password: walletPassword, }; const res = await this.c.post('/v1/key/export', req); - return { private_key: Buffer.from(res.body.private_key, 'base64') }; + return { private_key: base64ToBytes(res.body.private_key) }; } /** @@ -266,12 +263,12 @@ export default class Kmd extends ServiceClient { const req = { wallet_handle_token: walletHandle, wallet_password: walletPassword, - transaction: Buffer.from(tx.toByte()).toString('base64'), + transaction: bytesToBase64(tx.toByte()), }; const res = await this.c.post('/v1/transaction/sign', req); if (res.status === 200) { - return Buffer.from(res.body.signed_transaction, 'base64'); + return base64ToBytes(res.body.signed_transaction); } return res.body; } @@ -293,17 +290,24 @@ export default class Kmd extends ServiceClient { publicKey: Uint8Array | string ) { const tx = txn.instantiateTxnIfNeeded(transaction); + let pk: Uint8Array; + + if (typeof publicKey === 'string') { + pk = new TextEncoder().encode(publicKey); + } else { + pk = publicKey; + } const req = { wallet_handle_token: walletHandle, wallet_password: walletPassword, - transaction: Buffer.from(tx.toByte()).toString('base64'), - public_key: Buffer.from(publicKey).toString('base64'), + transaction: bytesToBase64(tx.toByte()), + public_key: bytesToBase64(pk), }; const res = await this.c.post('/v1/transaction/sign', req); if (res.status === 200) { - return Buffer.from(res.body.signed_transaction, 'base64'); + return base64ToBytes(res.body.signed_transaction); } return res.body; } @@ -389,10 +393,16 @@ export default class Kmd extends ServiceClient { partial: string ) { const tx = txn.instantiateTxnIfNeeded(transaction); + let pubkey: Uint8Array; + if (typeof pk === 'string') { + pubkey = new TextEncoder().encode(pk); + } else { + pubkey = pk; + } const req = { wallet_handle_token: walletHandle, - transaction: Buffer.from(tx.toByte()).toString('base64'), - public_key: Buffer.from(pk).toString('base64'), + transaction: bytesToBase64(tx.toByte()), + public_key: bytesToBase64(pubkey), partial_multisig: partial, wallet_password: pw, }; diff --git a/src/encoding/binarydata.ts b/src/encoding/binarydata.ts index 549a5b9ac..95ccddf72 100644 --- a/src/encoding/binarydata.ts +++ b/src/encoding/binarydata.ts @@ -42,7 +42,7 @@ export function bytesToBase64(byteArray: Uint8Array): string { } /** - * Convert a a Uint8Array to a hex string for Node.js and browser environments. + * Convert a Uint8Array to a hex string for Node.js and browser environments. * @returns A hex string */ export function bytesToHex(byteArray: Uint8Array): string { @@ -53,3 +53,22 @@ export function bytesToHex(byteArray: Uint8Array): string { .map((i) => i.toString(16).padStart(2, '0')) .join(''); } + +/** + * Convert a hex string to Uint8Array for Node.js and browser environments. + * @returns A Uint8Array + */ +export function hexToBytes(hexString: string): Uint8Array { + if (isNode()) { + return Buffer.from(hexString, 'hex'); + } + let hex = hexString; + if (hexString.length % 2 !== 0) { + hex = hexString.padStart(1, '0'); + } + const byteArray = new Uint8Array(hex.length / 2); + for (let i = 0, j = 0; i < hex.length / 2; i++, j += 2) { + byteArray[i] = parseInt(hex.slice(j, j + 2), 16); + } + return byteArray; +} diff --git a/src/main.ts b/src/main.ts index 94ab758d3..fc0e1d3c4 100644 --- a/src/main.ts +++ b/src/main.ts @@ -144,6 +144,7 @@ export { base64ToString, bytesToBase64, bytesToHex, + hexToBytes, } from './encoding/binarydata'; export { encodeUint64, decodeUint64 } from './encoding/uint64'; export { default as generateAccount } from './account'; diff --git a/tests/cucumber/browser/test.js b/tests/cucumber/browser/test.js index e276efcb3..3ed521c53 100644 --- a/tests/cucumber/browser/test.js +++ b/tests/cucumber/browser/test.js @@ -1,11 +1,9 @@ /* eslint-env browser */ -const { Buffer } = require('buffer'); const assert = require('assert'); const sha512 = require('js-sha512'); const nacl = require('tweetnacl'); window.assert = assert; -window.Buffer = Buffer; window.keyPairFromSecretKey = function keyPairFromSecretKey(sk) { return nacl.sign.keyPair.fromSecretKey(sk); @@ -25,7 +23,7 @@ window.loadResource = async function loadResource(resource) { throw new Error(`Failed to load resource (${res.status}): ${resource}`); } - return Buffer.from(await res.arrayBuffer()); + return res.arrayBuffer(); }; window.steps = { diff --git a/tests/cucumber/steps/index.js b/tests/cucumber/steps/index.js index abb07339c..2afa99e3d 100644 --- a/tests/cucumber/steps/index.js +++ b/tests/cucumber/steps/index.js @@ -1,6 +1,5 @@ /* eslint-disable no-console,global-require,no-loop-func,func-names */ const assert = require('assert'); -const { Buffer } = require('buffer'); const path = require('path'); const fs = require('fs'); const { @@ -14,6 +13,7 @@ const { } = require('cucumber'); const express = require('express'); const ServerMock = require('mock-http-server'); +const algosdk = require('../../../src/index'); const getSteps = require('./steps'); const cucumberPath = path.dirname(__dirname); @@ -275,7 +275,7 @@ function setupMockServerForResponses(fileName, jsonDirectory, mockServer) { } if (fileName.endsWith('base64')) { headers = { 'content-type': 'application/msgpack', ...corsHeaders }; - body = Buffer.from(resultString, 'base64'); + body = algosdk.base64ToBytes(resultString); } let statusCode = 200; if (fileName.indexOf('Error') > -1) { @@ -451,11 +451,11 @@ for (const name of Object.keys(steps.given)) { if (fileName.endsWith('base64')) { format = 'msgp'; } - if (Buffer.isBuffer(body1)) { - body1 = body1.toString('base64'); + if (ArrayBuffer.isView(body1)) { + body1 = algosdk.bytesToBase64(body1); } - if (Buffer.isBuffer(body2)) { - body2 = body2.toString('base64'); + if (ArrayBuffer.isView(body2)) { + body2 = algosdk.bytesToBase64(body2); } return fn.call(this, body2 || body1, format); }); @@ -478,11 +478,11 @@ for (const name of Object.keys(steps.given)) { if (fileName.endsWith('base64')) { format = 'msgp'; } - if (Buffer.isBuffer(body1)) { - body1 = body1.toString('base64'); + if (ArrayBuffer.isView(body1)) { + body1 = algosdk.bytesToBase64(body1); } - if (Buffer.isBuffer(body2)) { - body2 = body2.toString('base64'); + if (ArrayBuffer.isView(body2)) { + body2 = algosdk.bytesToBase64(body2); } return fn.call(this, body2 || body1, status, format); }); diff --git a/tests/cucumber/steps/steps.js b/tests/cucumber/steps/steps.js index b38569ad7..48f760c07 100644 --- a/tests/cucumber/steps/steps.js +++ b/tests/cucumber/steps/steps.js @@ -1,11 +1,11 @@ /* eslint-disable func-names,radix */ -const { Buffer } = require('buffer'); const assert = require('assert'); const fs = require('fs'); const path = require('path'); const algosdk = require('../../../src/index'); const nacl = require('../../../src/nacl/naclWrappers'); +const { concatArrays } = require('../../../src/utils/utils'); const maindir = path.dirname(path.dirname(path.dirname(__dirname))); @@ -127,13 +127,13 @@ module.exports = function getSteps(options) { function processAppArgs(subArg) { switch (subArg[0]) { case 'str': - return makeUint8Array(Buffer.from(subArg[1])); + return makeUint8Array(new TextEncoder().encode(subArg[1])); case 'int': return makeUint8Array(algosdk.encodeUint64(parseInt(subArg[1], 10))); case 'addr': return algosdk.decodeAddress(subArg[1]).publicKey; case 'b64': - return makeUint8Array(Buffer.from(subArg[1], 'base64')); + return makeUint8Array(algosdk.base64ToBytes(subArg[1])); default: throw Error(`did not recognize app arg of type ${subArg[0]}`); } @@ -248,7 +248,7 @@ module.exports = function getSteps(options) { this.gen = gen; } if (note !== 'none') { - this.note = makeUint8Array(Buffer.from(note, 'base64')); + this.note = makeUint8Array(algosdk.base64ToBytes(note)); } } ); @@ -293,9 +293,9 @@ module.exports = function getSteps(options) { const addrs = []; for (let i = 0; i < this.msig.addrs.length; i++) { addrs.push( - Buffer.from( + algosdk.bytesToBase64( algosdk.decodeAddress(this.msig.addrs[i]).publicKey - ).toString('base64') + ) ); } await this.kcl.importMultisig( @@ -320,17 +320,14 @@ module.exports = function getSteps(options) { Then( 'the signed transaction should equal the golden {string}', function (golden) { - assert.deepStrictEqual( - Buffer.from(golden, 'base64'), - Buffer.from(this.stx) - ); + assert.deepStrictEqual(algosdk.base64ToBytes(golden), this.stx); } ); Then( 'the signed transaction should equal the kmd signed transaction', function () { - assert.deepStrictEqual(Buffer.from(this.stx), Buffer.from(this.stxKmd)); + assert.deepStrictEqual(this.stx, this.stxKmd); } ); @@ -344,10 +341,7 @@ module.exports = function getSteps(options) { Then( 'the multisig transaction should equal the golden {string}', function (golden) { - assert.deepStrictEqual( - Buffer.from(golden, 'base64'), - Buffer.from(this.stx) - ); + assert.deepStrictEqual(algosdk.base64ToBytes(golden), this.stx); } ); @@ -361,10 +355,7 @@ module.exports = function getSteps(options) { ); const s = algosdk.decodeObj(this.stx); const m = algosdk.encodeObj(s.msig); - assert.deepStrictEqual( - Buffer.from(m), - Buffer.from(this.stxKmd, 'base64') - ); + assert.deepStrictEqual(m, algosdk.base64ToBytes(this.stxKmd)); } ); @@ -441,8 +432,8 @@ module.exports = function getSteps(options) { ); exp = exp.private_key; assert.deepStrictEqual( - Buffer.from(exp).toString('base64'), - Buffer.from(this.sk).toString('base64') + algosdk.bytesToBase64(exp), + algosdk.bytesToBase64(this.sk) ); return this.kcl.deleteKey(this.handle, this.wallet_pswd, this.pk); } @@ -464,7 +455,7 @@ module.exports = function getSteps(options) { to: this.accounts[1], amount: parseInt(amt), suggestedParams: result, - note: makeUint8Array(Buffer.from(note, 'base64')), + note: makeUint8Array(algosdk.base64ToBytes(note)), }); return this.txn; } @@ -484,7 +475,7 @@ module.exports = function getSteps(options) { lastRound: result.lastRound, genesisHash: result.genesisHash, genesisID: result.genesisID, - note: makeUint8Array(Buffer.from(note, 'base64')), + note: makeUint8Array(algosdk.base64ToBytes(note)), amount: parseInt(amt), }; return this.txn; @@ -510,7 +501,7 @@ module.exports = function getSteps(options) { lastRound: result.lastRound, genesisHash: result.genesisHash, genesisID: result.genesisID, - note: makeUint8Array(Buffer.from(note, 'base64')), + note: makeUint8Array(algosdk.base64ToBytes(note)), amount: parseInt(amt), }; return this.txn; @@ -521,9 +512,9 @@ module.exports = function getSteps(options) { const addrs = []; for (let i = 0; i < this.msig.addrs.length; i++) { addrs.push( - Buffer.from( + algosdk.bytesToBase64( algosdk.decodeAddress(this.msig.addrs[i]).publicKey - ).toString('base64') + ) ); } return this.kcl.importMultisig( @@ -577,7 +568,7 @@ module.exports = function getSteps(options) { Then('the multisig should equal the exported multisig', function () { for (let i = 0; i < this.msigExp.length; i++) { assert.deepStrictEqual( - algosdk.encodeAddress(Buffer.from(this.msigExp[i], 'base64')), + algosdk.encodeAddress(algosdk.base64ToBytes(this.msigExp[i])), this.msig.addrs[i] ); } @@ -677,7 +668,7 @@ module.exports = function getSteps(options) { }); Given('encoded multisig transaction {string}', function (encTxn) { - this.mtx = Buffer.from(encTxn, 'base64'); + this.mtx = algosdk.base64ToBytes(encTxn); this.stx = algosdk.decodeObj(this.mtx); }); @@ -719,7 +710,7 @@ module.exports = function getSteps(options) { this.mtxs = []; const mtxs = encTxns.split(' '); for (let i = 0; i < mtxs.length; i++) { - this.mtxs.push(Buffer.from(mtxs[i], 'base64')); + this.mtxs.push(algosdk.base64ToBytes(mtxs[i])); } }); @@ -912,15 +903,14 @@ module.exports = function getSteps(options) { 'default V2 key registration transaction {string}', async function (type) { const voteKey = makeUint8Array( - Buffer.from('9mr13Ri8rFepxN3ghIUrZNui6LqqM5hEzB45Rri5lkU=', 'base64') + algosdk.base64ToBytes('9mr13Ri8rFepxN3ghIUrZNui6LqqM5hEzB45Rri5lkU=') ); const selectionKey = makeUint8Array( - Buffer.from('dx717L3uOIIb/jr9OIyls1l5Ei00NFgRa380w7TnPr4=', 'base64') + algosdk.base64ToBytes('dx717L3uOIIb/jr9OIyls1l5Ei00NFgRa380w7TnPr4=') ); const stateProofKey = makeUint8Array( - Buffer.from( - 'mYR0GVEObMTSNdsKM6RwYywHYPqVDqg3E4JFzxZOreH9NU8B+tKzUanyY8AQ144hETgSMX7fXWwjBdHz6AWk9w==', - 'base64' + algosdk.base64ToBytes( + 'mYR0GVEObMTSNdsKM6RwYywHYPqVDqg3E4JFzxZOreH9NU8B+tKzUanyY8AQ144hETgSMX7fXWwjBdHz6AWk9w==' ) ); @@ -1036,7 +1026,7 @@ module.exports = function getSteps(options) { unitname: unitName, assetname: assetName, url: assetURL, - metadatahash: Buffer.from(metadataHash).toString('base64'), + metadatahash: algosdk.bytesToBase64(metadataHash), managerkey: manager, reserveaddr: reserve, freezeaddr: freeze, @@ -1102,7 +1092,7 @@ module.exports = function getSteps(options) { unitname: unitName, assetname: assetName, url: assetURL, - metadatahash: Buffer.from(metadataHash).toString('base64'), + metadatahash: algosdk.bytesToBase64(metadataHash), managerkey: manager, reserveaddr: reserve, freezeaddr: freeze, @@ -1477,7 +1467,7 @@ module.exports = function getSteps(options) { expectedMockResponse = expectedBody; if (format === 'msgp') { expectedMockResponse = new Uint8Array( - Buffer.from(expectedMockResponse, 'base64') + algosdk.base64ToBytes(expectedMockResponse) ); } } @@ -1504,7 +1494,7 @@ module.exports = function getSteps(options) { expectedMockResponse = expectedBody; if (format === 'msgp') { expectedMockResponse = new Uint8Array( - Buffer.from(expectedMockResponse, 'base64') + algosdk.base64ToBytes(expectedMockResponse) ); } } @@ -1945,9 +1935,9 @@ module.exports = function getSteps(options) { Then( 'the parsed Get Block response should have rewards pool {string}', (rewardsPoolAddress) => { - const rewardsPoolB64String = Buffer.from( + const rewardsPoolB64String = algosdk.bytesToBase64( anyBlockResponse.block.rwd - ).toString('base64'); + ); assert.strictEqual(rewardsPoolAddress, rewardsPoolB64String); } ); @@ -2849,7 +2839,7 @@ module.exports = function getSteps(options) { async (program) => { const data = await loadResource(program); const decodedResult = makeUint8Array( - Buffer.from(compileResponse.result, 'base64') + algosdk.base64ToBytes(compileResponse.result) ); assert.deepStrictEqual(makeUint8Array(data), decodedResult); } @@ -2860,7 +2850,7 @@ module.exports = function getSteps(options) { /// ///////////////////////////////// Given('base64 encoded data to sign {string}', function (data) { - this.data = Buffer.from(data, 'base64'); + this.data = algosdk.base64ToBytes(data); }); Given('program hash {string}', function (contractAddress) { @@ -2868,13 +2858,13 @@ module.exports = function getSteps(options) { }); Given('base64 encoded program {string}', function (programEncoded) { - const program = Buffer.from(programEncoded, 'base64'); + const program = algosdk.base64ToBytes(programEncoded); const lsig = new algosdk.LogicSig(program); this.contractAddress = lsig.address(); }); Given('base64 encoded private key {string}', function (keyEncoded) { - const seed = Buffer.from(keyEncoded, 'base64'); + const seed = algosdk.base64ToBytes(keyEncoded); const keys = keyPairFromSeed(seed); this.sk = keys.secretKey; }); @@ -2884,7 +2874,7 @@ module.exports = function getSteps(options) { }); Then('the signature should be equal to {string}', function (expectedEncoded) { - const expected = makeUint8Array(Buffer.from(expectedEncoded, 'base64')); + const expected = makeUint8Array(algosdk.base64ToBytes(expectedEncoded)); assert.deepStrictEqual(this.sig, expected); }); @@ -2932,10 +2922,10 @@ module.exports = function getSteps(options) { "I get the account address for the current application and see that it matches the app id's hash", async function () { const appID = this.currentApplicationIndex; - const toSign = Buffer.concat([ - Buffer.from('appID'), - algosdk.encodeUint64(appID), - ]); + const toSign = concatArrays( + new TextEncoder().encode('appID'), + algosdk.encodeUint64(appID) + ); const expected = algosdk.encodeAddress( makeUint8Array(genericHash(toSign)) ); @@ -3048,7 +3038,7 @@ module.exports = function getSteps(options) { try { const compiledResponse = await client.compile(data).do(); const compiledProgram = makeUint8Array( - Buffer.from(compiledResponse.result, 'base64') + algosdk.base64ToBytes(compiledResponse.result) ); return compiledProgram; } catch (err) { @@ -3270,7 +3260,7 @@ module.exports = function getSteps(options) { Then( 'the base64 encoded signed transaction should equal {string}', function (base64golden) { - const actualBase64 = Buffer.from(this.stx).toString('base64'); + const actualBase64 = algosdk.bytesToBase64(this.stx); assert.strictEqual(actualBase64, base64golden); } ); @@ -3680,7 +3670,7 @@ module.exports = function getSteps(options) { function (expectedSelectorHex) { const actualSelector = this.method.getSelector(); const expectedSelector = makeUint8Array( - Buffer.from(expectedSelectorHex, 'hex') + algosdk.hexToBytes(expectedSelectorHex) ); assert.deepStrictEqual(actualSelector, expectedSelector); } @@ -3830,7 +3820,7 @@ module.exports = function getSteps(options) { const appID = this.appIDs[parseInt(b64Arg[1], 10)]; args.push(algosdk.encodeUint64(appID)); } else { - args.push(makeUint8Array(Buffer.from(b64Arg, 'base64'))); + args.push(makeUint8Array(algosdk.base64ToBytes(b64Arg))); } } this.encodedMethodArguments.push(...args); @@ -4063,7 +4053,7 @@ module.exports = function getSteps(options) { Given( 'I add a nonced method call with the transient account, the current application, suggested params, on complete {string}, current transaction signer, current method arguments.', async function (onComplete) { - const nonce = makeUint8Array(Buffer.from(this.nonce)); + const nonce = makeUint8Array(new TextEncoder().encode(this.nonce)); await addMethodCallToComposer.call( this, this.transientAccount.addr, @@ -4154,10 +4144,10 @@ module.exports = function getSteps(options) { function (commaSeparatedB64SignedTxns) { const expectedSignedTxns = commaSeparatedB64SignedTxns .split(',') - .map((b64SignedTxn) => Buffer.from(b64SignedTxn, 'base64')); + .map((b64SignedTxn) => algosdk.base64ToBytes(b64SignedTxn)); const actualSignedTxns = this.composerSignedTransactions.map( - (signedTxn) => Buffer.from(signedTxn) + (signedTxn) => signedTxn ); assert.deepStrictEqual( [...actualSignedTxns], @@ -4191,20 +4181,19 @@ module.exports = function getSteps(options) { for (let i = 0; i < methodResults.length; i++) { const actualResult = methodResults[i]; const { method } = actualResult; - const expectedReturnValue = Buffer.from( - b64ExpectedReturnValues[i], - 'base64' + const expectedReturnValue = algosdk.base64ToBytes( + b64ExpectedReturnValues[i] ); if (actualResult.decodeError) { throw actualResult.decodeError; } assert.deepStrictEqual( - Buffer.from(actualResult.rawReturnValue), + actualResult.rawReturnValue, expectedReturnValue, - `Actual return value for method at index ${i} does not match expected. Actual: ${Buffer.from( - actualResult.rawReturnValue - ).toString('base64')}` + `Actual return value for method at index ${i} does not match expected. Actual: ${actualResult.rawReturnValue.toString( + 'base64' + )}` ); const returnType = method.returns.type; @@ -4292,7 +4281,7 @@ module.exports = function getSteps(options) { const quotient = witness % BigInt(methodArg.length); assert.strictEqual( methodArg[quotient], - Buffer.from(makeUint8Array([randomResult])).toString('utf-8') + new TextDecoder().decode(makeUint8Array([randomResult])) ); } ); @@ -4361,7 +4350,7 @@ module.exports = function getSteps(options) { ); const actualResult = this.composerExecuteResponse.methodResults[index]; let spin = abiType.decode(actualResult.rawReturnValue)[0]; - spin = Buffer.from(spin).toString('utf-8'); + spin = new TextDecoder().decode(Uint8Array.from(spin)); assert.ok(spin.match(regexString)); } @@ -4471,11 +4460,8 @@ module.exports = function getSteps(options) { const actualName = resp.name; const actualValue = resp.value; - assert.deepStrictEqual(Buffer.from(boxKey), Buffer.from(actualName)); - assert.deepStrictEqual( - Buffer.from(boxValue, 'base64'), - Buffer.from(actualValue) - ); + assert.deepStrictEqual(boxKey, actualName); + assert.deepStrictEqual(algosdk.base64ToBytes(boxValue), actualValue); } catch (err) { if (errString !== '') { assert.deepStrictEqual( @@ -4497,7 +4483,7 @@ module.exports = function getSteps(options) { const splitBoxB64Names = boxB64Names.split(':'); const boxNames = []; splitBoxB64Names.forEach((subArg) => { - boxNames.push(makeUint8Array(Buffer.from(subArg, 'base64'))); + boxNames.push(makeUint8Array(algosdk.base64ToBytes(subArg))); }); return boxNames; } @@ -4514,9 +4500,9 @@ module.exports = function getSteps(options) { assert.deepStrictEqual(boxes.length, resp.boxes.length); const actualBoxes = new Set( - resp.boxes.map((b) => Buffer.from(b.name, 'base64')) + resp.boxes.map((b) => algosdk.base64ToBytes(b.name)) ); - const expectedBoxes = new Set(boxes.map(Buffer.from)); + const expectedBoxes = new Set(boxes); assert.deepStrictEqual(expectedBoxes, actualBoxes); } ); @@ -4563,9 +4549,9 @@ module.exports = function getSteps(options) { assert.deepStrictEqual(boxes.length, resp.boxes.length); const actualBoxes = new Set( - resp.boxes.map((b) => Buffer.from(b.name, 'base64')) + resp.boxes.map((b) => algosdk.base64ToBytes(b.name)) ); - const expectedBoxes = new Set(boxes.map(Buffer.from)); + const expectedBoxes = new Set(boxes); assert.deepStrictEqual(expectedBoxes, actualBoxes); } ); @@ -4665,7 +4651,7 @@ module.exports = function getSteps(options) { 'a base64 encoded program bytes for heuristic sanity check {string}', async function (programByteStr) { this.seeminglyProgram = new Uint8Array( - Buffer.from(programByteStr, 'base64') + algosdk.base64ToBytes(programByteStr) ); } ); From 3ddfaec468ac1a7bf463fe44838294e36fee792c Mon Sep 17 00:00:00 2001 From: algochoi <86622919+algochoi@users.noreply.github.com> Date: Wed, 19 Jul 2023 01:12:11 -0400 Subject: [PATCH 22/34] Try loadResource in browser --- tests/cucumber/browser/test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/cucumber/browser/test.js b/tests/cucumber/browser/test.js index 3ed521c53..577009bed 100644 --- a/tests/cucumber/browser/test.js +++ b/tests/cucumber/browser/test.js @@ -23,7 +23,7 @@ window.loadResource = async function loadResource(resource) { throw new Error(`Failed to load resource (${res.status}): ${resource}`); } - return res.arrayBuffer(); + return Uint8Array.from(await res.arrayBuffer()); }; window.steps = { From 84f73c381113a21d08d7965f806c4be0837dcb66 Mon Sep 17 00:00:00 2001 From: algochoi <86622919+algochoi@users.noreply.github.com> Date: Wed, 19 Jul 2023 11:27:05 -0400 Subject: [PATCH 23/34] Update buffer usage in client files --- src/client/client.ts | 7 +++---- src/client/kmd.ts | 21 +++++++------------ src/client/urlTokenBaseHTTPClient.ts | 3 +-- src/client/v2/algod/compile.ts | 6 +++--- src/client/v2/algod/disassemble.ts | 6 +++--- src/client/v2/algod/dryrun.ts | 13 ++++-------- .../v2/algod/getApplicationBoxByName.ts | 8 +++---- src/client/v2/algod/sendRawTransaction.ts | 11 +++------- src/client/v2/algod/simulateTransaction.ts | 3 +-- src/client/v2/basemodel.ts | 6 +++--- .../v2/indexer/lookupAccountTransactions.ts | 8 +++---- .../lookupApplicationBoxByIDandName.ts | 8 +++---- src/encoding/binarydata.ts | 11 ++++++++++ 13 files changed, 51 insertions(+), 60 deletions(-) diff --git a/src/client/client.ts b/src/client/client.ts index 6a2036632..21db84ec4 100644 --- a/src/client/client.ts +++ b/src/client/client.ts @@ -1,4 +1,3 @@ -import { Buffer } from 'buffer'; import * as utils from '../utils/utils'; import { BaseHTTPClient, @@ -151,10 +150,10 @@ export default class HTTPClient { return new Uint8Array(0); // empty Uint8Array } if (requestHeaders['content-type'] === 'application/json') { - return new Uint8Array(Buffer.from(JSON.stringify(data))); + return new TextEncoder().encode(JSON.stringify(data)); } if (typeof data === 'string') { - return new Uint8Array(Buffer.from(data)); + return new TextEncoder().encode(data); } if (data instanceof Uint8Array) { return data; @@ -179,7 +178,7 @@ export default class HTTPClient { let text; if (format !== 'application/msgpack') { - text = (body && Buffer.from(body).toString()) || ''; + text = (body && new TextDecoder().decode(body)) || ''; } if (parseBody && format === 'application/json') { diff --git a/src/client/kmd.ts b/src/client/kmd.ts index 5d0120b60..69c3e08eb 100644 --- a/src/client/kmd.ts +++ b/src/client/kmd.ts @@ -1,4 +1,8 @@ -import { base64ToBytes, bytesToBase64 } from '../encoding/binarydata'; +import { + base64ToBytes, + bytesToBase64, + coerceToBytes, +} from '../encoding/binarydata'; import * as txn from '../transaction'; import { CustomTokenHeader, KMDTokenHeader } from './urlTokenBaseHTTPClient'; import ServiceClient from './v2/serviceClient'; @@ -290,13 +294,7 @@ export default class Kmd extends ServiceClient { publicKey: Uint8Array | string ) { const tx = txn.instantiateTxnIfNeeded(transaction); - let pk: Uint8Array; - - if (typeof publicKey === 'string') { - pk = new TextEncoder().encode(publicKey); - } else { - pk = publicKey; - } + const pk = coerceToBytes(publicKey); const req = { wallet_handle_token: walletHandle, @@ -393,12 +391,7 @@ export default class Kmd extends ServiceClient { partial: string ) { const tx = txn.instantiateTxnIfNeeded(transaction); - let pubkey: Uint8Array; - if (typeof pk === 'string') { - pubkey = new TextEncoder().encode(pk); - } else { - pubkey = pk; - } + const pubkey = coerceToBytes(pk); const req = { wallet_handle_token: walletHandle, transaction: bytesToBase64(tx.toByte()), diff --git a/src/client/urlTokenBaseHTTPClient.ts b/src/client/urlTokenBaseHTTPClient.ts index f91c254c6..bbacd9255 100644 --- a/src/client/urlTokenBaseHTTPClient.ts +++ b/src/client/urlTokenBaseHTTPClient.ts @@ -1,4 +1,3 @@ -import { Buffer } from 'buffer'; import { fetch, Response, Headers } from 'cross-fetch'; import { BaseHTTPClient, @@ -118,7 +117,7 @@ export class URLTokenBaseHTTPClient implements BaseHTTPClient { try { body = new Uint8Array(await res.arrayBuffer()); const decoded: Record = JSON.parse( - Buffer.from(body).toString() + new TextDecoder().decode(body) ); if (decoded.message) { bodyErrorMessage = decoded.message; diff --git a/src/client/v2/algod/compile.ts b/src/client/v2/algod/compile.ts index db8769c0e..f69ce59f9 100644 --- a/src/client/v2/algod/compile.ts +++ b/src/client/v2/algod/compile.ts @@ -1,6 +1,6 @@ -import { Buffer } from 'buffer'; -import JSONRequest from '../jsonrequest'; +import { coerceToBytes } from '../../../encoding/binarydata'; import HTTPClient from '../../client'; +import JSONRequest from '../jsonrequest'; /** * Sets the default header (if not previously set) @@ -42,7 +42,7 @@ export default class Compile extends JSONRequest { const txHeaders = setHeaders(headers); const res = await this.c.post( this.path(), - Buffer.from(this.source), + coerceToBytes(this.source), txHeaders, this.query ); diff --git a/src/client/v2/algod/disassemble.ts b/src/client/v2/algod/disassemble.ts index 552e8c622..291a04040 100644 --- a/src/client/v2/algod/disassemble.ts +++ b/src/client/v2/algod/disassemble.ts @@ -1,6 +1,6 @@ -import { Buffer } from 'buffer'; -import JSONRequest from '../jsonrequest'; +import { coerceToBytes } from '../../../encoding/binarydata'; import HTTPClient from '../../client'; +import JSONRequest from '../jsonrequest'; /** * Sets the default header (if not previously set) @@ -37,7 +37,7 @@ export default class Disassemble extends JSONRequest { const txHeaders = setHeaders(headers); const res = await this.c.post( this.path(), - Buffer.from(this.source), + coerceToBytes(this.source), txHeaders, this.query ); diff --git a/src/client/v2/algod/dryrun.ts b/src/client/v2/algod/dryrun.ts index 98b2fb463..23089d977 100644 --- a/src/client/v2/algod/dryrun.ts +++ b/src/client/v2/algod/dryrun.ts @@ -1,9 +1,8 @@ -import { Buffer } from 'buffer'; -import JSONRequest from '../jsonrequest'; -import HTTPClient from '../../client'; -import * as modelsv2 from './models/types'; import * as encoding from '../../../encoding/encoding'; +import HTTPClient from '../../client'; +import JSONRequest from '../jsonrequest'; import { setHeaders } from './compile'; +import * as modelsv2 from './models/types'; export default class Dryrun extends JSONRequest { private blob: Uint8Array; @@ -24,11 +23,7 @@ export default class Dryrun extends JSONRequest { */ async do(headers = {}) { const txHeaders = setHeaders(headers); - const res = await this.c.post( - this.path(), - Buffer.from(this.blob), - txHeaders - ); + const res = await this.c.post(this.path(), this.blob, txHeaders); return res.body; } } diff --git a/src/client/v2/algod/getApplicationBoxByName.ts b/src/client/v2/algod/getApplicationBoxByName.ts index b58aaf845..246c3ba0d 100644 --- a/src/client/v2/algod/getApplicationBoxByName.ts +++ b/src/client/v2/algod/getApplicationBoxByName.ts @@ -1,7 +1,7 @@ -import { Buffer } from 'buffer'; -import JSONRequest from '../jsonrequest'; -import HTTPClient from '../../client'; +import { bytesToBase64 } from '../../../encoding/binarydata'; import IntDecoding from '../../../types/intDecoding'; +import HTTPClient from '../../client'; +import JSONRequest from '../jsonrequest'; import { Box } from './models/types'; /** @@ -32,7 +32,7 @@ export default class GetApplicationBoxByName extends JSONRequest< super(c, intDecoding); this.index = index; // Encode name in base64 format and append the encoding prefix. - const encodedName = Buffer.from(name).toString('base64'); + const encodedName = bytesToBase64(name); this.query.name = encodeURI(`b64:${encodedName}`); } diff --git a/src/client/v2/algod/sendRawTransaction.ts b/src/client/v2/algod/sendRawTransaction.ts index 8977c1c5f..4c1629393 100644 --- a/src/client/v2/algod/sendRawTransaction.ts +++ b/src/client/v2/algod/sendRawTransaction.ts @@ -1,7 +1,6 @@ -import { Buffer } from 'buffer'; -import JSONRequest from '../jsonrequest'; -import HTTPClient from '../../client'; import { concatArrays } from '../../../utils/utils'; +import HTTPClient from '../../client'; +import JSONRequest from '../jsonrequest'; /** * Sets the default header (if not previously set) for sending a raw @@ -50,11 +49,7 @@ export default class SendRawTransaction extends JSONRequest { async do(headers = {}) { const txHeaders = setSendTransactionHeaders(headers); - const res = await this.c.post( - this.path(), - Buffer.from(this.txnBytesToPost), - txHeaders - ); + const res = await this.c.post(this.path(), this.txnBytesToPost, txHeaders); return res.body; } } diff --git a/src/client/v2/algod/simulateTransaction.ts b/src/client/v2/algod/simulateTransaction.ts index c6dad54f5..471b40855 100644 --- a/src/client/v2/algod/simulateTransaction.ts +++ b/src/client/v2/algod/simulateTransaction.ts @@ -1,4 +1,3 @@ -import { Buffer } from 'buffer'; import * as encoding from '../../../encoding/encoding'; import HTTPClient from '../../client'; import JSONRequest from '../jsonrequest'; @@ -42,7 +41,7 @@ export default class SimulateRawTransactions extends JSONRequest< const txHeaders = setSimulateTransactionsHeaders(headers); const res = await this.c.post( this.path(), - Buffer.from(this.requestBytes), + this.requestBytes, txHeaders, this.query, false diff --git a/src/client/v2/basemodel.ts b/src/client/v2/basemodel.ts index 39fa52e57..b882b18cb 100644 --- a/src/client/v2/basemodel.ts +++ b/src/client/v2/basemodel.ts @@ -1,9 +1,9 @@ -import { Buffer } from 'buffer'; - /** * Base class for models */ +import { bytesToBase64 } from '../../encoding/binarydata'; + /* eslint-disable no-underscore-dangle,camelcase */ function _is_primitive(val: any): val is string | boolean | number | bigint { /* eslint-enable no-underscore-dangle,camelcase */ @@ -29,7 +29,7 @@ function _get_obj_for_encoding(val: any, binary: boolean): any { let targetPropValue: any; if (val instanceof Uint8Array) { - targetPropValue = binary ? val : Buffer.from(val).toString('base64'); + targetPropValue = binary ? val : bytesToBase64(val); } else if (typeof val.get_obj_for_encoding === 'function') { targetPropValue = val.get_obj_for_encoding(binary); } else if (Array.isArray(val)) { diff --git a/src/client/v2/indexer/lookupAccountTransactions.ts b/src/client/v2/indexer/lookupAccountTransactions.ts index 12f48fa7e..961e06368 100644 --- a/src/client/v2/indexer/lookupAccountTransactions.ts +++ b/src/client/v2/indexer/lookupAccountTransactions.ts @@ -1,7 +1,7 @@ -import { Buffer } from 'buffer'; -import JSONRequest from '../jsonrequest'; -import HTTPClient from '../../client'; +import { bytesToBase64 } from '../../../encoding/binarydata'; import IntDecoding from '../../../types/intDecoding'; +import HTTPClient from '../../client'; +import JSONRequest from '../jsonrequest'; /** * Accept base64 string or Uint8Array and output base64 string @@ -12,7 +12,7 @@ export function base64StringFunnel(data: Uint8Array | string) { if (typeof data === 'string') { return data; } - return Buffer.from(data).toString('base64'); + return bytesToBase64(data); } export default class LookupAccountTransactions extends JSONRequest { diff --git a/src/client/v2/indexer/lookupApplicationBoxByIDandName.ts b/src/client/v2/indexer/lookupApplicationBoxByIDandName.ts index 94bc80175..fdc1c25ee 100644 --- a/src/client/v2/indexer/lookupApplicationBoxByIDandName.ts +++ b/src/client/v2/indexer/lookupApplicationBoxByIDandName.ts @@ -1,7 +1,7 @@ -import { Buffer } from 'buffer'; -import JSONRequest from '../jsonrequest'; -import HTTPClient from '../../client'; +import { bytesToBase64 } from '../../../encoding/binarydata'; import IntDecoding from '../../../types/intDecoding'; +import HTTPClient from '../../client'; +import JSONRequest from '../jsonrequest'; import { Box } from './models/types'; export default class LookupApplicationBoxByIDandName extends JSONRequest< @@ -33,7 +33,7 @@ export default class LookupApplicationBoxByIDandName extends JSONRequest< super(c, intDecoding); this.index = index; // Encode query in base64 format and append the encoding prefix. - const encodedName = Buffer.from(boxName).toString('base64'); + const encodedName = bytesToBase64(boxName); this.query.name = encodeURI(`b64:${encodedName}`); } diff --git a/src/encoding/binarydata.ts b/src/encoding/binarydata.ts index 95ccddf72..2cac230d8 100644 --- a/src/encoding/binarydata.ts +++ b/src/encoding/binarydata.ts @@ -41,6 +41,17 @@ export function bytesToBase64(byteArray: Uint8Array): string { return btoa(binString); } +/** + * Returns a Uint8Array given an input string or Uint8Array. + * @returns A base64 string + */ +export function coerceToBytes(input: Uint8Array | string): Uint8Array { + if (typeof input === 'string') { + return new TextEncoder().encode(input); + } + return input; +} + /** * Convert a Uint8Array to a hex string for Node.js and browser environments. * @returns A hex string From 3fc520005d694ec4b14f98acfe156a33003e2216 Mon Sep 17 00:00:00 2001 From: algochoi <86622919+algochoi@users.noreply.github.com> Date: Wed, 19 Jul 2023 12:48:45 -0400 Subject: [PATCH 24/34] Revert cucumber browser loadResource --- tests/cucumber/browser/test.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/cucumber/browser/test.js b/tests/cucumber/browser/test.js index 577009bed..e276efcb3 100644 --- a/tests/cucumber/browser/test.js +++ b/tests/cucumber/browser/test.js @@ -1,9 +1,11 @@ /* eslint-env browser */ +const { Buffer } = require('buffer'); const assert = require('assert'); const sha512 = require('js-sha512'); const nacl = require('tweetnacl'); window.assert = assert; +window.Buffer = Buffer; window.keyPairFromSecretKey = function keyPairFromSecretKey(sk) { return nacl.sign.keyPair.fromSecretKey(sk); @@ -23,7 +25,7 @@ window.loadResource = async function loadResource(resource) { throw new Error(`Failed to load resource (${res.status}): ${resource}`); } - return Uint8Array.from(await res.arrayBuffer()); + return Buffer.from(await res.arrayBuffer()); }; window.steps = { From a84101eaa5a4a83674957616c8c6c7a5785a5b00 Mon Sep 17 00:00:00 2001 From: algochoi <86622919+algochoi@users.noreply.github.com> Date: Wed, 19 Jul 2023 18:31:08 -0400 Subject: [PATCH 25/34] Fix browser tests --- src/composer.ts | 17 +- src/encoding/binarydata.ts | 25 ++- tests/6.Multisig.ts | 305 ++++++++++++++-------------------- tests/7.AlgoSDK.js | 164 +++++++----------- tests/8.LogicSig.ts | 156 +++++++---------- tests/cucumber/steps/steps.js | 26 ++- 6 files changed, 298 insertions(+), 395 deletions(-) diff --git a/src/composer.ts b/src/composer.ts index b75cbefa4..3f3e2eb23 100644 --- a/src/composer.ts +++ b/src/composer.ts @@ -16,7 +16,6 @@ import { SimulateRequestTransactionGroup, SimulateResponse, } from './client/v2/algod/models/types'; -import { base64ToBytes } from './encoding/binarydata'; import * as encoding from './encoding/encoding'; import { assignGroupID } from './group'; import { makeApplicationCallTxnFromObject } from './makeTxn'; @@ -782,17 +781,25 @@ export class AtomicTransactionComposer { try { returnedResult.txInfo = pendingInfo; if (method.returns.type !== 'void') { - const logs: string[] = pendingInfo.logs || []; + const logs = pendingInfo.logs || []; if (logs.length === 0) { - throw new Error('App call transaction did not log a return value'); + throw new Error( + `App call transaction did not log a return value ${JSON.stringify( + pendingInfo + )}` + ); } - const lastLog = base64ToBytes(logs[logs.length - 1]); + const lastLog: Uint8Array = logs[logs.length - 1]; if ( lastLog.byteLength < 4 || !arrayEqual(lastLog.slice(0, 4), RETURN_PREFIX) ) { - throw new Error('App call transaction did not log a return value'); + throw new Error( + `App call transaction did not log a return value ${JSON.stringify( + pendingInfo + )}` + ); } returnedResult.rawReturnValue = new Uint8Array(lastLog.slice(4)); diff --git a/src/encoding/binarydata.ts b/src/encoding/binarydata.ts index 2cac230d8..382c5302a 100644 --- a/src/encoding/binarydata.ts +++ b/src/encoding/binarydata.ts @@ -9,9 +9,18 @@ export function base64ToBytes(base64String: string): Uint8Array { if (isNode()) { return new Uint8Array(Buffer.from(base64String, 'base64')); } + if (typeof base64String !== 'string') { + throw new Error(`base64String is not string: ${base64String}`); + } /* eslint-env browser */ - const binString = atob(base64String); - return Uint8Array.from(binString, (m) => m.codePointAt(0)); + try { + const binString = atob(base64String); + return Uint8Array.from(binString, (m) => m.codePointAt(0)); + } catch (err) { + throw new Error( + `base64String is invalid: ${base64String}; ${typeof base64String};` + ); + } } /** @@ -35,10 +44,14 @@ export function bytesToBase64(byteArray: Uint8Array): string { return Buffer.from(byteArray).toString('base64'); } /* eslint-env browser */ - const binString = Array.from(byteArray, (x) => String.fromCodePoint(x)).join( - '' - ); - return btoa(binString); + try { + const binString = Array.from(byteArray, (x) => + String.fromCodePoint(x) + ).join(''); + return btoa(binString); + } catch (err) { + throw new Error(`byteArray is invalid: ${byteArray}; ${typeof byteArray}`); + } } /** diff --git a/tests/6.Multisig.ts b/tests/6.Multisig.ts index a2577e98a..3c0696e1e 100644 --- a/tests/6.Multisig.ts +++ b/tests/6.Multisig.ts @@ -1,5 +1,4 @@ /* eslint-env mocha */ -import { Buffer } from 'buffer'; import assert from 'assert'; import algosdk from '../src/index'; import { @@ -56,7 +55,7 @@ describe('Multisig Functionality', () => { from: sampleMultisigAddr, to: 'PNWOET7LLOWMBMLE4KOCELCX6X3D3Q4H2Q4QJASYIEOF7YIPPQBG3YQ5YI', amount: 1000, - note: new Uint8Array(Buffer.from('RSYiABhShvs=', 'base64')), + note: algosdk.base64ToBytes('RSYiABhShvs='), closeRemainderTo: 'IDUTJEUIEVSMXTU4LGTJWZ2UE2E6TIODUKU6UW3FU3UKIQQ77RLUBBBFLA', suggestedParams: { @@ -79,11 +78,10 @@ describe('Multisig Functionality', () => { 'MANN3ESOHQVHFZBAGD6UK6XFVWEFZQJPWO5SQ2J5LZRCF5E2VVQQ'; assert.strictEqual(txID, expectedTxID); - const expectedSignedTxn = Buffer.from( - 'gqRtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RAuLAFE0oma0skOoAmOzEwfPuLYpEWl4LINtsiLrUqWQkDxh4WHb29//YCpj4MFbiSgD2jKYt0XKRD86zKCF4RDYGicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxgaJwa8Qg5/D4TQaBHfnzHI2HixFV9GcdUaGFwgCQhmf0SVhwaKGjdGhyAqF2AaN0eG6Lo2FtdM0D6KVjbG9zZcQgQOk0koglZMvOnFmmm2dUJonpocOiqepbZabopEIf/FejZmVlzQPoomZ2zfMVo2dlbqxkZXZuZXQtdjM4LjCiZ2jEIP6zbDkQFDkAw9pVQsoYNrAP0vgZWRJXzSP2BC+YyDadomx2zfb9pG5vdGXECEUmIgAYUob7o3JjdsQge2ziT+tbrMCxZOKcIixX9fY9w4fUOQSCWEEcX+EPfAKjc25kxCCNkrSJkAFzoE36Q1mjZmpq/OosQqBd2cH3PuulR4A36aR0eXBlo3BheQ==', - 'base64' + const expectedSignedTxn = algosdk.base64ToBytes( + 'gqRtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RAuLAFE0oma0skOoAmOzEwfPuLYpEWl4LINtsiLrUqWQkDxh4WHb29//YCpj4MFbiSgD2jKYt0XKRD86zKCF4RDYGicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxgaJwa8Qg5/D4TQaBHfnzHI2HixFV9GcdUaGFwgCQhmf0SVhwaKGjdGhyAqF2AaN0eG6Lo2FtdM0D6KVjbG9zZcQgQOk0koglZMvOnFmmm2dUJonpocOiqepbZabopEIf/FejZmVlzQPoomZ2zfMVo2dlbqxkZXZuZXQtdjM4LjCiZ2jEIP6zbDkQFDkAw9pVQsoYNrAP0vgZWRJXzSP2BC+YyDadomx2zfb9pG5vdGXECEUmIgAYUob7o3JjdsQge2ziT+tbrMCxZOKcIixX9fY9w4fUOQSCWEEcX+EPfAKjc25kxCCNkrSJkAFzoE36Q1mjZmpq/OosQqBd2cH3PuulR4A36aR0eXBlo3BheQ==' ); - assert.deepStrictEqual(Buffer.from(blob), expectedSignedTxn); + assert.deepStrictEqual(blob, expectedSignedTxn); }); it('should correctly handle a different sender', () => { @@ -91,7 +89,7 @@ describe('Multisig Functionality', () => { from: 'EHGMQCXBIFBE364DEKWQVVNCTCTVCGQL3BR2Q5I7CFTRXWIVTF4SYA3GHU', to: 'PNWOET7LLOWMBMLE4KOCELCX6X3D3Q4H2Q4QJASYIEOF7YIPPQBG3YQ5YI', amount: 1000, - note: new Uint8Array(Buffer.from('RSYiABhShvs=', 'base64')), + note: algosdk.base64ToBytes('RSYiABhShvs='), closeRemainderTo: 'IDUTJEUIEVSMXTU4LGTJWZ2UE2E6TIODUKU6UW3FU3UKIQQ77RLUBBBFLA', suggestedParams: { @@ -114,19 +112,17 @@ describe('Multisig Functionality', () => { 'YQOXQNNO56WXQSU3IDUM2C4J7IZI6WMSCMKN5UCP5ZK6GWA6BXKQ'; assert.strictEqual(txID, expectedTxID); - const expectedSignedTxn = Buffer.from( - 'g6Rtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RAWLcyn6nB68yo/PUHXB21wyTy+PhHgMQNOIXPTGB96faZP2xqpQ8IFlIR2LPotlX68ylK8MCl82SUfMR4FYyzAIGicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxgaJwa8Qg5/D4TQaBHfnzHI2HixFV9GcdUaGFwgCQhmf0SVhwaKGjdGhyAqF2AaRzZ25yxCCNkrSJkAFzoE36Q1mjZmpq/OosQqBd2cH3PuulR4A36aN0eG6Lo2FtdM0D6KVjbG9zZcQgQOk0koglZMvOnFmmm2dUJonpocOiqepbZabopEIf/FejZmVlzQPoomZ2zfMVo2dlbqxkZXZuZXQtdjM4LjCiZ2jEIP6zbDkQFDkAw9pVQsoYNrAP0vgZWRJXzSP2BC+YyDadomx2zfb9pG5vdGXECEUmIgAYUob7o3JjdsQge2ziT+tbrMCxZOKcIixX9fY9w4fUOQSCWEEcX+EPfAKjc25kxCAhzMgK4UFCTfuDIq0K1aKYp1EaC9hjqHUfEWcb2RWZeaR0eXBlo3BheQ==', - 'base64' + const expectedSignedTxn = algosdk.base64ToBytes( + 'g6Rtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RAWLcyn6nB68yo/PUHXB21wyTy+PhHgMQNOIXPTGB96faZP2xqpQ8IFlIR2LPotlX68ylK8MCl82SUfMR4FYyzAIGicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxgaJwa8Qg5/D4TQaBHfnzHI2HixFV9GcdUaGFwgCQhmf0SVhwaKGjdGhyAqF2AaRzZ25yxCCNkrSJkAFzoE36Q1mjZmpq/OosQqBd2cH3PuulR4A36aN0eG6Lo2FtdM0D6KVjbG9zZcQgQOk0koglZMvOnFmmm2dUJonpocOiqepbZabopEIf/FejZmVlzQPoomZ2zfMVo2dlbqxkZXZuZXQtdjM4LjCiZ2jEIP6zbDkQFDkAw9pVQsoYNrAP0vgZWRJXzSP2BC+YyDadomx2zfb9pG5vdGXECEUmIgAYUob7o3JjdsQge2ziT+tbrMCxZOKcIixX9fY9w4fUOQSCWEEcX+EPfAKjc25kxCAhzMgK4UFCTfuDIq0K1aKYp1EaC9hjqHUfEWcb2RWZeaR0eXBlo3BheQ==' ); - assert.deepStrictEqual(Buffer.from(blob), expectedSignedTxn); + assert.deepStrictEqual(blob, expectedSignedTxn); }); }); describe('appendSignMultisigTransaction', () => { it('should match golden main repo result', () => { - const oneSigTxn = Buffer.from( - 'gqRtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RAuLAFE0oma0skOoAmOzEwfPuLYpEWl4LINtsiLrUqWQkDxh4WHb29//YCpj4MFbiSgD2jKYt0XKRD86zKCF4RDYGicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxgaJwa8Qg5/D4TQaBHfnzHI2HixFV9GcdUaGFwgCQhmf0SVhwaKGjdGhyAqF2AaN0eG6Lo2FtdM0D6KVjbG9zZcQgQOk0koglZMvOnFmmm2dUJonpocOiqepbZabopEIf/FejZmVlzQPoomZ2zfMVo2dlbqxkZXZuZXQtdjM4LjCiZ2jEIP6zbDkQFDkAw9pVQsoYNrAP0vgZWRJXzSP2BC+YyDadomx2zfb9pG5vdGXECEUmIgAYUob7o3JjdsQge2ziT+tbrMCxZOKcIixX9fY9w4fUOQSCWEEcX+EPfAKjc25kxCCNkrSJkAFzoE36Q1mjZmpq/OosQqBd2cH3PuulR4A36aR0eXBlo3BheQ==', - 'base64' + const oneSigTxn = algosdk.base64ToBytes( + 'gqRtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RAuLAFE0oma0skOoAmOzEwfPuLYpEWl4LINtsiLrUqWQkDxh4WHb29//YCpj4MFbiSgD2jKYt0XKRD86zKCF4RDYGicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxgaJwa8Qg5/D4TQaBHfnzHI2HixFV9GcdUaGFwgCQhmf0SVhwaKGjdGhyAqF2AaN0eG6Lo2FtdM0D6KVjbG9zZcQgQOk0koglZMvOnFmmm2dUJonpocOiqepbZabopEIf/FejZmVlzQPoomZ2zfMVo2dlbqxkZXZuZXQtdjM4LjCiZ2jEIP6zbDkQFDkAw9pVQsoYNrAP0vgZWRJXzSP2BC+YyDadomx2zfb9pG5vdGXECEUmIgAYUob7o3JjdsQge2ziT+tbrMCxZOKcIixX9fY9w4fUOQSCWEEcX+EPfAKjc25kxCCNkrSJkAFzoE36Q1mjZmpq/OosQqBd2cH3PuulR4A36aR0eXBlo3BheQ==' ); const { txID, blob } = algosdk.appendSignMultisigTransaction( @@ -139,17 +135,15 @@ describe('Multisig Functionality', () => { 'MANN3ESOHQVHFZBAGD6UK6XFVWEFZQJPWO5SQ2J5LZRCF5E2VVQQ'; assert.strictEqual(txID, expectedTxID); - const expectedBlob = Buffer.from( - 'gqRtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RAuLAFE0oma0skOoAmOzEwfPuLYpEWl4LINtsiLrUqWQkDxh4WHb29//YCpj4MFbiSgD2jKYt0XKRD86zKCF4RDYKicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxoXPEQBAhuyRjsOrnHp3s/xI+iMKiL7QPsh8iJZ22YOJJP0aFUwedMr+a6wfdBXk1OefyrAN1wqJ9rq6O+DrWV1fH0ASBonBrxCDn8PhNBoEd+fMcjYeLEVX0Zx1RoYXCAJCGZ/RJWHBooaN0aHICoXYBo3R4boujYW10zQPopWNsb3NlxCBA6TSSiCVky86cWaabZ1Qmiemhw6Kp6ltlpuikQh/8V6NmZWXNA+iiZnbN8xWjZ2VurGRldm5ldC12MzguMKJnaMQg/rNsORAUOQDD2lVCyhg2sA/S+BlZElfNI/YEL5jINp2ibHbN9v2kbm90ZcQIRSYiABhShvujcmN2xCB7bOJP61uswLFk4pwiLFf19j3Dh9Q5BIJYQRxf4Q98AqNzbmTEII2StImQAXOgTfpDWaNmamr86ixCoF3Zwfc+66VHgDfppHR5cGWjcGF5', - 'base64' + const expectedBlob = algosdk.base64ToBytes( + 'gqRtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RAuLAFE0oma0skOoAmOzEwfPuLYpEWl4LINtsiLrUqWQkDxh4WHb29//YCpj4MFbiSgD2jKYt0XKRD86zKCF4RDYKicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxoXPEQBAhuyRjsOrnHp3s/xI+iMKiL7QPsh8iJZ22YOJJP0aFUwedMr+a6wfdBXk1OefyrAN1wqJ9rq6O+DrWV1fH0ASBonBrxCDn8PhNBoEd+fMcjYeLEVX0Zx1RoYXCAJCGZ/RJWHBooaN0aHICoXYBo3R4boujYW10zQPopWNsb3NlxCBA6TSSiCVky86cWaabZ1Qmiemhw6Kp6ltlpuikQh/8V6NmZWXNA+iiZnbN8xWjZ2VurGRldm5ldC12MzguMKJnaMQg/rNsORAUOQDD2lVCyhg2sA/S+BlZElfNI/YEL5jINp2ibHbN9v2kbm90ZcQIRSYiABhShvujcmN2xCB7bOJP61uswLFk4pwiLFf19j3Dh9Q5BIJYQRxf4Q98AqNzbmTEII2StImQAXOgTfpDWaNmamr86ixCoF3Zwfc+66VHgDfppHR5cGWjcGF5' ); - assert.deepStrictEqual(Buffer.from(blob), expectedBlob); + assert.deepStrictEqual(blob, expectedBlob); }); it('should correctly handle a different sender', () => { - const oneSigTxn = Buffer.from( - 'g6Rtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RAWLcyn6nB68yo/PUHXB21wyTy+PhHgMQNOIXPTGB96faZP2xqpQ8IFlIR2LPotlX68ylK8MCl82SUfMR4FYyzAIGicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxgaJwa8Qg5/D4TQaBHfnzHI2HixFV9GcdUaGFwgCQhmf0SVhwaKGjdGhyAqF2AaRzZ25yxCCNkrSJkAFzoE36Q1mjZmpq/OosQqBd2cH3PuulR4A36aN0eG6Lo2FtdM0D6KVjbG9zZcQgQOk0koglZMvOnFmmm2dUJonpocOiqepbZabopEIf/FejZmVlzQPoomZ2zfMVo2dlbqxkZXZuZXQtdjM4LjCiZ2jEIP6zbDkQFDkAw9pVQsoYNrAP0vgZWRJXzSP2BC+YyDadomx2zfb9pG5vdGXECEUmIgAYUob7o3JjdsQge2ziT+tbrMCxZOKcIixX9fY9w4fUOQSCWEEcX+EPfAKjc25kxCAhzMgK4UFCTfuDIq0K1aKYp1EaC9hjqHUfEWcb2RWZeaR0eXBlo3BheQ==', - 'base64' + const oneSigTxn = algosdk.base64ToBytes( + 'g6Rtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RAWLcyn6nB68yo/PUHXB21wyTy+PhHgMQNOIXPTGB96faZP2xqpQ8IFlIR2LPotlX68ylK8MCl82SUfMR4FYyzAIGicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxgaJwa8Qg5/D4TQaBHfnzHI2HixFV9GcdUaGFwgCQhmf0SVhwaKGjdGhyAqF2AaRzZ25yxCCNkrSJkAFzoE36Q1mjZmpq/OosQqBd2cH3PuulR4A36aN0eG6Lo2FtdM0D6KVjbG9zZcQgQOk0koglZMvOnFmmm2dUJonpocOiqepbZabopEIf/FejZmVlzQPoomZ2zfMVo2dlbqxkZXZuZXQtdjM4LjCiZ2jEIP6zbDkQFDkAw9pVQsoYNrAP0vgZWRJXzSP2BC+YyDadomx2zfb9pG5vdGXECEUmIgAYUob7o3JjdsQge2ziT+tbrMCxZOKcIixX9fY9w4fUOQSCWEEcX+EPfAKjc25kxCAhzMgK4UFCTfuDIq0K1aKYp1EaC9hjqHUfEWcb2RWZeaR0eXBlo3BheQ==' ); const { txID, blob } = algosdk.appendSignMultisigTransaction( @@ -162,19 +156,17 @@ describe('Multisig Functionality', () => { 'YQOXQNNO56WXQSU3IDUM2C4J7IZI6WMSCMKN5UCP5ZK6GWA6BXKQ'; assert.strictEqual(txID, expectedTxID); - const expectedBlob = Buffer.from( - 'g6Rtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RAWLcyn6nB68yo/PUHXB21wyTy+PhHgMQNOIXPTGB96faZP2xqpQ8IFlIR2LPotlX68ylK8MCl82SUfMR4FYyzAIKicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxoXPEQPuH2WlM2x1tflA6LGMhKXBiuO7dsRzjXYPgcfjvDth9ZsCazyOKHqQmtYjD+pXLM8fJbrRhoUGTkyLxINiT9wCBonBrxCDn8PhNBoEd+fMcjYeLEVX0Zx1RoYXCAJCGZ/RJWHBooaN0aHICoXYBpHNnbnLEII2StImQAXOgTfpDWaNmamr86ixCoF3Zwfc+66VHgDfpo3R4boujYW10zQPopWNsb3NlxCBA6TSSiCVky86cWaabZ1Qmiemhw6Kp6ltlpuikQh/8V6NmZWXNA+iiZnbN8xWjZ2VurGRldm5ldC12MzguMKJnaMQg/rNsORAUOQDD2lVCyhg2sA/S+BlZElfNI/YEL5jINp2ibHbN9v2kbm90ZcQIRSYiABhShvujcmN2xCB7bOJP61uswLFk4pwiLFf19j3Dh9Q5BIJYQRxf4Q98AqNzbmTEICHMyArhQUJN+4MirQrVopinURoL2GOodR8RZxvZFZl5pHR5cGWjcGF5', - 'base64' + const expectedBlob = algosdk.base64ToBytes( + 'g6Rtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RAWLcyn6nB68yo/PUHXB21wyTy+PhHgMQNOIXPTGB96faZP2xqpQ8IFlIR2LPotlX68ylK8MCl82SUfMR4FYyzAIKicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxoXPEQPuH2WlM2x1tflA6LGMhKXBiuO7dsRzjXYPgcfjvDth9ZsCazyOKHqQmtYjD+pXLM8fJbrRhoUGTkyLxINiT9wCBonBrxCDn8PhNBoEd+fMcjYeLEVX0Zx1RoYXCAJCGZ/RJWHBooaN0aHICoXYBpHNnbnLEII2StImQAXOgTfpDWaNmamr86ixCoF3Zwfc+66VHgDfpo3R4boujYW10zQPopWNsb3NlxCBA6TSSiCVky86cWaabZ1Qmiemhw6Kp6ltlpuikQh/8V6NmZWXNA+iiZnbN8xWjZ2VurGRldm5ldC12MzguMKJnaMQg/rNsORAUOQDD2lVCyhg2sA/S+BlZElfNI/YEL5jINp2ibHbN9v2kbm90ZcQIRSYiABhShvujcmN2xCB7bOJP61uswLFk4pwiLFf19j3Dh9Q5BIJYQRxf4Q98AqNzbmTEICHMyArhQUJN+4MirQrVopinURoL2GOodR8RZxvZFZl5pHR5cGWjcGF5' ); - assert.deepStrictEqual(Buffer.from(blob), expectedBlob); + assert.deepStrictEqual(blob, expectedBlob); }); }); describe('create/append multisig with external signatures', () => { it('should match golden main repo result', () => { - const oneSigTxn = Buffer.from( - 'gqRtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RAuLAFE0oma0skOoAmOzEwfPuLYpEWl4LINtsiLrUqWQkDxh4WHb29//YCpj4MFbiSgD2jKYt0XKRD86zKCF4RDYGicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxgaJwa8Qg5/D4TQaBHfnzHI2HixFV9GcdUaGFwgCQhmf0SVhwaKGjdGhyAqF2AaN0eG6Lo2FtdM0D6KVjbG9zZcQgQOk0koglZMvOnFmmm2dUJonpocOiqepbZabopEIf/FejZmVlzQPoomZ2zfMVo2dlbqxkZXZuZXQtdjM4LjCiZ2jEIP6zbDkQFDkAw9pVQsoYNrAP0vgZWRJXzSP2BC+YyDadomx2zfb9pG5vdGXECEUmIgAYUob7o3JjdsQge2ziT+tbrMCxZOKcIixX9fY9w4fUOQSCWEEcX+EPfAKjc25kxCCNkrSJkAFzoE36Q1mjZmpq/OosQqBd2cH3PuulR4A36aR0eXBlo3BheQ==', - 'base64' + const oneSigTxn = algosdk.base64ToBytes( + 'gqRtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RAuLAFE0oma0skOoAmOzEwfPuLYpEWl4LINtsiLrUqWQkDxh4WHb29//YCpj4MFbiSgD2jKYt0XKRD86zKCF4RDYGicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxgaJwa8Qg5/D4TQaBHfnzHI2HixFV9GcdUaGFwgCQhmf0SVhwaKGjdGhyAqF2AaN0eG6Lo2FtdM0D6KVjbG9zZcQgQOk0koglZMvOnFmmm2dUJonpocOiqepbZabopEIf/FejZmVlzQPoomZ2zfMVo2dlbqxkZXZuZXQtdjM4LjCiZ2jEIP6zbDkQFDkAw9pVQsoYNrAP0vgZWRJXzSP2BC+YyDadomx2zfb9pG5vdGXECEUmIgAYUob7o3JjdsQge2ziT+tbrMCxZOKcIixX9fY9w4fUOQSCWEEcX+EPfAKjc25kxCCNkrSJkAFzoE36Q1mjZmpq/OosQqBd2cH3PuulR4A36aR0eXBlo3BheQ==' ); const signerAddr = sampleAccount2.addr; @@ -210,18 +202,16 @@ describe('Multisig Functionality', () => { 'MANN3ESOHQVHFZBAGD6UK6XFVWEFZQJPWO5SQ2J5LZRCF5E2VVQQ'; assert.strictEqual(txID, expectedTxID); - const expectedBlob = Buffer.from( - 'gqRtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RAuLAFE0oma0skOoAmOzEwfPuLYpEWl4LINtsiLrUqWQkDxh4WHb29//YCpj4MFbiSgD2jKYt0XKRD86zKCF4RDYKicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxoXPEQBAhuyRjsOrnHp3s/xI+iMKiL7QPsh8iJZ22YOJJP0aFUwedMr+a6wfdBXk1OefyrAN1wqJ9rq6O+DrWV1fH0ASBonBrxCDn8PhNBoEd+fMcjYeLEVX0Zx1RoYXCAJCGZ/RJWHBooaN0aHICoXYBo3R4boujYW10zQPopWNsb3NlxCBA6TSSiCVky86cWaabZ1Qmiemhw6Kp6ltlpuikQh/8V6NmZWXNA+iiZnbN8xWjZ2VurGRldm5ldC12MzguMKJnaMQg/rNsORAUOQDD2lVCyhg2sA/S+BlZElfNI/YEL5jINp2ibHbN9v2kbm90ZcQIRSYiABhShvujcmN2xCB7bOJP61uswLFk4pwiLFf19j3Dh9Q5BIJYQRxf4Q98AqNzbmTEII2StImQAXOgTfpDWaNmamr86ixCoF3Zwfc+66VHgDfppHR5cGWjcGF5', - 'base64' + const expectedBlob = algosdk.base64ToBytes( + 'gqRtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RAuLAFE0oma0skOoAmOzEwfPuLYpEWl4LINtsiLrUqWQkDxh4WHb29//YCpj4MFbiSgD2jKYt0XKRD86zKCF4RDYKicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxoXPEQBAhuyRjsOrnHp3s/xI+iMKiL7QPsh8iJZ22YOJJP0aFUwedMr+a6wfdBXk1OefyrAN1wqJ9rq6O+DrWV1fH0ASBonBrxCDn8PhNBoEd+fMcjYeLEVX0Zx1RoYXCAJCGZ/RJWHBooaN0aHICoXYBo3R4boujYW10zQPopWNsb3NlxCBA6TSSiCVky86cWaabZ1Qmiemhw6Kp6ltlpuikQh/8V6NmZWXNA+iiZnbN8xWjZ2VurGRldm5ldC12MzguMKJnaMQg/rNsORAUOQDD2lVCyhg2sA/S+BlZElfNI/YEL5jINp2ibHbN9v2kbm90ZcQIRSYiABhShvujcmN2xCB7bOJP61uswLFk4pwiLFf19j3Dh9Q5BIJYQRxf4Q98AqNzbmTEII2StImQAXOgTfpDWaNmamr86ixCoF3Zwfc+66VHgDfppHR5cGWjcGF5' ); - assert.deepStrictEqual(Buffer.from(blob), expectedBlob); + assert.deepStrictEqual(blob, expectedBlob); }); it('should not sign with signature of invalid length', () => { - const oneSigTxn = Buffer.from( - 'gqRtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RAuLAFE0oma0skOoAmOzEwfPuLYpEWl4LINtsiLrUqWQkDxh4WHb29//YCpj4MFbiSgD2jKYt0XKRD86zKCF4RDYGicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxgaJwa8Qg5/D4TQaBHfnzHI2HixFV9GcdUaGFwgCQhmf0SVhwaKGjdGhyAqF2AaN0eG6Lo2FtdM0D6KVjbG9zZcQgQOk0koglZMvOnFmmm2dUJonpocOiqepbZabopEIf/FejZmVlzQPoomZ2zfMVo2dlbqxkZXZuZXQtdjM4LjCiZ2jEIP6zbDkQFDkAw9pVQsoYNrAP0vgZWRJXzSP2BC+YyDadomx2zfb9pG5vdGXECEUmIgAYUob7o3JjdsQge2ziT+tbrMCxZOKcIixX9fY9w4fUOQSCWEEcX+EPfAKjc25kxCCNkrSJkAFzoE36Q1mjZmpq/OosQqBd2cH3PuulR4A36aR0eXBlo3BheQ==', - 'base64' + const oneSigTxn = algosdk.base64ToBytes( + 'gqRtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RAuLAFE0oma0skOoAmOzEwfPuLYpEWl4LINtsiLrUqWQkDxh4WHb29//YCpj4MFbiSgD2jKYt0XKRD86zKCF4RDYGicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxgaJwa8Qg5/D4TQaBHfnzHI2HixFV9GcdUaGFwgCQhmf0SVhwaKGjdGhyAqF2AaN0eG6Lo2FtdM0D6KVjbG9zZcQgQOk0koglZMvOnFmmm2dUJonpocOiqepbZabopEIf/FejZmVlzQPoomZ2zfMVo2dlbqxkZXZuZXQtdjM4LjCiZ2jEIP6zbDkQFDkAw9pVQsoYNrAP0vgZWRJXzSP2BC+YyDadomx2zfb9pG5vdGXECEUmIgAYUob7o3JjdsQge2ziT+tbrMCxZOKcIixX9fY9w4fUOQSCWEEcX+EPfAKjc25kxCCNkrSJkAFzoE36Q1mjZmpq/OosQqBd2cH3PuulR4A36aR0eXBlo3BheQ==' ); const signerAddr = sampleAccount2.addr; @@ -261,9 +251,8 @@ describe('Multisig Functionality', () => { }); it('should append signature to created raw multisig transaction', () => { - const rawTxBlob = Buffer.from( - 'jKNmZWXOAAPIwKJmds4ADvnao2dlbqxkZXZuZXQtdjM4LjCiZ2jEIP6zbDkQFDkAw9pVQsoYNrAP0vgZWRJXzSP2BC+YyDadomx2zgAO/cKmc2Vsa2V5xCAyEisr1j3cUzGWF6WqU8Sxwm/j3MryjTYitWl3oUBchqNzbmTEII2StImQAXOgTfpDWaNmamr86ixCoF3Zwfc+66VHgDfppHR5cGWma2V5cmVnp3ZvdGVmc3TOAA27oKZ2b3Rla2TNJxCndm90ZWtlecQgcBvX+5ErB7MIEf8oHZ/ulWPlgC4gJokjGSWPd/qTHoindm90ZWxzdM4AD0JA', - 'base64' + const rawTxBlob = algosdk.base64ToBytes( + 'jKNmZWXOAAPIwKJmds4ADvnao2dlbqxkZXZuZXQtdjM4LjCiZ2jEIP6zbDkQFDkAw9pVQsoYNrAP0vgZWRJXzSP2BC+YyDadomx2zgAO/cKmc2Vsa2V5xCAyEisr1j3cUzGWF6WqU8Sxwm/j3MryjTYitWl3oUBchqNzbmTEII2StImQAXOgTfpDWaNmamr86ixCoF3Zwfc+66VHgDfppHR5cGWma2V5cmVnp3ZvdGVmc3TOAA27oKZ2b3Rla2TNJxCndm90ZWtlecQgcBvX+5ErB7MIEf8oHZ/ulWPlgC4gJokjGSWPd/qTHoindm90ZWxzdM4AD0JA' ); const decRawTx = algosdk.decodeUnsignedTransaction(rawTxBlob); @@ -324,20 +313,18 @@ describe('Multisig Functionality', () => { 'E7DA7WTJCWWFQMKSVU5HOIJ5F5HGVGMOZGBIHRJRYGIX7FIJ5VWA'; assert.strictEqual(txID, expectedTxID); - const expectedBlob = 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 expectedBlob = algosdk.base64ToBytes( + 'gqRtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RAcT0s17wJbvnza+NpyHwM0RWbQ+HwKmsT1PLs+w6d6MpdTH3tra+yKZE0K0qEyhSE7Y56+B9oaf2orEbjc/njDYGicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxgaJwa8Qg5/D4TQaBHfnzHI2HixFV9GcdUaGFwgCQhmf0SVhwaKGjdGhyAqF2AaN0eG6Mo2ZlZc4AA8jAomZ2zgAO+dqjZ2VurGRldm5ldC12MzguMKJnaMQg/rNsORAUOQDD2lVCyhg2sA/S+BlZElfNI/YEL5jINp2ibHbOAA79wqZzZWxrZXnEIDISKyvWPdxTMZYXpapTxLHCb+PcyvKNNiK1aXehQFyGo3NuZMQgjZK0iZABc6BN+kNZo2ZqavzqLEKgXdnB9z7rpUeAN+mkdHlwZaZrZXlyZWendm90ZWZzdM4ADbugpnZvdGVrZM0nEKd2b3Rla2V5xCBwG9f7kSsHswgR/ygdn+6VY+WALiAmiSMZJY93+pMeiKd2b3RlbHN0zgAPQkA=' ); - assert.deepStrictEqual(Buffer.from(blob), expectedBlob); + assert.deepStrictEqual(blob, expectedBlob); }); }); describe('should sign keyreg transaction types', () => { it('first partial sig should match golden main repo result', () => { - const rawTxBlob = Buffer.from( - 'jKNmZWXOAAPIwKJmds4ADvnao2dlbqxkZXZuZXQtdjM4LjCiZ2jEIP6zbDkQFDkAw9pVQsoYNrAP0vgZWRJXzSP2BC+YyDadomx2zgAO/cKmc2Vsa2V5xCAyEisr1j3cUzGWF6WqU8Sxwm/j3MryjTYitWl3oUBchqNzbmTEII2StImQAXOgTfpDWaNmamr86ixCoF3Zwfc+66VHgDfppHR5cGWma2V5cmVnp3ZvdGVmc3TOAA27oKZ2b3Rla2TNJxCndm90ZWtlecQgcBvX+5ErB7MIEf8oHZ/ulWPlgC4gJokjGSWPd/qTHoindm90ZWxzdM4AD0JA', - 'base64' + const rawTxBlob = algosdk.base64ToBytes( + 'jKNmZWXOAAPIwKJmds4ADvnao2dlbqxkZXZuZXQtdjM4LjCiZ2jEIP6zbDkQFDkAw9pVQsoYNrAP0vgZWRJXzSP2BC+YyDadomx2zgAO/cKmc2Vsa2V5xCAyEisr1j3cUzGWF6WqU8Sxwm/j3MryjTYitWl3oUBchqNzbmTEII2StImQAXOgTfpDWaNmamr86ixCoF3Zwfc+66VHgDfppHR5cGWma2V5cmVnp3ZvdGVmc3TOAA27oKZ2b3Rla2TNJxCndm90ZWtlecQgcBvX+5ErB7MIEf8oHZ/ulWPlgC4gJokjGSWPd/qTHoindm90ZWxzdM4AD0JA' ); const decRawTx = algosdk.decodeUnsignedTransaction(rawTxBlob); @@ -351,18 +338,16 @@ describe('Multisig Functionality', () => { '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 oneSigTxBlob = algosdk.base64ToBytes( + 'gqRtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RAcT0s17wJbvnza+NpyHwM0RWbQ+HwKmsT1PLs+w6d6MpdTH3tra+yKZE0K0qEyhSE7Y56+B9oaf2orEbjc/njDYGicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxgaJwa8Qg5/D4TQaBHfnzHI2HixFV9GcdUaGFwgCQhmf0SVhwaKGjdGhyAqF2AaN0eG6Mo2ZlZc4AA8jAomZ2zgAO+dqjZ2VurGRldm5ldC12MzguMKJnaMQg/rNsORAUOQDD2lVCyhg2sA/S+BlZElfNI/YEL5jINp2ibHbOAA79wqZzZWxrZXnEIDISKyvWPdxTMZYXpapTxLHCb+PcyvKNNiK1aXehQFyGo3NuZMQgjZK0iZABc6BN+kNZo2ZqavzqLEKgXdnB9z7rpUeAN+mkdHlwZaZrZXlyZWendm90ZWZzdM4ADbugpnZvdGVrZM0nEKd2b3Rla2V5xCBwG9f7kSsHswgR/ygdn+6VY+WALiAmiSMZJY93+pMeiKd2b3RlbHN0zgAPQkA=' ); - assert.deepStrictEqual(Buffer.from(blob), oneSigTxBlob); + assert.deepStrictEqual(blob, oneSigTxBlob); }); it('second partial sig with 3rd pk should match golden main repo result', () => { - 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 rawOneSigTxBlob = algosdk.base64ToBytes( + 'gqRtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RAcT0s17wJbvnza+NpyHwM0RWbQ+HwKmsT1PLs+w6d6MpdTH3tra+yKZE0K0qEyhSE7Y56+B9oaf2orEbjc/njDYGicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxgaJwa8Qg5/D4TQaBHfnzHI2HixFV9GcdUaGFwgCQhmf0SVhwaKGjdGhyAqF2AaN0eG6Mo2ZlZc4AA8jAomZ2zgAO+dqjZ2VurGRldm5ldC12MzguMKJnaMQg/rNsORAUOQDD2lVCyhg2sA/S+BlZElfNI/YEL5jINp2ibHbOAA79wqZzZWxrZXnEIDISKyvWPdxTMZYXpapTxLHCb+PcyvKNNiK1aXehQFyGo3NuZMQgjZK0iZABc6BN+kNZo2ZqavzqLEKgXdnB9z7rpUeAN+mkdHlwZaZrZXlyZWendm90ZWZzdM4ADbugpnZvdGVrZM0nEKd2b3Rla2V5xCBwG9f7kSsHswgR/ygdn+6VY+WALiAmiSMZJY93+pMeiKd2b3RlbHN0zgAPQkA=' ); const decRawTx = algosdk.decodeSignedTransaction(rawOneSigTxBlob).txn; @@ -382,23 +367,22 @@ describe('Multisig Functionality', () => { 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' + const twoSigTxBlob = algosdk.base64ToBytes( + 'gqRtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RAcT0s17wJbvnza+NpyHwM0RWbQ+HwKmsT1PLs+w6d6MpdTH3tra+yKZE0K0qEyhSE7Y56+B9oaf2orEbjc/njDYGicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxgqJwa8Qg5/D4TQaBHfnzHI2HixFV9GcdUaGFwgCQhmf0SVhwaKGhc8RAfScXfzBLaE42NbF9IR0qMa3NBQnhY6kQsV+6htqBsw/bWmc2vBla65CJLSNCNS236BsUMlvbwrs3knF+6bqhD6N0aHICoXYBo3R4boyjZmVlzgADyMCiZnbOAA752qNnZW6sZGV2bmV0LXYzOC4womdoxCD+s2w5EBQ5AMPaVULKGDawD9L4GVkSV80j9gQvmMg2naJsds4ADv3CpnNlbGtlecQgMhIrK9Y93FMxlhelqlPEscJv49zK8o02IrVpd6FAXIajc25kxCCNkrSJkAFzoE36Q1mjZmpq/OosQqBd2cH3PuulR4A36aR0eXBlpmtleXJlZ6d2b3RlZnN0zgANu6Cmdm90ZWtkzScQp3ZvdGVrZXnEIHAb1/uRKwezCBH/KB2f7pVj5YAuICaJIxklj3f6kx6Ip3ZvdGVsc3TOAA9CQA==' ); - assert.deepStrictEqual(Buffer.from(finMsigBlob), twoSigTxBlob); + assert.deepStrictEqual(finMsigBlob, twoSigTxBlob); }); }); describe('mergeMultisigTransactions', () => { it('should be symmetric and match golden main repo result', () => { // prettier-ignore - const oneAndThreeBlob = 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 oneAndThreeBlob = Uint8Array.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]); // prettier-ignore - const twoAndThreeBlob = Buffer.from([130, 164, 109, 115, 105, 103, 131, 166, 115, 117, 98, 115, 105, 103, 147, 129, 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, 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 twoAndThreeBlob = Uint8Array.from([130, 164, 109, 115, 105, 103, 131, 166, 115, 117, 98, 115, 105, 103, 147, 129, 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, 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]); // 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 allThreeBlob = Uint8Array.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 = algosdk.mergeMultisigTransactions([ new Uint8Array(twoAndThreeBlob), @@ -408,19 +392,19 @@ describe('Multisig Functionality', () => { new Uint8Array(oneAndThreeBlob), new Uint8Array(twoAndThreeBlob), ]); - assert.deepStrictEqual(Buffer.from(finMsigBlob), allThreeBlob); - assert.deepStrictEqual(Buffer.from(finMsigBlobTwo), allThreeBlob); + assert.deepStrictEqual(finMsigBlob, allThreeBlob); + assert.deepStrictEqual(finMsigBlobTwo, allThreeBlob); }); it('should merge several transactions', () => { // prettier-ignore - const blobSignedByFirst = 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 blobSignedByFirst = Uint8Array.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 blobSignedBySecond = Buffer.from([ 130, 164, 109, 115, 105, 103, 131, 166, 115, 117, 98, 115, 105, 103, 147, 129, 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, 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, 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 blobSignedBySecond = Uint8Array.from([ 130, 164, 109, 115, 105, 103, 131, 166, 115, 117, 98, 115, 105, 103, 147, 129, 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, 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, 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 blobSignedByThird = Buffer.from([ 130, 164, 109, 115, 105, 103, 131, 166, 115, 117, 98, 115, 105, 103, 147, 129, 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, 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 blobSignedByThird = Uint8Array.from([ 130, 164, 109, 115, 105, 103, 131, 166, 115, 117, 98, 115, 105, 103, 147, 129, 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, 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, ]); // prettier-ignore - const blobSignedByAllThree = 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 blobSignedByAllThree = Uint8Array.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 = algosdk.mergeMultisigTransactions([ new Uint8Array(blobSignedByFirst), @@ -447,22 +431,19 @@ describe('Multisig Functionality', () => { ); // let's check the merged transactions against our reference blob - assert.deepStrictEqual(Buffer.from(finMsigBlob), blobSignedByAllThree); - assert.deepStrictEqual(Buffer.from(finMsigBlobTwo), blobSignedByAllThree); + assert.deepStrictEqual(finMsigBlob, blobSignedByAllThree); + assert.deepStrictEqual(finMsigBlobTwo, blobSignedByAllThree); }); it('should correctly handle a different sender', () => { - const oneAndThreeBlob = Buffer.from( - 'g6Rtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RAWLcyn6nB68yo/PUHXB21wyTy+PhHgMQNOIXPTGB96faZP2xqpQ8IFlIR2LPotlX68ylK8MCl82SUfMR4FYyzAIGicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxgqJwa8Qg5/D4TQaBHfnzHI2HixFV9GcdUaGFwgCQhmf0SVhwaKGhc8RAQ3t8lAipybLbWaRa3EDKl0mLGwUpYzl0iBCHSflhJM6zboJiT10FnWtXqW0dUBzpj9yeqtSuSJyKb8Ml3YJkCqN0aHICoXYBpHNnbnLEII2StImQAXOgTfpDWaNmamr86ixCoF3Zwfc+66VHgDfpo3R4boujYW10zQPopWNsb3NlxCBA6TSSiCVky86cWaabZ1Qmiemhw6Kp6ltlpuikQh/8V6NmZWXNA+iiZnbN8xWjZ2VurGRldm5ldC12MzguMKJnaMQg/rNsORAUOQDD2lVCyhg2sA/S+BlZElfNI/YEL5jINp2ibHbN9v2kbm90ZcQIRSYiABhShvujcmN2xCB7bOJP61uswLFk4pwiLFf19j3Dh9Q5BIJYQRxf4Q98AqNzbmTEICHMyArhQUJN+4MirQrVopinURoL2GOodR8RZxvZFZl5pHR5cGWjcGF5', - 'base64' + const oneAndThreeBlob = algosdk.base64ToBytes( + 'g6Rtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RAWLcyn6nB68yo/PUHXB21wyTy+PhHgMQNOIXPTGB96faZP2xqpQ8IFlIR2LPotlX68ylK8MCl82SUfMR4FYyzAIGicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxgqJwa8Qg5/D4TQaBHfnzHI2HixFV9GcdUaGFwgCQhmf0SVhwaKGhc8RAQ3t8lAipybLbWaRa3EDKl0mLGwUpYzl0iBCHSflhJM6zboJiT10FnWtXqW0dUBzpj9yeqtSuSJyKb8Ml3YJkCqN0aHICoXYBpHNnbnLEII2StImQAXOgTfpDWaNmamr86ixCoF3Zwfc+66VHgDfpo3R4boujYW10zQPopWNsb3NlxCBA6TSSiCVky86cWaabZ1Qmiemhw6Kp6ltlpuikQh/8V6NmZWXNA+iiZnbN8xWjZ2VurGRldm5ldC12MzguMKJnaMQg/rNsORAUOQDD2lVCyhg2sA/S+BlZElfNI/YEL5jINp2ibHbN9v2kbm90ZcQIRSYiABhShvujcmN2xCB7bOJP61uswLFk4pwiLFf19j3Dh9Q5BIJYQRxf4Q98AqNzbmTEICHMyArhQUJN+4MirQrVopinURoL2GOodR8RZxvZFZl5pHR5cGWjcGF5' ); - const twoAndThreeBlob = Buffer.from( - 'g6Rtc2lng6ZzdWJzaWeTgaJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXiConBrxCAJYzIJU3OJ8HVnEXc5kcfQPhtzyMT1K/av8BqiXPnCcaFzxED7h9lpTNsdbX5QOixjISlwYrju3bEc412D4HH47w7YfWbAms8jih6kJrWIw/qVyzPHyW60YaFBk5Mi8SDYk/cAgqJwa8Qg5/D4TQaBHfnzHI2HixFV9GcdUaGFwgCQhmf0SVhwaKGhc8RAQ3t8lAipybLbWaRa3EDKl0mLGwUpYzl0iBCHSflhJM6zboJiT10FnWtXqW0dUBzpj9yeqtSuSJyKb8Ml3YJkCqN0aHICoXYBpHNnbnLEII2StImQAXOgTfpDWaNmamr86ixCoF3Zwfc+66VHgDfpo3R4boujYW10zQPopWNsb3NlxCBA6TSSiCVky86cWaabZ1Qmiemhw6Kp6ltlpuikQh/8V6NmZWXNA+iiZnbN8xWjZ2VurGRldm5ldC12MzguMKJnaMQg/rNsORAUOQDD2lVCyhg2sA/S+BlZElfNI/YEL5jINp2ibHbN9v2kbm90ZcQIRSYiABhShvujcmN2xCB7bOJP61uswLFk4pwiLFf19j3Dh9Q5BIJYQRxf4Q98AqNzbmTEICHMyArhQUJN+4MirQrVopinURoL2GOodR8RZxvZFZl5pHR5cGWjcGF5', - 'base64' + const twoAndThreeBlob = algosdk.base64ToBytes( + 'g6Rtc2lng6ZzdWJzaWeTgaJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXiConBrxCAJYzIJU3OJ8HVnEXc5kcfQPhtzyMT1K/av8BqiXPnCcaFzxED7h9lpTNsdbX5QOixjISlwYrju3bEc412D4HH47w7YfWbAms8jih6kJrWIw/qVyzPHyW60YaFBk5Mi8SDYk/cAgqJwa8Qg5/D4TQaBHfnzHI2HixFV9GcdUaGFwgCQhmf0SVhwaKGhc8RAQ3t8lAipybLbWaRa3EDKl0mLGwUpYzl0iBCHSflhJM6zboJiT10FnWtXqW0dUBzpj9yeqtSuSJyKb8Ml3YJkCqN0aHICoXYBpHNnbnLEII2StImQAXOgTfpDWaNmamr86ixCoF3Zwfc+66VHgDfpo3R4boujYW10zQPopWNsb3NlxCBA6TSSiCVky86cWaabZ1Qmiemhw6Kp6ltlpuikQh/8V6NmZWXNA+iiZnbN8xWjZ2VurGRldm5ldC12MzguMKJnaMQg/rNsORAUOQDD2lVCyhg2sA/S+BlZElfNI/YEL5jINp2ibHbN9v2kbm90ZcQIRSYiABhShvujcmN2xCB7bOJP61uswLFk4pwiLFf19j3Dh9Q5BIJYQRxf4Q98AqNzbmTEICHMyArhQUJN+4MirQrVopinURoL2GOodR8RZxvZFZl5pHR5cGWjcGF5' ); - const allThreeBlob = Buffer.from( - 'g6Rtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RAWLcyn6nB68yo/PUHXB21wyTy+PhHgMQNOIXPTGB96faZP2xqpQ8IFlIR2LPotlX68ylK8MCl82SUfMR4FYyzAIKicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxoXPEQPuH2WlM2x1tflA6LGMhKXBiuO7dsRzjXYPgcfjvDth9ZsCazyOKHqQmtYjD+pXLM8fJbrRhoUGTkyLxINiT9wCConBrxCDn8PhNBoEd+fMcjYeLEVX0Zx1RoYXCAJCGZ/RJWHBooaFzxEBDe3yUCKnJsttZpFrcQMqXSYsbBSljOXSIEIdJ+WEkzrNugmJPXQWda1epbR1QHOmP3J6q1K5InIpvwyXdgmQKo3RocgKhdgGkc2ducsQgjZK0iZABc6BN+kNZo2ZqavzqLEKgXdnB9z7rpUeAN+mjdHhui6NhbXTNA+ilY2xvc2XEIEDpNJKIJWTLzpxZpptnVCaJ6aHDoqnqW2Wm6KRCH/xXo2ZlZc0D6KJmds3zFaNnZW6sZGV2bmV0LXYzOC4womdoxCD+s2w5EBQ5AMPaVULKGDawD9L4GVkSV80j9gQvmMg2naJsds32/aRub3RlxAhFJiIAGFKG+6NyY3bEIHts4k/rW6zAsWTinCIsV/X2PcOH1DkEglhBHF/hD3wCo3NuZMQgIczICuFBQk37gyKtCtWimKdRGgvYY6h1HxFnG9kVmXmkdHlwZaNwYXk=', - 'base64' + const allThreeBlob = algosdk.base64ToBytes( + 'g6Rtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RAWLcyn6nB68yo/PUHXB21wyTy+PhHgMQNOIXPTGB96faZP2xqpQ8IFlIR2LPotlX68ylK8MCl82SUfMR4FYyzAIKicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxoXPEQPuH2WlM2x1tflA6LGMhKXBiuO7dsRzjXYPgcfjvDth9ZsCazyOKHqQmtYjD+pXLM8fJbrRhoUGTkyLxINiT9wCConBrxCDn8PhNBoEd+fMcjYeLEVX0Zx1RoYXCAJCGZ/RJWHBooaFzxEBDe3yUCKnJsttZpFrcQMqXSYsbBSljOXSIEIdJ+WEkzrNugmJPXQWda1epbR1QHOmP3J6q1K5InIpvwyXdgmQKo3RocgKhdgGkc2ducsQgjZK0iZABc6BN+kNZo2ZqavzqLEKgXdnB9z7rpUeAN+mjdHhui6NhbXTNA+ilY2xvc2XEIEDpNJKIJWTLzpxZpptnVCaJ6aHDoqnqW2Wm6KRCH/xXo2ZlZc0D6KJmds3zFaNnZW6sZGV2bmV0LXYzOC4womdoxCD+s2w5EBQ5AMPaVULKGDawD9L4GVkSV80j9gQvmMg2naJsds32/aRub3RlxAhFJiIAGFKG+6NyY3bEIHts4k/rW6zAsWTinCIsV/X2PcOH1DkEglhBHF/hD3wCo3NuZMQgIczICuFBQk37gyKtCtWimKdRGgvYY6h1HxFnG9kVmXmkdHlwZaNwYXk=' ); const finMsigBlob = algosdk.mergeMultisigTransactions([ @@ -473,8 +454,8 @@ describe('Multisig Functionality', () => { new Uint8Array(oneAndThreeBlob), new Uint8Array(twoAndThreeBlob), ]); - assert.deepStrictEqual(Buffer.from(finMsigBlob), allThreeBlob); - assert.deepStrictEqual(Buffer.from(finMsigBlobTwo), allThreeBlob); + assert.deepStrictEqual(finMsigBlob, allThreeBlob); + assert.deepStrictEqual(finMsigBlobTwo, allThreeBlob); }); }); @@ -488,58 +469,46 @@ describe('Multisig Functionality', () => { // Create a multisig transaction to use for each test beforeEach(() => { const paymentTxnObj = { - snd: Buffer.from( - algosdk.decodeAddress( - 'RWJLJCMQAFZ2ATP2INM2GZTKNL6OULCCUBO5TQPXH3V2KR4AG7U5UA5JNM' - ).publicKey - ), - rcv: Buffer.from( - algosdk.decodeAddress( - 'PNWOET7LLOWMBMLE4KOCELCX6X3D3Q4H2Q4QJASYIEOF7YIPPQBG3YQ5YI' - ).publicKey - ), + snd: algosdk.decodeAddress( + 'RWJLJCMQAFZ2ATP2INM2GZTKNL6OULCCUBO5TQPXH3V2KR4AG7U5UA5JNM' + ).publicKey, + rcv: algosdk.decodeAddress( + 'PNWOET7LLOWMBMLE4KOCELCX6X3D3Q4H2Q4QJASYIEOF7YIPPQBG3YQ5YI' + ).publicKey, fee: 1000, amt: 1000, - close: Buffer.from( - algosdk.decodeAddress( - 'IDUTJEUIEVSMXTU4LGTJWZ2UE2E6TIODUKU6UW3FU3UKIQQ77RLUBBBFLA' - ).publicKey - ), - gh: Buffer.from( - '/rNsORAUOQDD2lVCyhg2sA/S+BlZElfNI/YEL5jINp0=', - 'base64' + close: algosdk.decodeAddress( + 'IDUTJEUIEVSMXTU4LGTJWZ2UE2E6TIODUKU6UW3FU3UKIQQ77RLUBBBFLA' + ).publicKey, + gh: algosdk.base64ToBytes( + '/rNsORAUOQDD2lVCyhg2sA/S+BlZElfNI/YEL5jINp0=' ), fv: 62229, lv: 63229, gen: 'devnet-v38.0', type: 'pay', - note: Buffer.from('RSYiABhShvs=', 'base64'), + note: algosdk.base64ToBytes('RSYiABhShvs='), }; stdPaymentTxn = algosdk.Transaction.from_obj_for_encoding(paymentTxnObj); msigPaymentTxn = MultisigTransaction.from_obj_for_encoding(paymentTxnObj); const keyregTxnObj = { - snd: Buffer.from( - algosdk.decodeAddress( - 'RWJLJCMQAFZ2ATP2INM2GZTKNL6OULCCUBO5TQPXH3V2KR4AG7U5UA5JNM' - ).publicKey - ), + snd: algosdk.decodeAddress( + 'RWJLJCMQAFZ2ATP2INM2GZTKNL6OULCCUBO5TQPXH3V2KR4AG7U5UA5JNM' + ).publicKey, fee: 10, fv: 51, lv: 61, - note: Buffer.from([123, 12, 200]), - gh: Buffer.from( - 'JgsgCaCTqIaLeVhyL6XlRu3n7Rfk2FxMeK+wRSaQ7dI=', - 'base64' + note: Uint8Array.from([123, 12, 200]), + gh: algosdk.base64ToBytes( + 'JgsgCaCTqIaLeVhyL6XlRu3n7Rfk2FxMeK+wRSaQ7dI=' ), - votekey: Buffer.from( - '5/D4TQaBHfnzHI2HixFV9GcdUaGFwgCQhmf0SVhwaKE=', - 'base64' + votekey: algosdk.base64ToBytes( + '5/D4TQaBHfnzHI2HixFV9GcdUaGFwgCQhmf0SVhwaKE=' ), - selkey: Buffer.from( - 'oImqaSLjuZj63/bNSAjd+eAh5JROOJ6j1cY4eGaJGX4=', - 'base64' + selkey: algosdk.base64ToBytes( + 'oImqaSLjuZj63/bNSAjd+eAh5JROOJ6j1cY4eGaJGX4=' ), votefst: 123, votelst: 456, @@ -581,55 +550,43 @@ describe('Multisig Functionality', () => { // Create a multisig transaction to use for each test beforeEach(() => { const paymentTxnObj = { - snd: Buffer.from( - algosdk.decodeAddress( - 'RWJLJCMQAFZ2ATP2INM2GZTKNL6OULCCUBO5TQPXH3V2KR4AG7U5UA5JNM' - ).publicKey - ), - rcv: Buffer.from( - algosdk.decodeAddress( - 'PNWOET7LLOWMBMLE4KOCELCX6X3D3Q4H2Q4QJASYIEOF7YIPPQBG3YQ5YI' - ).publicKey - ), + snd: algosdk.decodeAddress( + 'RWJLJCMQAFZ2ATP2INM2GZTKNL6OULCCUBO5TQPXH3V2KR4AG7U5UA5JNM' + ).publicKey, + rcv: algosdk.decodeAddress( + 'PNWOET7LLOWMBMLE4KOCELCX6X3D3Q4H2Q4QJASYIEOF7YIPPQBG3YQ5YI' + ).publicKey, fee: 1000, amt: 1000, - close: Buffer.from( - algosdk.decodeAddress( - 'IDUTJEUIEVSMXTU4LGTJWZ2UE2E6TIODUKU6UW3FU3UKIQQ77RLUBBBFLA' - ).publicKey - ), - gh: Buffer.from( - '/rNsORAUOQDD2lVCyhg2sA/S+BlZElfNI/YEL5jINp0=', - 'base64' + close: algosdk.decodeAddress( + 'IDUTJEUIEVSMXTU4LGTJWZ2UE2E6TIODUKU6UW3FU3UKIQQ77RLUBBBFLA' + ).publicKey, + gh: algosdk.base64ToBytes( + '/rNsORAUOQDD2lVCyhg2sA/S+BlZElfNI/YEL5jINp0=' ), fv: 62229, lv: 63229, gen: 'devnet-v38.0', type: 'pay', - note: Buffer.from('RSYiABhShvs=', 'base64'), + note: algosdk.base64ToBytes('RSYiABhShvs='), }; const keyregTxnObj = { - snd: Buffer.from( - algosdk.decodeAddress( - 'RWJLJCMQAFZ2ATP2INM2GZTKNL6OULCCUBO5TQPXH3V2KR4AG7U5UA5JNM' - ).publicKey - ), + snd: algosdk.decodeAddress( + 'RWJLJCMQAFZ2ATP2INM2GZTKNL6OULCCUBO5TQPXH3V2KR4AG7U5UA5JNM' + ).publicKey, fee: 10, fv: 51, lv: 61, - note: Buffer.from([123, 12, 200]), - gh: Buffer.from( - 'JgsgCaCTqIaLeVhyL6XlRu3n7Rfk2FxMeK+wRSaQ7dI=', - 'base64' + note: Uint8Array.from([123, 12, 200]), + gh: algosdk.base64ToBytes( + 'JgsgCaCTqIaLeVhyL6XlRu3n7Rfk2FxMeK+wRSaQ7dI=' ), - votekey: Buffer.from( - '5/D4TQaBHfnzHI2HixFV9GcdUaGFwgCQhmf0SVhwaKE=', - 'base64' + votekey: algosdk.base64ToBytes( + '5/D4TQaBHfnzHI2HixFV9GcdUaGFwgCQhmf0SVhwaKE=' ), - selkey: Buffer.from( - 'oImqaSLjuZj63/bNSAjd+eAh5JROOJ6j1cY4eGaJGX4=', - 'base64' + selkey: algosdk.base64ToBytes( + 'oImqaSLjuZj63/bNSAjd+eAh5JROOJ6j1cY4eGaJGX4=' ), votefst: 123, votelst: 456, @@ -672,55 +629,43 @@ describe('Multisig Functionality', () => { // Create a multisig transaction to use for each test beforeEach(() => { const paymentTxnObj = { - snd: Buffer.from( - algosdk.decodeAddress( - 'RWJLJCMQAFZ2ATP2INM2GZTKNL6OULCCUBO5TQPXH3V2KR4AG7U5UA5JNM' - ).publicKey - ), - rcv: Buffer.from( - algosdk.decodeAddress( - 'PNWOET7LLOWMBMLE4KOCELCX6X3D3Q4H2Q4QJASYIEOF7YIPPQBG3YQ5YI' - ).publicKey - ), + snd: algosdk.decodeAddress( + 'RWJLJCMQAFZ2ATP2INM2GZTKNL6OULCCUBO5TQPXH3V2KR4AG7U5UA5JNM' + ).publicKey, + rcv: algosdk.decodeAddress( + 'PNWOET7LLOWMBMLE4KOCELCX6X3D3Q4H2Q4QJASYIEOF7YIPPQBG3YQ5YI' + ).publicKey, fee: 1000, amt: 1000, - close: Buffer.from( - algosdk.decodeAddress( - 'IDUTJEUIEVSMXTU4LGTJWZ2UE2E6TIODUKU6UW3FU3UKIQQ77RLUBBBFLA' - ).publicKey - ), - gh: Buffer.from( - '/rNsORAUOQDD2lVCyhg2sA/S+BlZElfNI/YEL5jINp0=', - 'base64' + close: algosdk.decodeAddress( + 'IDUTJEUIEVSMXTU4LGTJWZ2UE2E6TIODUKU6UW3FU3UKIQQ77RLUBBBFLA' + ).publicKey, + gh: algosdk.base64ToBytes( + '/rNsORAUOQDD2lVCyhg2sA/S+BlZElfNI/YEL5jINp0=' ), fv: 62229, lv: 63229, gen: 'devnet-v38.0', type: 'pay', - note: Buffer.from('RSYiABhShvs=', 'base64'), + note: algosdk.base64ToBytes('RSYiABhShvs='), }; const keyregTxnObj = { - snd: Buffer.from( - algosdk.decodeAddress( - 'RWJLJCMQAFZ2ATP2INM2GZTKNL6OULCCUBO5TQPXH3V2KR4AG7U5UA5JNM' - ).publicKey - ), + snd: algosdk.decodeAddress( + 'RWJLJCMQAFZ2ATP2INM2GZTKNL6OULCCUBO5TQPXH3V2KR4AG7U5UA5JNM' + ).publicKey, fee: 10, fv: 51, lv: 61, - note: Buffer.from([123, 12, 200]), - gh: Buffer.from( - 'JgsgCaCTqIaLeVhyL6XlRu3n7Rfk2FxMeK+wRSaQ7dI=', - 'base64' + note: Uint8Array.from([123, 12, 200]), + gh: algosdk.base64ToBytes( + 'JgsgCaCTqIaLeVhyL6XlRu3n7Rfk2FxMeK+wRSaQ7dI=' ), - votekey: Buffer.from( - '5/D4TQaBHfnzHI2HixFV9GcdUaGFwgCQhmf0SVhwaKE=', - 'base64' + votekey: algosdk.base64ToBytes( + '5/D4TQaBHfnzHI2HixFV9GcdUaGFwgCQhmf0SVhwaKE=' ), - selkey: Buffer.from( - 'oImqaSLjuZj63/bNSAjd+eAh5JROOJ6j1cY4eGaJGX4=', - 'base64' + selkey: algosdk.base64ToBytes( + 'oImqaSLjuZj63/bNSAjd+eAh5JROOJ6j1cY4eGaJGX4=' ), votefst: 123, votelst: 456, diff --git a/tests/7.AlgoSDK.js b/tests/7.AlgoSDK.js index e54a59734..3ee526318 100644 --- a/tests/7.AlgoSDK.js +++ b/tests/7.AlgoSDK.js @@ -1,5 +1,4 @@ /* eslint-env mocha */ -const { Buffer } = require('buffer'); const assert = require('assert'); const algosdk = require('../src/index'); const nacl = require('../src/nacl/naclWrappers'); @@ -39,7 +38,7 @@ describe('Algosdk (AKA end to end)', () => { const genesisHash = 'JgsgCaCTqIaLeVhyL6XlRu3n7Rfk2FxMeK+wRSaQ7dI='; const closeRemainderTo = 'IDUTJEUIEVSMXTU4LGTJWZ2UE2E6TIODUKU6UW3FU3UKIQQ77RLUBBBFLA'; - const note = new Uint8Array(Buffer.from('6gAVR0Nsv5Y=', 'base64')); + const note = new Uint8Array(algosdk.base64ToBytes('6gAVR0Nsv5Y=')); const from = to; const suggestedParams = { genesisHash, @@ -63,9 +62,8 @@ describe('Algosdk (AKA end to end)', () => { ); assert.deepStrictEqual(txnAsBuffer, txnAsBufferRecovered); const txnAsBufferGolden = new Uint8Array( - Buffer.from( - 'i6NhbXTNA+ilY2xvc2XEIEDpNJKIJWTLzpxZpptnVCaJ6aHDoqnqW2Wm6KRCH/xXo2ZlZc0EmKJmds0wsqNnZW6sZGV2bmV0LXYzMy4womdoxCAmCyAJoJOohot5WHIvpeVG7eftF+TYXEx4r7BFJpDt0qJsds00mqRub3RlxAjqABVHQ2y/lqNyY3bEIHts4k/rW6zAsWTinCIsV/X2PcOH1DkEglhBHF/hD3wCo3NuZMQge2ziT+tbrMCxZOKcIixX9fY9w4fUOQSCWEEcX+EPfAKkdHlwZaNwYXk=', - 'base64' + algosdk.base64ToBytes( + 'i6NhbXTNA+ilY2xvc2XEIEDpNJKIJWTLzpxZpptnVCaJ6aHDoqnqW2Wm6KRCH/xXo2ZlZc0EmKJmds0wsqNnZW6sZGV2bmV0LXYzMy4womdoxCAmCyAJoJOohot5WHIvpeVG7eftF+TYXEx4r7BFJpDt0qJsds00mqRub3RlxAjqABVHQ2y/lqNyY3bEIHts4k/rW6zAsWTinCIsV/X2PcOH1DkEglhBHF/hD3wCo3NuZMQge2ziT+tbrMCxZOKcIixX9fY9w4fUOQSCWEEcX+EPfAKkdHlwZaNwYXk=' ) ); assert.deepStrictEqual(txnAsBufferGolden, txnAsBufferRecovered); @@ -81,7 +79,7 @@ describe('Algosdk (AKA end to end)', () => { const genesisHash = 'JgsgCaCTqIaLeVhyL6XlRu3n7Rfk2FxMeK+wRSaQ7dI='; const closeRemainderTo = 'IDUTJEUIEVSMXTU4LGTJWZ2UE2E6TIODUKU6UW3FU3UKIQQ77RLUBBBFLA'; - const note = new Uint8Array(Buffer.from('6gAVR0Nsv5Y=', 'base64')); + const note = new Uint8Array(algosdk.base64ToBytes('6gAVR0Nsv5Y=')); const from = to; const suggestedParams = { genesisHash, @@ -109,7 +107,7 @@ describe('Algosdk (AKA end to end)', () => { const recoveredSignedTxnBytes = txnAsObjRecovered.signTxn(sk.sk); assert.deepStrictEqual(initialSignedTxnBytes, recoveredSignedTxnBytes); const signedTxnBytesGolden = new Uint8Array( - Buffer.from( + algosdk.base64ToBytes( 'g6RzZ25yxCDn8PhNBoEd+fMcjYeLEVX0Zx1RoYXCAJCGZ/RJWHBooaNzaWfEQDJHtrytU9p3nhRH1XS8tX+KmeKGyekigG7M704dOkBMTqiOJFuukbK2gUViJtivsPrKNiV0+WIrdbBk7gmNkgGjdHhui6NhbXTNA+ilY2xvc2XEIEDpNJKIJWTLzpxZpptnVCaJ6aHDoqnqW2Wm6KRCH/xXo2ZlZc0EmKJmds0wsqNnZW6sZGV2bmV0LXYzMy4womdoxCAmCyAJoJOohot5WHIvpeVG7eftF+TYXEx4r7BFJpDt0qJsds00mqRub3RlxAjqABVHQ2y/lqNyY3bEIHts4k/rW6zAsWTinCIsV/X2PcOH1DkEglhBHF/hD3wCo3NuZMQge2ziT+tbrMCxZOKcIixX9fY9w4fUOQSCWEEcX+EPfAKkdHlwZaNwYXk=', 'base64' ) @@ -134,16 +132,13 @@ describe('Algosdk (AKA end to end)', () => { genesisHash: 'JgsgCaCTqIaLeVhyL6XlRu3n7Rfk2FxMeK+wRSaQ7dI=', closeRemainderTo: 'IDUTJEUIEVSMXTU4LGTJWZ2UE2E6TIODUKU6UW3FU3UKIQQ77RLUBBBFLA', - note: new Uint8Array(Buffer.from('6gAVR0Nsv5Y=', 'base64')), + note: new Uint8Array(algosdk.base64ToBytes('6gAVR0Nsv5Y=')), }; sk = algosdk.mnemonicToSecretKey(sk); const jsDec = algosdk.signTransaction(o, sk.sk); - assert.deepStrictEqual( - Buffer.from(jsDec.blob), - Buffer.from(golden, 'base64') - ); + assert.deepStrictEqual(jsDec.blob, algosdk.base64ToBytes(golden)); // // Check txid const txGolden = '5FJDJD5LMZC3EHUYYJNH5I23U4X6H2KXABNDGPIL557ZMJ33GZHQ'; @@ -165,17 +160,14 @@ describe('Algosdk (AKA end to end)', () => { genesisHash: 'JgsgCaCTqIaLeVhyL6XlRu3n7Rfk2FxMeK+wRSaQ7dI=', closeRemainderTo: 'IDUTJEUIEVSMXTU4LGTJWZ2UE2E6TIODUKU6UW3FU3UKIQQ77RLUBBBFLA', - note: new Uint8Array(Buffer.from('6gAVR0Nsv5Y=', 'base64')), + note: new Uint8Array(algosdk.base64ToBytes('6gAVR0Nsv5Y=')), flatFee: true, }; sk = algosdk.mnemonicToSecretKey(sk); const jsDec = algosdk.signTransaction(o, sk.sk); - assert.deepStrictEqual( - Buffer.from(jsDec.blob), - Buffer.from(golden, 'base64') - ); + assert.deepStrictEqual(jsDec.blob, algosdk.base64ToBytes(golden)); // // Check txid const txGolden = '5FJDJD5LMZC3EHUYYJNH5I23U4X6H2KXABNDGPIL557ZMJ33GZHQ'; @@ -199,17 +191,14 @@ describe('Algosdk (AKA end to end)', () => { genesisHash: 'JgsgCaCTqIaLeVhyL6XlRu3n7Rfk2FxMeK+wRSaQ7dI=', closeRemainderTo: 'IDUTJEUIEVSMXTU4LGTJWZ2UE2E6TIODUKU6UW3FU3UKIQQ77RLUBBBFLA', - note: new Uint8Array(Buffer.from('6gAVR0Nsv5Y=', 'base64')), + note: new Uint8Array(algosdk.base64ToBytes('6gAVR0Nsv5Y=')), lease, }; sk = algosdk.mnemonicToSecretKey(sk); const jsDec = algosdk.signTransaction(o, sk.sk); - assert.deepStrictEqual( - Buffer.from(jsDec.blob), - Buffer.from(golden, 'base64') - ); + assert.deepStrictEqual(jsDec.blob, algosdk.base64ToBytes(golden)); // Check txid const txGolden = '7BG6COBZKF6I6W5XY72ZE4HXV6LLZ6ENSR6DASEGSTXYXR4XJOOQ'; @@ -232,7 +221,7 @@ describe('Algosdk (AKA end to end)', () => { const genesisHash = 'JgsgCaCTqIaLeVhyL6XlRu3n7Rfk2FxMeK+wRSaQ7dI='; const closeRemainderTo = 'IDUTJEUIEVSMXTU4LGTJWZ2UE2E6TIODUKU6UW3FU3UKIQQ77RLUBBBFLA'; - const note = new Uint8Array(Buffer.from('6gAVR0Nsv5Y=', 'base64')); + const note = new Uint8Array(algosdk.base64ToBytes('6gAVR0Nsv5Y=')); sk = algosdk.mnemonicToSecretKey(sk); const key = nacl.keyPairFromSecretKey(sk.sk); const from = algosdk.encodeAddress(key.publicKey); @@ -254,10 +243,7 @@ describe('Algosdk (AKA end to end)', () => { txn.addLease(lease, fee); const txnBytes = txn.signTxn(sk.sk); - assert.deepStrictEqual( - Buffer.from(txnBytes), - Buffer.from(golden, 'base64') - ); + assert.deepStrictEqual(txnBytes, algosdk.base64ToBytes(golden)); // Check txid const txGolden = '7BG6COBZKF6I6W5XY72ZE4HXV6LLZ6ENSR6DASEGSTXYXR4XJOOQ'; @@ -268,14 +254,14 @@ describe('Algosdk (AKA end to end)', () => { describe('Sign and verify bytes', () => { it('should verify a correct signature', () => { const account = algosdk.generateAccount(); - const toSign = new Uint8Array(Buffer.from([1, 9, 25, 49])); + const toSign = Uint8Array.from([1, 9, 25, 49]); const signed = algosdk.signBytes(toSign, account.sk); assert.equal(true, algosdk.verifyBytes(toSign, signed, account.addr)); }); it('should not verify a corrupted signature', () => { const account = algosdk.generateAccount(); - const toSign = Buffer.from([1, 9, 25, 49]); + const toSign = Uint8Array.from([1, 9, 25, 49]); const signed = algosdk.signBytes(toSign, account.sk); signed[0] = (signed[0] + 1) % 256; assert.equal(false, algosdk.verifyBytes(toSign, signed, account.addr)); @@ -373,16 +359,15 @@ describe('Algosdk (AKA end to end)', () => { genesisHash: 'JgsgCaCTqIaLeVhyL6XlRu3n7Rfk2FxMeK+wRSaQ7dI=', closeRemainderTo: 'IDUTJEUIEVSMXTU4LGTJWZ2UE2E6TIODUKU6UW3FU3UKIQQ77RLUBBBFLA', - note: new Uint8Array(Buffer.from('X4Bl4wQ9rCo=', 'base64')), + note: algosdk.base64ToBytes('X4Bl4wQ9rCo='), }; const jsDec = algosdk.signMultisigTransaction(o, params, sk); // this golden also contains the correct multisig address - const golden = Buffer.from( - 'gqRtc2lng6ZzdWJzaWeTgaJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXiBonBrxCAJYzIJU3OJ8HVnEXc5kcfQPhtzyMT1K/av8BqiXPnCcYKicGvEIOfw+E0GgR358xyNh4sRVfRnHVGhhcIAkIZn9ElYcGihoXPEQF6nXZ7CgInd1h7NVspIPFZNhkPL+vGFpTNwH3Eh9gwPM8pf1EPTHfPvjf14sS7xN7mTK+wrz7Odhp4rdWBNUASjdGhyAqF2AaN0eG6Lo2FtdM0D6KVjbG9zZcQgQOk0koglZMvOnFmmm2dUJonpocOiqepbZabopEIf/FejZmVlzQSYomZ2zTCyo2dlbqxkZXZuZXQtdjMzLjCiZ2jEICYLIAmgk6iGi3lYci+l5Ubt5+0X5NhcTHivsEUmkO3Somx2zTSapG5vdGXECF+AZeMEPawqo3JjdsQge2ziT+tbrMCxZOKcIixX9fY9w4fUOQSCWEEcX+EPfAKjc25kxCCNkrSJkAFzoE36Q1mjZmpq/OosQqBd2cH3PuulR4A36aR0eXBlo3BheQ==', - 'base64' + const golden = algosdk.base64ToBytes( + 'gqRtc2lng6ZzdWJzaWeTgaJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXiBonBrxCAJYzIJU3OJ8HVnEXc5kcfQPhtzyMT1K/av8BqiXPnCcYKicGvEIOfw+E0GgR358xyNh4sRVfRnHVGhhcIAkIZn9ElYcGihoXPEQF6nXZ7CgInd1h7NVspIPFZNhkPL+vGFpTNwH3Eh9gwPM8pf1EPTHfPvjf14sS7xN7mTK+wrz7Odhp4rdWBNUASjdGhyAqF2AaN0eG6Lo2FtdM0D6KVjbG9zZcQgQOk0koglZMvOnFmmm2dUJonpocOiqepbZabopEIf/FejZmVlzQSYomZ2zTCyo2dlbqxkZXZuZXQtdjMzLjCiZ2jEICYLIAmgk6iGi3lYci+l5Ubt5+0X5NhcTHivsEUmkO3Somx2zTSapG5vdGXECF+AZeMEPawqo3JjdsQge2ziT+tbrMCxZOKcIixX9fY9w4fUOQSCWEEcX+EPfAKjc25kxCCNkrSJkAFzoE36Q1mjZmpq/OosQqBd2cH3PuulR4A36aR0eXBlo3BheQ==' ); - assert.deepStrictEqual(Buffer.from(jsDec.blob), golden); + assert.deepStrictEqual(jsDec.blob, golden); // Check txid const txGolden = 'TDIO6RJWJIVDDJZELMSX5CPJW7MUNM3QR4YAHYAKHF3W2CFRTI7A'; @@ -416,7 +401,7 @@ describe('Algosdk (AKA end to end)', () => { const genesisHash = 'JgsgCaCTqIaLeVhyL6XlRu3n7Rfk2FxMeK+wRSaQ7dI='; const closeRemainder = 'IDUTJEUIEVSMXTU4LGTJWZ2UE2E6TIODUKU6UW3FU3UKIQQ77RLUBBBFLA'; - const note = new Uint8Array(Buffer.from('X4Bl4wQ9rCo=', 'base64')); + const note = algosdk.base64ToBytes('X4Bl4wQ9rCo='); const oDict = { to: toAddr, from: fromAddr, @@ -468,17 +453,15 @@ describe('Algosdk (AKA end to end)', () => { const { sk } = algosdk.mnemonicToSecretKey(mnem1); // this is a multisig transaction with an existing signature - const o = Buffer.from( - 'gqRtc2lng6ZzdWJzaWeTgaJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXiBonBrxCAJYzIJU3OJ8HVnEXc5kcfQPhtzyMT1K/av8BqiXPnCcYKicGvEIOfw+E0GgR358xyNh4sRVfRnHVGhhcIAkIZn9ElYcGihoXPEQF6nXZ7CgInd1h7NVspIPFZNhkPL+vGFpTNwH3Eh9gwPM8pf1EPTHfPvjf14sS7xN7mTK+wrz7Odhp4rdWBNUASjdGhyAqF2AaN0eG6Lo2FtdM0D6KVjbG9zZcQgQOk0koglZMvOnFmmm2dUJonpocOiqepbZabopEIf/FejZmVlzQSYomZ2zTCyo2dlbqxkZXZuZXQtdjMzLjCiZ2jEICYLIAmgk6iGi3lYci+l5Ubt5+0X5NhcTHivsEUmkO3Somx2zTSapG5vdGXECF+AZeMEPawqo3JjdsQge2ziT+tbrMCxZOKcIixX9fY9w4fUOQSCWEEcX+EPfAKjc25kxCCNkrSJkAFzoE36Q1mjZmpq/OosQqBd2cH3PuulR4A36aR0eXBlo3BheQ==', - 'base64' + const o = algosdk.base64ToBytes( + 'gqRtc2lng6ZzdWJzaWeTgaJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXiBonBrxCAJYzIJU3OJ8HVnEXc5kcfQPhtzyMT1K/av8BqiXPnCcYKicGvEIOfw+E0GgR358xyNh4sRVfRnHVGhhcIAkIZn9ElYcGihoXPEQF6nXZ7CgInd1h7NVspIPFZNhkPL+vGFpTNwH3Eh9gwPM8pf1EPTHfPvjf14sS7xN7mTK+wrz7Odhp4rdWBNUASjdGhyAqF2AaN0eG6Lo2FtdM0D6KVjbG9zZcQgQOk0koglZMvOnFmmm2dUJonpocOiqepbZabopEIf/FejZmVlzQSYomZ2zTCyo2dlbqxkZXZuZXQtdjMzLjCiZ2jEICYLIAmgk6iGi3lYci+l5Ubt5+0X5NhcTHivsEUmkO3Somx2zTSapG5vdGXECF+AZeMEPawqo3JjdsQge2ziT+tbrMCxZOKcIixX9fY9w4fUOQSCWEEcX+EPfAKjc25kxCCNkrSJkAFzoE36Q1mjZmpq/OosQqBd2cH3PuulR4A36aR0eXBlo3BheQ==' ); const jsDec = algosdk.appendSignMultisigTransaction(o, params, sk); - const golden = Buffer.from( - 'gqRtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RAjmG2MILQVLoKg8q7jAYpu0r42zu9edYHrkkuSAikJAnDPplY1Pq90/ssyFhpKLrmvDDcSwNAwTGBjqtSOFYUAIGicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxgqJwa8Qg5/D4TQaBHfnzHI2HixFV9GcdUaGFwgCQhmf0SVhwaKGhc8RAXqddnsKAid3WHs1Wykg8Vk2GQ8v68YWlM3AfcSH2DA8zyl/UQ9Md8++N/XixLvE3uZMr7CvPs52Gnit1YE1QBKN0aHICoXYBo3R4boujYW10zQPopWNsb3NlxCBA6TSSiCVky86cWaabZ1Qmiemhw6Kp6ltlpuikQh/8V6NmZWXNBJiiZnbNMLKjZ2VurGRldm5ldC12MzMuMKJnaMQgJgsgCaCTqIaLeVhyL6XlRu3n7Rfk2FxMeK+wRSaQ7dKibHbNNJqkbm90ZcQIX4Bl4wQ9rCqjcmN2xCB7bOJP61uswLFk4pwiLFf19j3Dh9Q5BIJYQRxf4Q98AqNzbmTEII2StImQAXOgTfpDWaNmamr86ixCoF3Zwfc+66VHgDfppHR5cGWjcGF5', - 'base64' + const golden = algosdk.base64ToBytes( + 'gqRtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RAjmG2MILQVLoKg8q7jAYpu0r42zu9edYHrkkuSAikJAnDPplY1Pq90/ssyFhpKLrmvDDcSwNAwTGBjqtSOFYUAIGicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxgqJwa8Qg5/D4TQaBHfnzHI2HixFV9GcdUaGFwgCQhmf0SVhwaKGhc8RAXqddnsKAid3WHs1Wykg8Vk2GQ8v68YWlM3AfcSH2DA8zyl/UQ9Md8++N/XixLvE3uZMr7CvPs52Gnit1YE1QBKN0aHICoXYBo3R4boujYW10zQPopWNsb3NlxCBA6TSSiCVky86cWaabZ1Qmiemhw6Kp6ltlpuikQh/8V6NmZWXNBJiiZnbNMLKjZ2VurGRldm5ldC12MzMuMKJnaMQgJgsgCaCTqIaLeVhyL6XlRu3n7Rfk2FxMeK+wRSaQ7dKibHbNNJqkbm90ZcQIX4Bl4wQ9rCqjcmN2xCB7bOJP61uswLFk4pwiLFf19j3Dh9Q5BIJYQRxf4Q98AqNzbmTEII2StImQAXOgTfpDWaNmamr86ixCoF3Zwfc+66VHgDfppHR5cGWjcGF5' ); - assert.deepStrictEqual(Buffer.from(jsDec.blob), golden); + assert.deepStrictEqual(jsDec.blob, golden); // Check txid const txGolden = 'TDIO6RJWJIVDDJZELMSX5CPJW7MUNM3QR4YAHYAKHF3W2CFRTI7A'; @@ -515,7 +498,7 @@ describe('Algosdk (AKA end to end)', () => { const genesisID = 'devnet-v1.0'; const genesisHash = 'sC3P7e2SdbqKJK0tbiCdK9tdSpbe6XeCGKdoNzmlj0E'; const firstRound1 = 710399; - const note1 = new Uint8Array(Buffer.from('wRKw5cJ0CMo=', 'base64')); + const note1 = algosdk.base64ToBytes('wRKw5cJ0CMo='); const o1 = { to: toAddress, from: fromAddress, @@ -530,7 +513,7 @@ describe('Algosdk (AKA end to end)', () => { }; const firstRound2 = 710515; - const note2 = new Uint8Array(Buffer.from('dBlHI6BdrIg=', 'base64')); + const note2 = algosdk.base64ToBytes('dBlHI6BdrIg='); const o2 = { to: toAddress, @@ -554,14 +537,10 @@ describe('Algosdk (AKA end to end)', () => { const tx2 = new algosdk.Transaction(o2); // goal clerk send dumps unsigned transaction as signed with empty signature in order to save tx type - let stx1 = Buffer.from( - algosdk.encodeObj({ txn: tx1.get_obj_for_encoding() }) - ); - let stx2 = Buffer.from( - algosdk.encodeObj({ txn: tx2.get_obj_for_encoding() }) - ); - assert.deepStrictEqual(stx1, Buffer.from(goldenTx1, 'base64')); - assert.deepStrictEqual(stx2, Buffer.from(goldenTx2, 'base64')); + let stx1 = algosdk.encodeObj({ txn: tx1.get_obj_for_encoding() }); + let stx2 = algosdk.encodeObj({ txn: tx2.get_obj_for_encoding() }); + assert.deepStrictEqual(stx1, algosdk.base64ToBytes(goldenTx1)); + assert.deepStrictEqual(stx2, algosdk.base64ToBytes(goldenTx2)); // goal clerk group sets Group to every transaction and concatenate them in output file // simulating that behavior here @@ -573,8 +552,8 @@ describe('Algosdk (AKA end to end)', () => { tx2.group = gid; stx1 = algosdk.encodeObj({ txn: tx1.get_obj_for_encoding() }); stx2 = algosdk.encodeObj({ txn: tx2.get_obj_for_encoding() }); - const concat = Buffer.concat([stx1, stx2]); - assert.deepStrictEqual(concat, Buffer.from(goldenTxg, 'base64')); + const concat = utils.concatArrays(stx1, stx2); + assert.deepStrictEqual(concat, algosdk.base64ToBytes(goldenTxg)); } // check computeGroupID for list of dicts (not Transaction objects) @@ -584,8 +563,8 @@ describe('Algosdk (AKA end to end)', () => { tx2.group = gid; stx1 = algosdk.encodeObj({ txn: tx1.get_obj_for_encoding() }); stx2 = algosdk.encodeObj({ txn: tx2.get_obj_for_encoding() }); - const concat = Buffer.concat([stx1, stx2]); - assert.deepStrictEqual(concat, Buffer.from(goldenTxg, 'base64')); + const concat = utils.concatArrays(stx1, stx2); + assert.deepStrictEqual(concat, algosdk.base64ToBytes(goldenTxg)); } // check filtering by address in assignGroupID @@ -636,10 +615,7 @@ describe('Algosdk (AKA end to end)', () => { }; sk = algosdk.mnemonicToSecretKey(sk); const jsDecCreate = algosdk.signTransaction(createTxn, sk.sk); - assert.deepStrictEqual( - Buffer.from(jsDecCreate.blob), - Buffer.from(golden, 'base64') - ); + assert.deepStrictEqual(jsDecCreate.blob, algosdk.base64ToBytes(golden)); }); it('should return a blob that matches the go code for asset create with decimals', () => { @@ -670,10 +646,7 @@ describe('Algosdk (AKA end to end)', () => { }; sk = algosdk.mnemonicToSecretKey(sk); const jsDecCreate = algosdk.signTransaction(createTxn, sk.sk); - assert.deepStrictEqual( - Buffer.from(jsDecCreate.blob), - Buffer.from(golden, 'base64') - ); + assert.deepStrictEqual(jsDecCreate.blob, algosdk.base64ToBytes(golden)); }); it('should return a blob that matches the go code for asset configuration', () => { @@ -698,10 +671,7 @@ describe('Algosdk (AKA end to end)', () => { }; sk = algosdk.mnemonicToSecretKey(sk); const jsDec = algosdk.signTransaction(o, sk.sk); - assert.deepStrictEqual( - Buffer.from(jsDec.blob), - Buffer.from(golden, 'base64') - ); + assert.deepStrictEqual(jsDec.blob, algosdk.base64ToBytes(golden)); }); it('should return a blob that matches the go code for asset destroy', () => { @@ -722,10 +692,7 @@ describe('Algosdk (AKA end to end)', () => { }; sk = algosdk.mnemonicToSecretKey(sk); const jsDec = algosdk.signTransaction(o, sk.sk); - assert.deepStrictEqual( - Buffer.from(jsDec.blob), - Buffer.from(golden, 'base64') - ); + assert.deepStrictEqual(jsDec.blob, algosdk.base64ToBytes(golden)); }); it('should return a blob that matches the go code for asset freeze', () => { const addr = 'BH55E5RMBD4GYWXGX5W5PJ5JAHPGM5OXKDQH5DC4O2MGI7NW4H6VOE4CP4'; @@ -745,11 +712,10 @@ describe('Algosdk (AKA end to end)', () => { 'awful drop leaf tennis indoor begin mandate discover uncle seven only coil atom any hospital uncover make any climb actor armed measure need above hundred'; const { sk } = algosdk.mnemonicToSecretKey(mnem); const jsDec = algosdk.signTransaction(o, sk); - const golden = Buffer.from( - 'gqNzaWfEQAhru5V2Xvr19s4pGnI0aslqwY4lA2skzpYtDTAN9DKSH5+qsfQQhm4oq+9VHVj7e1rQC49S28vQZmzDTVnYDQGjdHhuiaRhZnJ6w6RmYWRkxCAJ+9J2LAj4bFrmv23Xp6kB3mZ111Dgfoxcdphkfbbh/aRmYWlkAaNmZWXNCRqiZnbOAATsD6JnaMQgSGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiKibHbOAATv+KNzbmTEIAn70nYsCPhsWua/bdenqQHeZnXXUOB+jFx2mGR9tuH9pHR5cGWkYWZyeg==', - 'base64' + const golden = algosdk.base64ToBytes( + 'gqNzaWfEQAhru5V2Xvr19s4pGnI0aslqwY4lA2skzpYtDTAN9DKSH5+qsfQQhm4oq+9VHVj7e1rQC49S28vQZmzDTVnYDQGjdHhuiaRhZnJ6w6RmYWRkxCAJ+9J2LAj4bFrmv23Xp6kB3mZ111Dgfoxcdphkfbbh/aRmYWlkAaNmZWXNCRqiZnbOAATsD6JnaMQgSGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiKibHbOAATv+KNzbmTEIAn70nYsCPhsWua/bdenqQHeZnXXUOB+jFx2mGR9tuH9pHR5cGWkYWZyeg==' ); - assert.deepStrictEqual(Buffer.from(jsDec.blob), golden); + assert.deepStrictEqual(jsDec.blob, golden); }); it('should return a blob that matches the go code for asset transfer', () => { const addr = 'BH55E5RMBD4GYWXGX5W5PJ5JAHPGM5OXKDQH5DC4O2MGI7NW4H6VOE4CP4'; @@ -771,11 +737,10 @@ describe('Algosdk (AKA end to end)', () => { 'awful drop leaf tennis indoor begin mandate discover uncle seven only coil atom any hospital uncover make any climb actor armed measure need above hundred'; const { sk } = algosdk.mnemonicToSecretKey(mnem); const jsDec = algosdk.signTransaction(o, sk); - const golden = Buffer.from( - 'gqNzaWfEQNkEs3WdfFq6IQKJdF1n0/hbV9waLsvojy9pM1T4fvwfMNdjGQDy+LeesuQUfQVTneJD4VfMP7zKx4OUlItbrwSjdHhuiqRhYW10AaZhY2xvc2XEIAn70nYsCPhsWua/bdenqQHeZnXXUOB+jFx2mGR9tuH9pGFyY3bEIAn70nYsCPhsWua/bdenqQHeZnXXUOB+jFx2mGR9tuH9o2ZlZc0KvqJmds4ABOwPomdoxCBIY7UYpLPITsgQ8i1PEIHLD3HwWaesIN7GL39w5Qk6IqJsds4ABO/4o3NuZMQgCfvSdiwI+Gxa5r9t16epAd5mdddQ4H6MXHaYZH224f2kdHlwZaVheGZlcqR4YWlkAQ==', - 'base64' + const golden = algosdk.base64ToBytes( + 'gqNzaWfEQNkEs3WdfFq6IQKJdF1n0/hbV9waLsvojy9pM1T4fvwfMNdjGQDy+LeesuQUfQVTneJD4VfMP7zKx4OUlItbrwSjdHhuiqRhYW10AaZhY2xvc2XEIAn70nYsCPhsWua/bdenqQHeZnXXUOB+jFx2mGR9tuH9pGFyY3bEIAn70nYsCPhsWua/bdenqQHeZnXXUOB+jFx2mGR9tuH9o2ZlZc0KvqJmds4ABOwPomdoxCBIY7UYpLPITsgQ8i1PEIHLD3HwWaesIN7GL39w5Qk6IqJsds4ABO/4o3NuZMQgCfvSdiwI+Gxa5r9t16epAd5mdddQ4H6MXHaYZH224f2kdHlwZaVheGZlcqR4YWlkAQ==' ); - assert.deepStrictEqual(Buffer.from(jsDec.blob), golden); + assert.deepStrictEqual(jsDec.blob, golden); }); it('should return a blob that matches the go code for asset accept', () => { const addr = 'BH55E5RMBD4GYWXGX5W5PJ5JAHPGM5OXKDQH5DC4O2MGI7NW4H6VOE4CP4'; @@ -796,11 +761,10 @@ describe('Algosdk (AKA end to end)', () => { 'awful drop leaf tennis indoor begin mandate discover uncle seven only coil atom any hospital uncover make any climb actor armed measure need above hundred'; const { sk } = algosdk.mnemonicToSecretKey(mnem); const jsDec = algosdk.signTransaction(o, sk); - const golden = Buffer.from( - 'gqNzaWfEQJ7q2rOT8Sb/wB0F87ld+1zMprxVlYqbUbe+oz0WM63FctIi+K9eYFSqT26XBZ4Rr3+VTJpBE+JLKs8nctl9hgijdHhuiKRhcmN2xCAJ+9J2LAj4bFrmv23Xp6kB3mZ111Dgfoxcdphkfbbh/aNmZWXNCOiiZnbOAATsD6JnaMQgSGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiKibHbOAATv96NzbmTEIAn70nYsCPhsWua/bdenqQHeZnXXUOB+jFx2mGR9tuH9pHR5cGWlYXhmZXKkeGFpZAE=', - 'base64' + const golden = algosdk.base64ToBytes( + 'gqNzaWfEQJ7q2rOT8Sb/wB0F87ld+1zMprxVlYqbUbe+oz0WM63FctIi+K9eYFSqT26XBZ4Rr3+VTJpBE+JLKs8nctl9hgijdHhuiKRhcmN2xCAJ+9J2LAj4bFrmv23Xp6kB3mZ111Dgfoxcdphkfbbh/aNmZWXNCOiiZnbOAATsD6JnaMQgSGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiKibHbOAATv96NzbmTEIAn70nYsCPhsWua/bdenqQHeZnXXUOB+jFx2mGR9tuH9pHR5cGWlYXhmZXKkeGFpZAE=' ); - assert.deepStrictEqual(Buffer.from(jsDec.blob), golden); + assert.deepStrictEqual(jsDec.blob, golden); }); it('should return a blob that matches the go code for asset revoke', () => { const addr = 'BH55E5RMBD4GYWXGX5W5PJ5JAHPGM5OXKDQH5DC4O2MGI7NW4H6VOE4CP4'; @@ -822,11 +786,10 @@ describe('Algosdk (AKA end to end)', () => { 'awful drop leaf tennis indoor begin mandate discover uncle seven only coil atom any hospital uncover make any climb actor armed measure need above hundred'; const { sk } = algosdk.mnemonicToSecretKey(mnem); const jsDec = algosdk.signTransaction(o, sk); - const golden = Buffer.from( - 'gqNzaWfEQHsgfEAmEHUxLLLR9s+Y/yq5WeoGo/jAArCbany+7ZYwExMySzAhmV7M7S8+LBtJalB4EhzEUMKmt3kNKk6+vAWjdHhuiqRhYW10AaRhcmN2xCAJ+9J2LAj4bFrmv23Xp6kB3mZ111Dgfoxcdphkfbbh/aRhc25kxCAJ+9J2LAj4bFrmv23Xp6kB3mZ111Dgfoxcdphkfbbh/aNmZWXNCqqiZnbOAATsD6JnaMQgSGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiKibHbOAATv96NzbmTEIAn70nYsCPhsWua/bdenqQHeZnXXUOB+jFx2mGR9tuH9pHR5cGWlYXhmZXKkeGFpZAE=', - 'base64' + const golden = algosdk.base64ToBytes( + 'gqNzaWfEQHsgfEAmEHUxLLLR9s+Y/yq5WeoGo/jAArCbany+7ZYwExMySzAhmV7M7S8+LBtJalB4EhzEUMKmt3kNKk6+vAWjdHhuiqRhYW10AaRhcmN2xCAJ+9J2LAj4bFrmv23Xp6kB3mZ111Dgfoxcdphkfbbh/aRhc25kxCAJ+9J2LAj4bFrmv23Xp6kB3mZ111Dgfoxcdphkfbbh/aNmZWXNCqqiZnbOAATsD6JnaMQgSGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiKibHbOAATv96NzbmTEIAn70nYsCPhsWua/bdenqQHeZnXXUOB+jFx2mGR9tuH9pHR5cGWlYXhmZXKkeGFpZAE=' ); - assert.deepStrictEqual(Buffer.from(jsDec.blob), golden); + assert.deepStrictEqual(jsDec.blob, golden); }); }); @@ -926,7 +889,7 @@ describe('Algosdk (AKA end to end)', () => { const firstRound = 2063137; const genesisID = 'devnet-v1.0'; const genesisHash = 'sC3P7e2SdbqKJK0tbiCdK9tdSpbe6XeCGKdoNzmlj0E='; - const note = new Uint8Array(Buffer.from('8xMCTuLQ810=', 'base64')); + const note = algosdk.base64ToBytes('8xMCTuLQ810='); const txn = { to: toAddress, @@ -958,10 +921,7 @@ describe('Algosdk (AKA end to end)', () => { const golden = 'gqRsc2lng6NhcmeSxAMxMjPEAzQ1NqFsxAUBIAEBIqNzaWfEQE6HXaI5K0lcq50o/y3bWOYsyw9TLi/oorZB4xaNdn1Z14351u2f6JTON478fl+JhIP4HNRRAIh/I8EWXBPpJQ2jdHhuiqNhbXTNB9CjZmVlzQPoomZ2zgAfeyGjZ2Vuq2Rldm5ldC12MS4womdoxCCwLc/t7ZJ1uookrS1uIJ0r211Klt7pd4IYp2g3OaWPQaJsds4AH38JpG5vdGXECPMTAk7i0PNdo3JjdsQge2ziT+tbrMCxZOKcIixX9fY9w4fUOQSCWEEcX+EPfAKjc25kxCDn8PhNBoEd+fMcjYeLEVX0Zx1RoYXCAJCGZ/RJWHBooaR0eXBlo3BheQ=='; - assert.deepStrictEqual( - Buffer.from(jsDec.blob), - Buffer.from(golden, 'base64') - ); + assert.deepStrictEqual(jsDec.blob, algosdk.base64ToBytes(golden)); const senderPk = algosdk.decodeAddress(fromAddress).publicKey; const verified = lsig.verify(senderPk); assert.equal(verified, true); @@ -969,13 +929,12 @@ describe('Algosdk (AKA end to end)', () => { }); describe('tealSign', () => { - const data = Buffer.from('Ux8jntyBJQarjKGF8A==', 'base64'); - const prog = Buffer.from('ASABASI=', 'base64'); + const data = algosdk.base64ToBytes('Ux8jntyBJQarjKGF8A=='); + const prog = algosdk.base64ToBytes('ASABASI='); const addr = new algosdk.LogicSig(prog).address(); - const seed = Buffer.from( - '5Pf7eGMA52qfMT4R4/vYCt7con/7U3yejkdXkrcb26Q=', - 'base64' + const seed = algosdk.base64ToBytes( + '5Pf7eGMA52qfMT4R4/vYCt7con/7U3yejkdXkrcb26Q=' ); const { publicKey: pk, secretKey: sk } = nacl.keyPairFromSeed(seed); @@ -986,8 +945,9 @@ describe('Algosdk (AKA end to end)', () => { algosdk.decodeAddress(addr).publicKey, data ); - const toBeVerified = Buffer.from( - utils.concatArrays(Buffer.from('ProgData'), parts) + const toBeVerified = utils.concatArrays( + new TextEncoder().encode('ProgData'), + parts ); const verified = nacl.verify(toBeVerified, sig, pk); assert.equal(verified, true); @@ -1059,7 +1019,7 @@ describe('Algosdk (AKA end to end)', () => { const golden = 'ewogICJhY2NvdW50cyI6IFsKICAgIHsKICAgICAgImFkZHJlc3MiOiAiVUFQSkUzNTVLN0JHN1JRVk1UWk9XN1FXNElDWkpFSUMzUlpHWUc1TFNIWjY1SzZMQ05GUEpEU1I3TSIsCiAgICAgICJhbW91bnQiOiA1MDAyMjgwMDAwMDAwMDAwLAogICAgICAiYW1vdW50LXdpdGhvdXQtcGVuZGluZy1yZXdhcmRzIjogNTAwMDAwMDAwMDAwMDAwMCwKICAgICAgInBlbmRpbmctcmV3YXJkcyI6IDIyODAwMDAwMDAwMDAsCiAgICAgICJyZXdhcmQtYmFzZSI6IDQ1NiwKICAgICAgInJld2FyZHMiOiAyMjgwMDAwMDAwMDAwLAogICAgICAicm91bmQiOiAxODI0MSwKICAgICAgInN0YXR1cyI6ICJPbmxpbmUiCiAgICB9CiAgXSwKICAiYXBwcyI6IFsKICAgIHsKICAgICAgImlkIjogMTM4MDAxMTU4OCwKICAgICAgInBhcmFtcyI6IHsKICAgICAgICAiY3JlYXRvciI6ICJVQVBKRTM1NUs3Qkc3UlFWTVRaT1c3UVc0SUNaSkVJQzNSWkdZRzVMU0haNjVLNkxDTkZQSkRTUjdNIiwKICAgICAgICAiYXBwcm92YWwtcHJvZ3JhbSI6ICJBaUFCQVNJPSIsCiAgICAgICAgImNsZWFyLXN0YXRlLXByb2dyYW0iOiAiQWlBQkFTST0iLAogICAgICAgICJnbG9iYWwtc3RhdGUtc2NoZW1hIjogewogICAgICAgICAgIm51bS1ieXRlLXNsaWNlIjogNSwKICAgICAgICAgICJudW0tdWludCI6IDUKICAgICAgICB9LAogICAgICAgICJsb2NhbC1zdGF0ZS1zY2hlbWEiOiB7CiAgICAgICAgICAibnVtLWJ5dGUtc2xpY2UiOiA1LAogICAgICAgICAgIm51bS11aW50IjogNQogICAgICAgIH0KICAgICAgfQogICAgfQogIF0sCiAgImxhdGVzdC10aW1lc3RhbXAiOiAxNTkyNTM3NzU3LAogICJwcm90b2NvbC12ZXJzaW9uIjogImZ1dHVyZSIsCiAgInJvdW5kIjogMTgyNDEsCiAgInR4bnMiOiBbCiAgICB7CiAgICAgICJ0eG4iOiB7CiAgICAgICAgImFwc3UiOiAiQWlBQkFTST0iLAogICAgICAgICJmZWUiOiAxMDAwLAogICAgICAgICJmdiI6IDE4MjQyLAogICAgICAgICJnaCI6ICJaSWtQczhwVER4YlJKc0ZCMXlKN2d2bnBEdTBRODVGUmtsMk5Da0VBUUxVPSIsCiAgICAgICAgImx2IjogMTkyNDIsCiAgICAgICAgIm5vdGUiOiAidGpwTmdlNzhKRDg9IiwKICAgICAgICAic25kIjogIlVBUEpFMzU1SzdCRzdSUVZNVFpPVzdRVzRJQ1pKRUlDM1JaR1lHNUxTSFo2NUs2TENORlBKRFNSN00iLAogICAgICAgICJ0eXBlIjogImFwcGwiCiAgICAgIH0KICAgIH0KICBdCn0K'; - const goldenString = Buffer.from(golden, 'base64').toString('utf8'); + const goldenString = algosdk.base64ToString(golden, 'base64'); const expected = JSON.parse(goldenString); assert.deepStrictEqual(actual, expected); @@ -1069,7 +1029,7 @@ describe('Algosdk (AKA end to end)', () => { const actual = req.get_obj_for_encoding(true); const golden = 'hqhhY2NvdW50c5GIp2FkZHJlc3PZOlVBUEpFMzU1SzdCRzdSUVZNVFpPVzdRVzRJQ1pKRUlDM1JaR1lHNUxTSFo2NUs2TENORlBKRFNSN02mYW1vdW50zwARxYwSd5AAvmFtb3VudC13aXRob3V0LXBlbmRpbmctcmV3YXJkc88AEcN5N+CAAK9wZW5kaW5nLXJld2FyZHPPAAACEtqXEACrcmV3YXJkLWJhc2XNAcincmV3YXJkc88AAAIS2pcQAKVyb3VuZM1HQaZzdGF0dXOmT25saW5lpGFwcHORgqJpZM5SQU5EpnBhcmFtc4WwYXBwcm92YWwtcHJvZ3JhbcQFAiABASKzY2xlYXItc3RhdGUtcHJvZ3JhbcQFAiABASKnY3JlYXRvctk6VUFQSkUzNTVLN0JHN1JRVk1UWk9XN1FXNElDWkpFSUMzUlpHWUc1TFNIWjY1SzZMQ05GUEpEU1I3TbNnbG9iYWwtc3RhdGUtc2NoZW1hgq5udW0tYnl0ZS1zbGljZQWobnVtLXVpbnQFsmxvY2FsLXN0YXRlLXNjaGVtYYKubnVtLWJ5dGUtc2xpY2UFqG51bS11aW50BbBsYXRlc3QtdGltZXN0YW1wzl7sMp2wcHJvdG9jb2wtdmVyc2lvbqZmdXR1cmWlcm91bmTNR0GkdHhuc5GBo3R4boikYXBzdahBaUFCQVNJPaNmZWXNA+iiZnbNR0KiZ2jZLFpJa1BzOHBURHhiUkpzRkIxeUo3Z3ZucER1MFE4NUZSa2wyTkNrRUFRTFU9omx2zUsqpG5vdGWsdGpwTmdlNzhKRDg9o3NuZNk6VUFQSkUzNTVLN0JHN1JRVk1UWk9XN1FXNElDWkpFSUMzUlpHWUc1TFNIWjY1SzZMQ05GUEpEU1I3TaR0eXBlpGFwcGw='; - const goldenBinary = new Uint8Array(Buffer.from(golden, 'base64')); + const goldenBinary = new Uint8Array(algosdk.base64ToBytes(golden)); const expected = algosdk.decodeObj(goldenBinary); assert.deepStrictEqual(actual, expected); diff --git a/tests/8.LogicSig.ts b/tests/8.LogicSig.ts index f9c38a33a..8b2c4cdb3 100644 --- a/tests/8.LogicSig.ts +++ b/tests/8.LogicSig.ts @@ -1,5 +1,4 @@ /* eslint-env mocha */ -import { Buffer } from 'buffer'; import assert from 'assert'; import algosdk from '../src/index'; @@ -96,7 +95,7 @@ describe('LogicSigAccount', () => { // check serialization const encoded = lsigAccount.toByte(); const expectedEncoded = new Uint8Array( - Buffer.from('gaRsc2lngaFsxAUBIAEBIg==', 'base64') + algosdk.base64ToBytes('gaRsc2lngaFsxAUBIAEBIg==') ); assert.deepStrictEqual(encoded, expectedEncoded); @@ -117,7 +116,7 @@ describe('LogicSigAccount', () => { // check serialization const encoded = lsigAccount.toByte(); const expectedEncoded = new Uint8Array( - Buffer.from('gaRsc2lngqNhcmeSxAEBxAICA6FsxAUBIAEBIg==', 'base64') + algosdk.base64ToBytes('gaRsc2lngqNhcmeSxAEBxAICA6FsxAUBIAEBIg==') ); assert.deepStrictEqual(encoded, expectedEncoded); @@ -135,9 +134,8 @@ describe('LogicSigAccount', () => { lsigAccount.sign(sampleAccount1.sk); const expectedSig = new Uint8Array( - Buffer.from( - 'SRO4BdGefywQgPYzfhhUp87q7hDdvRNlhL+Tt18wYxWRyiMM7e8j0XQbUp2w/+83VNZG9LVh/Iu8LXtOY1y9Ag==', - 'base64' + algosdk.base64ToBytes( + 'SRO4BdGefywQgPYzfhhUp87q7hDdvRNlhL+Tt18wYxWRyiMM7e8j0XQbUp2w/+83VNZG9LVh/Iu8LXtOY1y9Ag==' ) ); const expectedSigKey = algosdk.decodeAddress(sampleAccount1.addr) @@ -152,9 +150,8 @@ describe('LogicSigAccount', () => { // check serialization const encoded = lsigAccount.toByte(); const expectedEncoded = new Uint8Array( - Buffer.from( - 'gqRsc2lng6NhcmeSxAEBxAICA6FsxAUBIAEBIqNzaWfEQEkTuAXRnn8sEID2M34YVKfO6u4Q3b0TZYS/k7dfMGMVkcojDO3vI9F0G1KdsP/vN1TWRvS1YfyLvC17TmNcvQKmc2lna2V5xCAbfsCwS+pht5aQl+bL9AfhCKcFNR0LyYq+sSIJqKuBeA==', - 'base64' + algosdk.base64ToBytes( + 'gqRsc2lng6NhcmeSxAEBxAICA6FsxAUBIAEBIqNzaWfEQEkTuAXRnn8sEID2M34YVKfO6u4Q3b0TZYS/k7dfMGMVkcojDO3vI9F0G1KdsP/vN1TWRvS1YfyLvC17TmNcvQKmc2lna2V5xCAbfsCwS+pht5aQl+bL9AfhCKcFNR0LyYq+sSIJqKuBeA==' ) ); assert.deepStrictEqual(encoded, expectedEncoded); @@ -173,9 +170,8 @@ describe('LogicSigAccount', () => { lsigAccount.signMultisig(sampleMultisigParams, sampleAccount1.sk); const expectedSig = new Uint8Array( - Buffer.from( - 'SRO4BdGefywQgPYzfhhUp87q7hDdvRNlhL+Tt18wYxWRyiMM7e8j0XQbUp2w/+83VNZG9LVh/Iu8LXtOY1y9Ag==', - 'base64' + algosdk.base64ToBytes( + 'SRO4BdGefywQgPYzfhhUp87q7hDdvRNlhL+Tt18wYxWRyiMM7e8j0XQbUp2w/+83VNZG9LVh/Iu8LXtOY1y9Ag==' ) ); const expectedMsig: algosdk.EncodedMultisig = { @@ -196,9 +192,8 @@ describe('LogicSigAccount', () => { // check serialization const encoded = lsigAccount.toByte(); const expectedEncoded = new Uint8Array( - Buffer.from( - 'gaRsc2lng6NhcmeSxAEBxAICA6FsxAUBIAEBIqRtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RASRO4BdGefywQgPYzfhhUp87q7hDdvRNlhL+Tt18wYxWRyiMM7e8j0XQbUp2w/+83VNZG9LVh/Iu8LXtOY1y9AoGicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxgaJwa8Qg5/D4TQaBHfnzHI2HixFV9GcdUaGFwgCQhmf0SVhwaKGjdGhyAqF2AQ==', - 'base64' + algosdk.base64ToBytes( + 'gaRsc2lng6NhcmeSxAEBxAICA6FsxAUBIAEBIqRtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RASRO4BdGefywQgPYzfhhUp87q7hDdvRNlhL+Tt18wYxWRyiMM7e8j0XQbUp2w/+83VNZG9LVh/Iu8LXtOY1y9AoGicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxgaJwa8Qg5/D4TQaBHfnzHI2HixFV9GcdUaGFwgCQhmf0SVhwaKGjdGhyAqF2AQ==' ) ); assert.deepStrictEqual(encoded, expectedEncoded); @@ -211,9 +206,8 @@ describe('LogicSigAccount', () => { describe('appendToMultisig', () => { it('should properly append a signature', () => { const msig1of3Encoded = new Uint8Array( - Buffer.from( - 'gaRsc2lng6NhcmeSxAEBxAICA6FsxAUBIAEBIqRtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RASRO4BdGefywQgPYzfhhUp87q7hDdvRNlhL+Tt18wYxWRyiMM7e8j0XQbUp2w/+83VNZG9LVh/Iu8LXtOY1y9AoGicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxgaJwa8Qg5/D4TQaBHfnzHI2HixFV9GcdUaGFwgCQhmf0SVhwaKGjdGhyAqF2AQ==', - 'base64' + algosdk.base64ToBytes( + 'gaRsc2lng6NhcmeSxAEBxAICA6FsxAUBIAEBIqRtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RASRO4BdGefywQgPYzfhhUp87q7hDdvRNlhL+Tt18wYxWRyiMM7e8j0XQbUp2w/+83VNZG9LVh/Iu8LXtOY1y9AoGicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxgaJwa8Qg5/D4TQaBHfnzHI2HixFV9GcdUaGFwgCQhmf0SVhwaKGjdGhyAqF2AQ==' ) ); const lsigAccount = algosdk.LogicSigAccount.fromByte(msig1of3Encoded); @@ -221,15 +215,13 @@ describe('LogicSigAccount', () => { lsigAccount.appendToMultisig(sampleAccount2.sk); const expectedSig1 = new Uint8Array( - Buffer.from( - 'SRO4BdGefywQgPYzfhhUp87q7hDdvRNlhL+Tt18wYxWRyiMM7e8j0XQbUp2w/+83VNZG9LVh/Iu8LXtOY1y9Ag==', - 'base64' + algosdk.base64ToBytes( + 'SRO4BdGefywQgPYzfhhUp87q7hDdvRNlhL+Tt18wYxWRyiMM7e8j0XQbUp2w/+83VNZG9LVh/Iu8LXtOY1y9Ag==' ) ); const expectedSig2 = new Uint8Array( - Buffer.from( - 'ZLxV2+2RokHUKrZg9+FKuZmaUrOxcVjO/D9P58siQRStqT1ehAUCChemaYMDIk6Go4tqNsVUviBQ/9PuqLMECQ==', - 'base64' + algosdk.base64ToBytes( + 'ZLxV2+2RokHUKrZg9+FKuZmaUrOxcVjO/D9P58siQRStqT1ehAUCChemaYMDIk6Go4tqNsVUviBQ/9PuqLMECQ==' ) ); const expectedMsig: algosdk.EncodedMultisig = { @@ -249,9 +241,8 @@ describe('LogicSigAccount', () => { // check serialization const encoded = lsigAccount.toByte(); const expectedEncoded = new Uint8Array( - Buffer.from( - 'gaRsc2lng6NhcmeSxAEBxAICA6FsxAUBIAEBIqRtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RASRO4BdGefywQgPYzfhhUp87q7hDdvRNlhL+Tt18wYxWRyiMM7e8j0XQbUp2w/+83VNZG9LVh/Iu8LXtOY1y9AoKicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxoXPEQGS8VdvtkaJB1Cq2YPfhSrmZmlKzsXFYzvw/T+fLIkEUrak9XoQFAgoXpmmDAyJOhqOLajbFVL4gUP/T7qizBAmBonBrxCDn8PhNBoEd+fMcjYeLEVX0Zx1RoYXCAJCGZ/RJWHBooaN0aHICoXYB', - 'base64' + algosdk.base64ToBytes( + 'gaRsc2lng6NhcmeSxAEBxAICA6FsxAUBIAEBIqRtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RASRO4BdGefywQgPYzfhhUp87q7hDdvRNlhL+Tt18wYxWRyiMM7e8j0XQbUp2w/+83VNZG9LVh/Iu8LXtOY1y9AoKicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxoXPEQGS8VdvtkaJB1Cq2YPfhSrmZmlKzsXFYzvw/T+fLIkEUrak9XoQFAgoXpmmDAyJOhqOLajbFVL4gUP/T7qizBAmBonBrxCDn8PhNBoEd+fMcjYeLEVX0Zx1RoYXCAJCGZ/RJWHBooaN0aHICoXYB' ) ); assert.deepStrictEqual(encoded, expectedEncoded); @@ -264,7 +255,7 @@ describe('LogicSigAccount', () => { describe('verify', () => { it('should verify valid escrow', () => { const escrowEncoded = new Uint8Array( - Buffer.from('gaRsc2lngqNhcmeSxAEBxAICA6FsxAUBIAEBIg==', 'base64') + algosdk.base64ToBytes('gaRsc2lngqNhcmeSxAEBxAICA6FsxAUBIAEBIg==') ); const lsigAccount = algosdk.LogicSigAccount.fromByte(escrowEncoded); @@ -273,9 +264,8 @@ describe('LogicSigAccount', () => { it('should verify valid single sig', () => { const sigEncoded = new Uint8Array( - Buffer.from( - 'gqRsc2lng6NhcmeSxAEBxAICA6FsxAUBIAEBIqNzaWfEQEkTuAXRnn8sEID2M34YVKfO6u4Q3b0TZYS/k7dfMGMVkcojDO3vI9F0G1KdsP/vN1TWRvS1YfyLvC17TmNcvQKmc2lna2V5xCAbfsCwS+pht5aQl+bL9AfhCKcFNR0LyYq+sSIJqKuBeA==', - 'base64' + algosdk.base64ToBytes( + 'gqRsc2lng6NhcmeSxAEBxAICA6FsxAUBIAEBIqNzaWfEQEkTuAXRnn8sEID2M34YVKfO6u4Q3b0TZYS/k7dfMGMVkcojDO3vI9F0G1KdsP/vN1TWRvS1YfyLvC17TmNcvQKmc2lna2V5xCAbfsCwS+pht5aQl+bL9AfhCKcFNR0LyYq+sSIJqKuBeA==' ) ); const lsigAccount = algosdk.LogicSigAccount.fromByte(sigEncoded); @@ -285,9 +275,8 @@ describe('LogicSigAccount', () => { it('should fail single sig with wrong sig', () => { const sigEncoded = new Uint8Array( - Buffer.from( - 'gqRsc2lng6NhcmeSxAEBxAICA6FsxAUBIAEBIqNzaWfEQEkTuAXRnn8sEID2M34YVKfO6u4Q3b0TZYS/k7dfMGMVkcojDO3vI9F0G1KdsP/vN1TWRvS1YfyLvC17TmNcvQKmc2lna2V5xCAbfsCwS+pht5aQl+bL9AfhCKcFNR0LyYq+sSIJqKuBeA==', - 'base64' + algosdk.base64ToBytes( + 'gqRsc2lng6NhcmeSxAEBxAICA6FsxAUBIAEBIqNzaWfEQEkTuAXRnn8sEID2M34YVKfO6u4Q3b0TZYS/k7dfMGMVkcojDO3vI9F0G1KdsP/vN1TWRvS1YfyLvC17TmNcvQKmc2lna2V5xCAbfsCwS+pht5aQl+bL9AfhCKcFNR0LyYq+sSIJqKuBeA==' ) ); const lsigAccount = algosdk.LogicSigAccount.fromByte(sigEncoded); @@ -300,9 +289,8 @@ describe('LogicSigAccount', () => { it('should verify valid multisig', () => { const msigEncoded = new Uint8Array( - Buffer.from( - 'gaRsc2lng6NhcmeSxAEBxAICA6FsxAUBIAEBIqRtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RASRO4BdGefywQgPYzfhhUp87q7hDdvRNlhL+Tt18wYxWRyiMM7e8j0XQbUp2w/+83VNZG9LVh/Iu8LXtOY1y9AoKicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxoXPEQGS8VdvtkaJB1Cq2YPfhSrmZmlKzsXFYzvw/T+fLIkEUrak9XoQFAgoXpmmDAyJOhqOLajbFVL4gUP/T7qizBAmBonBrxCDn8PhNBoEd+fMcjYeLEVX0Zx1RoYXCAJCGZ/RJWHBooaN0aHICoXYB', - 'base64' + algosdk.base64ToBytes( + 'gaRsc2lng6NhcmeSxAEBxAICA6FsxAUBIAEBIqRtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RASRO4BdGefywQgPYzfhhUp87q7hDdvRNlhL+Tt18wYxWRyiMM7e8j0XQbUp2w/+83VNZG9LVh/Iu8LXtOY1y9AoKicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxoXPEQGS8VdvtkaJB1Cq2YPfhSrmZmlKzsXFYzvw/T+fLIkEUrak9XoQFAgoXpmmDAyJOhqOLajbFVL4gUP/T7qizBAmBonBrxCDn8PhNBoEd+fMcjYeLEVX0Zx1RoYXCAJCGZ/RJWHBooaN0aHICoXYB' ) ); const lsigAccount = algosdk.LogicSigAccount.fromByte(msigEncoded); @@ -312,9 +300,8 @@ describe('LogicSigAccount', () => { it('should fail multisig with wrong sig', () => { const msigEncoded = new Uint8Array( - Buffer.from( - 'gaRsc2lng6NhcmeSxAEBxAICA6FsxAUBIAEBIqRtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RASRO4BdGefywQgPYzfhhUp87q7hDdvRNlhL+Tt18wYxWRyiMM7e8j0XQbUp2w/+83VNZG9LVh/Iu8LXtOY1y9AoKicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxoXPEQGS8VdvtkaJB1Cq2YPfhSrmZmlKzsXFYzvw/T+fLIkEUrak9XoQFAgoXpmmDAyJOhqOLajbFVL4gUP/T7qizBAmBonBrxCDn8PhNBoEd+fMcjYeLEVX0Zx1RoYXCAJCGZ/RJWHBooaN0aHICoXYB', - 'base64' + algosdk.base64ToBytes( + 'gaRsc2lng6NhcmeSxAEBxAICA6FsxAUBIAEBIqRtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RASRO4BdGefywQgPYzfhhUp87q7hDdvRNlhL+Tt18wYxWRyiMM7e8j0XQbUp2w/+83VNZG9LVh/Iu8LXtOY1y9AoKicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxoXPEQGS8VdvtkaJB1Cq2YPfhSrmZmlKzsXFYzvw/T+fLIkEUrak9XoQFAgoXpmmDAyJOhqOLajbFVL4gUP/T7qizBAmBonBrxCDn8PhNBoEd+fMcjYeLEVX0Zx1RoYXCAJCGZ/RJWHBooaN0aHICoXYB' ) ); const lsigAccount = algosdk.LogicSigAccount.fromByte(msigEncoded); @@ -327,9 +314,8 @@ describe('LogicSigAccount', () => { it('should fail multisig that does not meet threshold', () => { const msigBelowThresholdEncoded = new Uint8Array( - Buffer.from( - 'gaRsc2lng6NhcmeSxAEBxAICA6FsxAUBIAEBIqRtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RASRO4BdGefywQgPYzfhhUp87q7hDdvRNlhL+Tt18wYxWRyiMM7e8j0XQbUp2w/+83VNZG9LVh/Iu8LXtOY1y9AoGicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxgaJwa8Qg5/D4TQaBHfnzHI2HixFV9GcdUaGFwgCQhmf0SVhwaKGjdGhyAqF2AQ==', - 'base64' + algosdk.base64ToBytes( + 'gaRsc2lng6NhcmeSxAEBxAICA6FsxAUBIAEBIqRtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RASRO4BdGefywQgPYzfhhUp87q7hDdvRNlhL+Tt18wYxWRyiMM7e8j0XQbUp2w/+83VNZG9LVh/Iu8LXtOY1y9AoGicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxgaJwa8Qg5/D4TQaBHfnzHI2HixFV9GcdUaGFwgCQhmf0SVhwaKGjdGhyAqF2AQ==' ) ); const lsigAccount = algosdk.LogicSigAccount.fromByte( @@ -343,7 +329,7 @@ describe('LogicSigAccount', () => { describe('isDelegated', () => { it('should be correct for escrow', () => { const escrowEncoded = new Uint8Array( - Buffer.from('gaRsc2lngqNhcmeSxAEBxAICA6FsxAUBIAEBIg==', 'base64') + algosdk.base64ToBytes('gaRsc2lngqNhcmeSxAEBxAICA6FsxAUBIAEBIg==') ); const lsigAccount = algosdk.LogicSigAccount.fromByte(escrowEncoded); @@ -352,9 +338,8 @@ describe('LogicSigAccount', () => { it('should be correct for single sig', () => { const sigEncoded = new Uint8Array( - Buffer.from( - 'gqRsc2lng6NhcmeSxAEBxAICA6FsxAUBIAEBIqNzaWfEQEkTuAXRnn8sEID2M34YVKfO6u4Q3b0TZYS/k7dfMGMVkcojDO3vI9F0G1KdsP/vN1TWRvS1YfyLvC17TmNcvQKmc2lna2V5xCAbfsCwS+pht5aQl+bL9AfhCKcFNR0LyYq+sSIJqKuBeA==', - 'base64' + algosdk.base64ToBytes( + 'gqRsc2lng6NhcmeSxAEBxAICA6FsxAUBIAEBIqNzaWfEQEkTuAXRnn8sEID2M34YVKfO6u4Q3b0TZYS/k7dfMGMVkcojDO3vI9F0G1KdsP/vN1TWRvS1YfyLvC17TmNcvQKmc2lna2V5xCAbfsCwS+pht5aQl+bL9AfhCKcFNR0LyYq+sSIJqKuBeA==' ) ); const lsigAccount = algosdk.LogicSigAccount.fromByte(sigEncoded); @@ -364,9 +349,8 @@ describe('LogicSigAccount', () => { it('should be correct for multisig', () => { const msigEncoded = new Uint8Array( - Buffer.from( - 'gaRsc2lng6NhcmeSxAEBxAICA6FsxAUBIAEBIqRtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RASRO4BdGefywQgPYzfhhUp87q7hDdvRNlhL+Tt18wYxWRyiMM7e8j0XQbUp2w/+83VNZG9LVh/Iu8LXtOY1y9AoKicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxoXPEQGS8VdvtkaJB1Cq2YPfhSrmZmlKzsXFYzvw/T+fLIkEUrak9XoQFAgoXpmmDAyJOhqOLajbFVL4gUP/T7qizBAmBonBrxCDn8PhNBoEd+fMcjYeLEVX0Zx1RoYXCAJCGZ/RJWHBooaN0aHICoXYB', - 'base64' + algosdk.base64ToBytes( + 'gaRsc2lng6NhcmeSxAEBxAICA6FsxAUBIAEBIqRtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RASRO4BdGefywQgPYzfhhUp87q7hDdvRNlhL+Tt18wYxWRyiMM7e8j0XQbUp2w/+83VNZG9LVh/Iu8LXtOY1y9AoKicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxoXPEQGS8VdvtkaJB1Cq2YPfhSrmZmlKzsXFYzvw/T+fLIkEUrak9XoQFAgoXpmmDAyJOhqOLajbFVL4gUP/T7qizBAmBonBrxCDn8PhNBoEd+fMcjYeLEVX0Zx1RoYXCAJCGZ/RJWHBooaN0aHICoXYB' ) ); const lsigAccount = algosdk.LogicSigAccount.fromByte(msigEncoded); @@ -378,7 +362,7 @@ describe('LogicSigAccount', () => { describe('address', () => { it('should be correct for escrow', () => { const escrowEncoded = new Uint8Array( - Buffer.from('gaRsc2lngqNhcmeSxAEBxAICA6FsxAUBIAEBIg==', 'base64') + algosdk.base64ToBytes('gaRsc2lngqNhcmeSxAEBxAICA6FsxAUBIAEBIg==') ); const lsigAccount = algosdk.LogicSigAccount.fromByte(escrowEncoded); @@ -392,9 +376,8 @@ describe('LogicSigAccount', () => { it('should be correct for single sig', () => { const sigEncoded = new Uint8Array( - Buffer.from( - 'gqRsc2lng6NhcmeSxAEBxAICA6FsxAUBIAEBIqNzaWfEQEkTuAXRnn8sEID2M34YVKfO6u4Q3b0TZYS/k7dfMGMVkcojDO3vI9F0G1KdsP/vN1TWRvS1YfyLvC17TmNcvQKmc2lna2V5xCAbfsCwS+pht5aQl+bL9AfhCKcFNR0LyYq+sSIJqKuBeA==', - 'base64' + algosdk.base64ToBytes( + 'gqRsc2lng6NhcmeSxAEBxAICA6FsxAUBIAEBIqNzaWfEQEkTuAXRnn8sEID2M34YVKfO6u4Q3b0TZYS/k7dfMGMVkcojDO3vI9F0G1KdsP/vN1TWRvS1YfyLvC17TmNcvQKmc2lna2V5xCAbfsCwS+pht5aQl+bL9AfhCKcFNR0LyYq+sSIJqKuBeA==' ) ); const lsigAccount = algosdk.LogicSigAccount.fromByte(sigEncoded); @@ -409,9 +392,8 @@ describe('LogicSigAccount', () => { it('should be correct for multisig', () => { const msigEncoded = new Uint8Array( - Buffer.from( - 'gaRsc2lng6NhcmeSxAEBxAICA6FsxAUBIAEBIqRtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RASRO4BdGefywQgPYzfhhUp87q7hDdvRNlhL+Tt18wYxWRyiMM7e8j0XQbUp2w/+83VNZG9LVh/Iu8LXtOY1y9AoKicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxoXPEQGS8VdvtkaJB1Cq2YPfhSrmZmlKzsXFYzvw/T+fLIkEUrak9XoQFAgoXpmmDAyJOhqOLajbFVL4gUP/T7qizBAmBonBrxCDn8PhNBoEd+fMcjYeLEVX0Zx1RoYXCAJCGZ/RJWHBooaN0aHICoXYB', - 'base64' + algosdk.base64ToBytes( + 'gaRsc2lng6NhcmeSxAEBxAICA6FsxAUBIAEBIqRtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RASRO4BdGefywQgPYzfhhUp87q7hDdvRNlhL+Tt18wYxWRyiMM7e8j0XQbUp2w/+83VNZG9LVh/Iu8LXtOY1y9AoKicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxoXPEQGS8VdvtkaJB1Cq2YPfhSrmZmlKzsXFYzvw/T+fLIkEUrak9XoQFAgoXpmmDAyJOhqOLajbFVL4gUP/T7qizBAmBonBrxCDn8PhNBoEd+fMcjYeLEVX0Zx1RoYXCAJCGZ/RJWHBooaN0aHICoXYB' ) ); const lsigAccount = algosdk.LogicSigAccount.fromByte(msigEncoded); @@ -467,9 +449,8 @@ describe('signLogicSigTransaction', () => { const expected = { txID: 'SV3GD4AKRRX43F3V4V7GYYB6YCQEPULGUI6GKZO6GPJDKOO75NFA', blob: new Uint8Array( - Buffer.from( - 'gqRsc2lngqNhcmeSxAEBxAICA6FsxAUBIAEBIqN0eG6Ko2FtdM0TiKNmZWXOAANPqKJmds4ADtbco2dlbq10ZXN0bmV0LXYzMS4womdoxCAmCyAJoJOohot5WHIvpeVG7eftF+TYXEx4r7BFJpDt0qJsds4ADtrEpG5vdGXECLRReTn8+tJxo3JjdsQgtMYiaKTDNVD1im3UuMojnJ8dELNBqn4aNuPOYfv8+Yqjc25kxCD2di2sdbGZfWwslhgGgFB0kNeVES/+f7dgsnOK+cfxraR0eXBlo3BheQ==', - 'base64' + algosdk.base64ToBytes( + 'gqRsc2lngqNhcmeSxAEBxAICA6FsxAUBIAEBIqN0eG6Ko2FtdM0TiKNmZWXOAANPqKJmds4ADtbco2dlbq10ZXN0bmV0LXYzMS4womdoxCAmCyAJoJOohot5WHIvpeVG7eftF+TYXEx4r7BFJpDt0qJsds4ADtrEpG5vdGXECLRReTn8+tJxo3JjdsQgtMYiaKTDNVD1im3UuMojnJ8dELNBqn4aNuPOYfv8+Yqjc25kxCD2di2sdbGZfWwslhgGgFB0kNeVES/+f7dgsnOK+cfxraR0eXBlo3BheQ==' ) ), }; @@ -481,9 +462,8 @@ describe('signLogicSigTransaction', () => { const expected = { txID: 'DRBC5KBOYEUCL6L6H45GQSRKCCUTPNELUHUSQO4ZWCEODJEXQBBQ', blob: new Uint8Array( - Buffer.from( - 'g6Rsc2lngqNhcmeSxAEBxAICA6FsxAUBIAEBIqRzZ25yxCD2di2sdbGZfWwslhgGgFB0kNeVES/+f7dgsnOK+cfxraN0eG6Ko2FtdM0TiKNmZWXOAANPqKJmds4ADtbco2dlbq10ZXN0bmV0LXYzMS4womdoxCAmCyAJoJOohot5WHIvpeVG7eftF+TYXEx4r7BFJpDt0qJsds4ADtrEpG5vdGXECLRReTn8+tJxo3JjdsQgtMYiaKTDNVD1im3UuMojnJ8dELNBqn4aNuPOYfv8+Yqjc25kxCC0xiJopMM1UPWKbdS4yiOcnx0Qs0Gqfho2485h+/z5iqR0eXBlo3BheQ==', - 'base64' + algosdk.base64ToBytes( + 'g6Rsc2lngqNhcmeSxAEBxAICA6FsxAUBIAEBIqRzZ25yxCD2di2sdbGZfWwslhgGgFB0kNeVES/+f7dgsnOK+cfxraN0eG6Ko2FtdM0TiKNmZWXOAANPqKJmds4ADtbco2dlbq10ZXN0bmV0LXYzMS4womdoxCAmCyAJoJOohot5WHIvpeVG7eftF+TYXEx4r7BFJpDt0qJsds4ADtrEpG5vdGXECLRReTn8+tJxo3JjdsQgtMYiaKTDNVD1im3UuMojnJ8dELNBqn4aNuPOYfv8+Yqjc25kxCC0xiJopMM1UPWKbdS4yiOcnx0Qs0Gqfho2485h+/z5iqR0eXBlo3BheQ==' ) ), }; @@ -503,9 +483,8 @@ describe('signLogicSigTransaction', () => { const expected = { txID: 'EZB2N2TEFR5OOL76Z46ZMRUL3ZQQOYKRFIX6WSHQ5FWESHU4LZPA', blob: new Uint8Array( - Buffer.from( - 'gqRsc2lng6NhcmeSxAEBxAICA6FsxAUBIAEBIqNzaWfEQD4FPTlN+xK8ZXmf6jGKe46iUYtVLIq+bNenZS3YsBh+IQUtuSRiiRblYXTNDxmsuWxFpCmRmREd5Hzk/BLszgKjdHhuiqNhbXTNE4ijZmVlzgADT6iiZnbOAA7W3KNnZW6tdGVzdG5ldC12MzEuMKJnaMQgJgsgCaCTqIaLeVhyL6XlRu3n7Rfk2FxMeK+wRSaQ7dKibHbOAA7axKRub3RlxAi0UXk5/PrScaNyY3bEILTGImikwzVQ9Ypt1LjKI5yfHRCzQap+GjbjzmH7/PmKo3NuZMQgXmdPHAru7DdxiY9hx2/10koZeT4skfoIUWJj44Vz6kKkdHlwZaNwYXk=', - 'base64' + algosdk.base64ToBytes( + 'gqRsc2lng6NhcmeSxAEBxAICA6FsxAUBIAEBIqNzaWfEQD4FPTlN+xK8ZXmf6jGKe46iUYtVLIq+bNenZS3YsBh+IQUtuSRiiRblYXTNDxmsuWxFpCmRmREd5Hzk/BLszgKjdHhuiqNhbXTNE4ijZmVlzgADT6iiZnbOAA7W3KNnZW6tdGVzdG5ldC12MzEuMKJnaMQgJgsgCaCTqIaLeVhyL6XlRu3n7Rfk2FxMeK+wRSaQ7dKibHbOAA7axKRub3RlxAi0UXk5/PrScaNyY3bEILTGImikwzVQ9Ypt1LjKI5yfHRCzQap+GjbjzmH7/PmKo3NuZMQgXmdPHAru7DdxiY9hx2/10koZeT4skfoIUWJj44Vz6kKkdHlwZaNwYXk=' ) ), }; @@ -547,9 +526,8 @@ describe('signLogicSigTransaction', () => { const expected = { txID: 'UGGT5EZXG2OBPGWTEINC65UXIQ6UVAAOTNKRRCRAUCZH4FWJTVQQ', blob: new Uint8Array( - Buffer.from( - 'gqRsc2lng6NhcmeSxAEBxAICA6FsxAUBIAEBIqRtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RASRO4BdGefywQgPYzfhhUp87q7hDdvRNlhL+Tt18wYxWRyiMM7e8j0XQbUp2w/+83VNZG9LVh/Iu8LXtOY1y9AoKicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxoXPEQGS8VdvtkaJB1Cq2YPfhSrmZmlKzsXFYzvw/T+fLIkEUrak9XoQFAgoXpmmDAyJOhqOLajbFVL4gUP/T7qizBAmBonBrxCDn8PhNBoEd+fMcjYeLEVX0Zx1RoYXCAJCGZ/RJWHBooaN0aHICoXYBo3R4boqjYW10zROIo2ZlZc4AA0+oomZ2zgAO1tyjZ2VurXRlc3RuZXQtdjMxLjCiZ2jEICYLIAmgk6iGi3lYci+l5Ubt5+0X5NhcTHivsEUmkO3Somx2zgAO2sSkbm90ZcQItFF5Ofz60nGjcmN2xCC0xiJopMM1UPWKbdS4yiOcnx0Qs0Gqfho2485h+/z5iqNzbmTEII2StImQAXOgTfpDWaNmamr86ixCoF3Zwfc+66VHgDfppHR5cGWjcGF5', - 'base64' + algosdk.base64ToBytes( + 'gqRsc2lng6NhcmeSxAEBxAICA6FsxAUBIAEBIqRtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RASRO4BdGefywQgPYzfhhUp87q7hDdvRNlhL+Tt18wYxWRyiMM7e8j0XQbUp2w/+83VNZG9LVh/Iu8LXtOY1y9AoKicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxoXPEQGS8VdvtkaJB1Cq2YPfhSrmZmlKzsXFYzvw/T+fLIkEUrak9XoQFAgoXpmmDAyJOhqOLajbFVL4gUP/T7qizBAmBonBrxCDn8PhNBoEd+fMcjYeLEVX0Zx1RoYXCAJCGZ/RJWHBooaN0aHICoXYBo3R4boqjYW10zROIo2ZlZc4AA0+oomZ2zgAO1tyjZ2VurXRlc3RuZXQtdjMxLjCiZ2jEICYLIAmgk6iGi3lYci+l5Ubt5+0X5NhcTHivsEUmkO3Somx2zgAO2sSkbm90ZcQItFF5Ofz60nGjcmN2xCC0xiJopMM1UPWKbdS4yiOcnx0Qs0Gqfho2485h+/z5iqNzbmTEII2StImQAXOgTfpDWaNmamr86ixCoF3Zwfc+66VHgDfppHR5cGWjcGF5' ) ), }; @@ -561,9 +539,8 @@ describe('signLogicSigTransaction', () => { const expected = { txID: 'DRBC5KBOYEUCL6L6H45GQSRKCCUTPNELUHUSQO4ZWCEODJEXQBBQ', blob: new Uint8Array( - Buffer.from( - 'g6Rsc2lng6NhcmeSxAEBxAICA6FsxAUBIAEBIqRtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RASRO4BdGefywQgPYzfhhUp87q7hDdvRNlhL+Tt18wYxWRyiMM7e8j0XQbUp2w/+83VNZG9LVh/Iu8LXtOY1y9AoKicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxoXPEQGS8VdvtkaJB1Cq2YPfhSrmZmlKzsXFYzvw/T+fLIkEUrak9XoQFAgoXpmmDAyJOhqOLajbFVL4gUP/T7qizBAmBonBrxCDn8PhNBoEd+fMcjYeLEVX0Zx1RoYXCAJCGZ/RJWHBooaN0aHICoXYBpHNnbnLEII2StImQAXOgTfpDWaNmamr86ixCoF3Zwfc+66VHgDfpo3R4boqjYW10zROIo2ZlZc4AA0+oomZ2zgAO1tyjZ2VurXRlc3RuZXQtdjMxLjCiZ2jEICYLIAmgk6iGi3lYci+l5Ubt5+0X5NhcTHivsEUmkO3Somx2zgAO2sSkbm90ZcQItFF5Ofz60nGjcmN2xCC0xiJopMM1UPWKbdS4yiOcnx0Qs0Gqfho2485h+/z5iqNzbmTEILTGImikwzVQ9Ypt1LjKI5yfHRCzQap+GjbjzmH7/PmKpHR5cGWjcGF5', - 'base64' + algosdk.base64ToBytes( + 'g6Rsc2lng6NhcmeSxAEBxAICA6FsxAUBIAEBIqRtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RASRO4BdGefywQgPYzfhhUp87q7hDdvRNlhL+Tt18wYxWRyiMM7e8j0XQbUp2w/+83VNZG9LVh/Iu8LXtOY1y9AoKicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxoXPEQGS8VdvtkaJB1Cq2YPfhSrmZmlKzsXFYzvw/T+fLIkEUrak9XoQFAgoXpmmDAyJOhqOLajbFVL4gUP/T7qizBAmBonBrxCDn8PhNBoEd+fMcjYeLEVX0Zx1RoYXCAJCGZ/RJWHBooaN0aHICoXYBpHNnbnLEII2StImQAXOgTfpDWaNmamr86ixCoF3Zwfc+66VHgDfpo3R4boqjYW10zROIo2ZlZc4AA0+oomZ2zgAO1tyjZ2VurXRlc3RuZXQtdjMxLjCiZ2jEICYLIAmgk6iGi3lYci+l5Ubt5+0X5NhcTHivsEUmkO3Somx2zgAO2sSkbm90ZcQItFF5Ofz60nGjcmN2xCC0xiJopMM1UPWKbdS4yiOcnx0Qs0Gqfho2485h+/z5iqNzbmTEILTGImikwzVQ9Ypt1LjKI5yfHRCzQap+GjbjzmH7/PmKpHR5cGWjcGF5' ) ), }; @@ -581,9 +558,8 @@ describe('signLogicSigTransaction', () => { const expected = { txID: 'SV3GD4AKRRX43F3V4V7GYYB6YCQEPULGUI6GKZO6GPJDKOO75NFA', blob: new Uint8Array( - Buffer.from( - 'gqRsc2lngqNhcmeSxAEBxAICA6FsxAUBIAEBIqN0eG6Ko2FtdM0TiKNmZWXOAANPqKJmds4ADtbco2dlbq10ZXN0bmV0LXYzMS4womdoxCAmCyAJoJOohot5WHIvpeVG7eftF+TYXEx4r7BFJpDt0qJsds4ADtrEpG5vdGXECLRReTn8+tJxo3JjdsQgtMYiaKTDNVD1im3UuMojnJ8dELNBqn4aNuPOYfv8+Yqjc25kxCD2di2sdbGZfWwslhgGgFB0kNeVES/+f7dgsnOK+cfxraR0eXBlo3BheQ==', - 'base64' + algosdk.base64ToBytes( + 'gqRsc2lngqNhcmeSxAEBxAICA6FsxAUBIAEBIqN0eG6Ko2FtdM0TiKNmZWXOAANPqKJmds4ADtbco2dlbq10ZXN0bmV0LXYzMS4womdoxCAmCyAJoJOohot5WHIvpeVG7eftF+TYXEx4r7BFJpDt0qJsds4ADtrEpG5vdGXECLRReTn8+tJxo3JjdsQgtMYiaKTDNVD1im3UuMojnJ8dELNBqn4aNuPOYfv8+Yqjc25kxCD2di2sdbGZfWwslhgGgFB0kNeVES/+f7dgsnOK+cfxraR0eXBlo3BheQ==' ) ), }; @@ -595,9 +571,8 @@ describe('signLogicSigTransaction', () => { const expected = { txID: 'DRBC5KBOYEUCL6L6H45GQSRKCCUTPNELUHUSQO4ZWCEODJEXQBBQ', blob: new Uint8Array( - Buffer.from( - 'g6Rsc2lngqNhcmeSxAEBxAICA6FsxAUBIAEBIqRzZ25yxCD2di2sdbGZfWwslhgGgFB0kNeVES/+f7dgsnOK+cfxraN0eG6Ko2FtdM0TiKNmZWXOAANPqKJmds4ADtbco2dlbq10ZXN0bmV0LXYzMS4womdoxCAmCyAJoJOohot5WHIvpeVG7eftF+TYXEx4r7BFJpDt0qJsds4ADtrEpG5vdGXECLRReTn8+tJxo3JjdsQgtMYiaKTDNVD1im3UuMojnJ8dELNBqn4aNuPOYfv8+Yqjc25kxCC0xiJopMM1UPWKbdS4yiOcnx0Qs0Gqfho2485h+/z5iqR0eXBlo3BheQ==', - 'base64' + algosdk.base64ToBytes( + 'g6Rsc2lngqNhcmeSxAEBxAICA6FsxAUBIAEBIqRzZ25yxCD2di2sdbGZfWwslhgGgFB0kNeVES/+f7dgsnOK+cfxraN0eG6Ko2FtdM0TiKNmZWXOAANPqKJmds4ADtbco2dlbq10ZXN0bmV0LXYzMS4womdoxCAmCyAJoJOohot5WHIvpeVG7eftF+TYXEx4r7BFJpDt0qJsds4ADtrEpG5vdGXECLRReTn8+tJxo3JjdsQgtMYiaKTDNVD1im3UuMojnJ8dELNBqn4aNuPOYfv8+Yqjc25kxCC0xiJopMM1UPWKbdS4yiOcnx0Qs0Gqfho2485h+/z5iqR0eXBlo3BheQ==' ) ), }; @@ -617,9 +592,8 @@ describe('signLogicSigTransaction', () => { const expected = { txID: 'EZB2N2TEFR5OOL76Z46ZMRUL3ZQQOYKRFIX6WSHQ5FWESHU4LZPA', blob: new Uint8Array( - Buffer.from( - 'gqRsc2lng6NhcmeSxAEBxAICA6FsxAUBIAEBIqNzaWfEQD4FPTlN+xK8ZXmf6jGKe46iUYtVLIq+bNenZS3YsBh+IQUtuSRiiRblYXTNDxmsuWxFpCmRmREd5Hzk/BLszgKjdHhuiqNhbXTNE4ijZmVlzgADT6iiZnbOAA7W3KNnZW6tdGVzdG5ldC12MzEuMKJnaMQgJgsgCaCTqIaLeVhyL6XlRu3n7Rfk2FxMeK+wRSaQ7dKibHbOAA7axKRub3RlxAi0UXk5/PrScaNyY3bEILTGImikwzVQ9Ypt1LjKI5yfHRCzQap+GjbjzmH7/PmKo3NuZMQgXmdPHAru7DdxiY9hx2/10koZeT4skfoIUWJj44Vz6kKkdHlwZaNwYXk=', - 'base64' + algosdk.base64ToBytes( + 'gqRsc2lng6NhcmeSxAEBxAICA6FsxAUBIAEBIqNzaWfEQD4FPTlN+xK8ZXmf6jGKe46iUYtVLIq+bNenZS3YsBh+IQUtuSRiiRblYXTNDxmsuWxFpCmRmREd5Hzk/BLszgKjdHhuiqNhbXTNE4ijZmVlzgADT6iiZnbOAA7W3KNnZW6tdGVzdG5ldC12MzEuMKJnaMQgJgsgCaCTqIaLeVhyL6XlRu3n7Rfk2FxMeK+wRSaQ7dKibHbOAA7axKRub3RlxAi0UXk5/PrScaNyY3bEILTGImikwzVQ9Ypt1LjKI5yfHRCzQap+GjbjzmH7/PmKo3NuZMQgXmdPHAru7DdxiY9hx2/10koZeT4skfoIUWJj44Vz6kKkdHlwZaNwYXk=' ) ), }; @@ -631,9 +605,8 @@ describe('signLogicSigTransaction', () => { const expected = { txID: 'DRBC5KBOYEUCL6L6H45GQSRKCCUTPNELUHUSQO4ZWCEODJEXQBBQ', blob: new Uint8Array( - Buffer.from( - 'g6Rsc2lng6NhcmeSxAEBxAICA6FsxAUBIAEBIqNzaWfEQD4FPTlN+xK8ZXmf6jGKe46iUYtVLIq+bNenZS3YsBh+IQUtuSRiiRblYXTNDxmsuWxFpCmRmREd5Hzk/BLszgKkc2ducsQgXmdPHAru7DdxiY9hx2/10koZeT4skfoIUWJj44Vz6kKjdHhuiqNhbXTNE4ijZmVlzgADT6iiZnbOAA7W3KNnZW6tdGVzdG5ldC12MzEuMKJnaMQgJgsgCaCTqIaLeVhyL6XlRu3n7Rfk2FxMeK+wRSaQ7dKibHbOAA7axKRub3RlxAi0UXk5/PrScaNyY3bEILTGImikwzVQ9Ypt1LjKI5yfHRCzQap+GjbjzmH7/PmKo3NuZMQgtMYiaKTDNVD1im3UuMojnJ8dELNBqn4aNuPOYfv8+YqkdHlwZaNwYXk=', - 'base64' + algosdk.base64ToBytes( + 'g6Rsc2lng6NhcmeSxAEBxAICA6FsxAUBIAEBIqNzaWfEQD4FPTlN+xK8ZXmf6jGKe46iUYtVLIq+bNenZS3YsBh+IQUtuSRiiRblYXTNDxmsuWxFpCmRmREd5Hzk/BLszgKkc2ducsQgXmdPHAru7DdxiY9hx2/10koZeT4skfoIUWJj44Vz6kKjdHhuiqNhbXTNE4ijZmVlzgADT6iiZnbOAA7W3KNnZW6tdGVzdG5ldC12MzEuMKJnaMQgJgsgCaCTqIaLeVhyL6XlRu3n7Rfk2FxMeK+wRSaQ7dKibHbOAA7axKRub3RlxAi0UXk5/PrScaNyY3bEILTGImikwzVQ9Ypt1LjKI5yfHRCzQap+GjbjzmH7/PmKo3NuZMQgtMYiaKTDNVD1im3UuMojnJ8dELNBqn4aNuPOYfv8+YqkdHlwZaNwYXk=' ) ), }; @@ -651,9 +624,8 @@ describe('signLogicSigTransaction', () => { const expected = { txID: 'UGGT5EZXG2OBPGWTEINC65UXIQ6UVAAOTNKRRCRAUCZH4FWJTVQQ', blob: new Uint8Array( - Buffer.from( - 'gqRsc2lng6NhcmeSxAEBxAICA6FsxAUBIAEBIqRtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RASRO4BdGefywQgPYzfhhUp87q7hDdvRNlhL+Tt18wYxWRyiMM7e8j0XQbUp2w/+83VNZG9LVh/Iu8LXtOY1y9AoKicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxoXPEQGS8VdvtkaJB1Cq2YPfhSrmZmlKzsXFYzvw/T+fLIkEUrak9XoQFAgoXpmmDAyJOhqOLajbFVL4gUP/T7qizBAmBonBrxCDn8PhNBoEd+fMcjYeLEVX0Zx1RoYXCAJCGZ/RJWHBooaN0aHICoXYBo3R4boqjYW10zROIo2ZlZc4AA0+oomZ2zgAO1tyjZ2VurXRlc3RuZXQtdjMxLjCiZ2jEICYLIAmgk6iGi3lYci+l5Ubt5+0X5NhcTHivsEUmkO3Somx2zgAO2sSkbm90ZcQItFF5Ofz60nGjcmN2xCC0xiJopMM1UPWKbdS4yiOcnx0Qs0Gqfho2485h+/z5iqNzbmTEII2StImQAXOgTfpDWaNmamr86ixCoF3Zwfc+66VHgDfppHR5cGWjcGF5', - 'base64' + algosdk.base64ToBytes( + 'gqRsc2lng6NhcmeSxAEBxAICA6FsxAUBIAEBIqRtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RASRO4BdGefywQgPYzfhhUp87q7hDdvRNlhL+Tt18wYxWRyiMM7e8j0XQbUp2w/+83VNZG9LVh/Iu8LXtOY1y9AoKicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxoXPEQGS8VdvtkaJB1Cq2YPfhSrmZmlKzsXFYzvw/T+fLIkEUrak9XoQFAgoXpmmDAyJOhqOLajbFVL4gUP/T7qizBAmBonBrxCDn8PhNBoEd+fMcjYeLEVX0Zx1RoYXCAJCGZ/RJWHBooaN0aHICoXYBo3R4boqjYW10zROIo2ZlZc4AA0+oomZ2zgAO1tyjZ2VurXRlc3RuZXQtdjMxLjCiZ2jEICYLIAmgk6iGi3lYci+l5Ubt5+0X5NhcTHivsEUmkO3Somx2zgAO2sSkbm90ZcQItFF5Ofz60nGjcmN2xCC0xiJopMM1UPWKbdS4yiOcnx0Qs0Gqfho2485h+/z5iqNzbmTEII2StImQAXOgTfpDWaNmamr86ixCoF3Zwfc+66VHgDfppHR5cGWjcGF5' ) ), }; @@ -665,9 +637,8 @@ describe('signLogicSigTransaction', () => { const expected = { txID: 'DRBC5KBOYEUCL6L6H45GQSRKCCUTPNELUHUSQO4ZWCEODJEXQBBQ', blob: new Uint8Array( - Buffer.from( - 'g6Rsc2lng6NhcmeSxAEBxAICA6FsxAUBIAEBIqRtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RASRO4BdGefywQgPYzfhhUp87q7hDdvRNlhL+Tt18wYxWRyiMM7e8j0XQbUp2w/+83VNZG9LVh/Iu8LXtOY1y9AoKicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxoXPEQGS8VdvtkaJB1Cq2YPfhSrmZmlKzsXFYzvw/T+fLIkEUrak9XoQFAgoXpmmDAyJOhqOLajbFVL4gUP/T7qizBAmBonBrxCDn8PhNBoEd+fMcjYeLEVX0Zx1RoYXCAJCGZ/RJWHBooaN0aHICoXYBpHNnbnLEII2StImQAXOgTfpDWaNmamr86ixCoF3Zwfc+66VHgDfpo3R4boqjYW10zROIo2ZlZc4AA0+oomZ2zgAO1tyjZ2VurXRlc3RuZXQtdjMxLjCiZ2jEICYLIAmgk6iGi3lYci+l5Ubt5+0X5NhcTHivsEUmkO3Somx2zgAO2sSkbm90ZcQItFF5Ofz60nGjcmN2xCC0xiJopMM1UPWKbdS4yiOcnx0Qs0Gqfho2485h+/z5iqNzbmTEILTGImikwzVQ9Ypt1LjKI5yfHRCzQap+GjbjzmH7/PmKpHR5cGWjcGF5', - 'base64' + algosdk.base64ToBytes( + 'g6Rsc2lng6NhcmeSxAEBxAICA6FsxAUBIAEBIqRtc2lng6ZzdWJzaWeTgqJwa8QgG37AsEvqYbeWkJfmy/QH4QinBTUdC8mKvrEiCairgXihc8RASRO4BdGefywQgPYzfhhUp87q7hDdvRNlhL+Tt18wYxWRyiMM7e8j0XQbUp2w/+83VNZG9LVh/Iu8LXtOY1y9AoKicGvEIAljMglTc4nwdWcRdzmRx9A+G3PIxPUr9q/wGqJc+cJxoXPEQGS8VdvtkaJB1Cq2YPfhSrmZmlKzsXFYzvw/T+fLIkEUrak9XoQFAgoXpmmDAyJOhqOLajbFVL4gUP/T7qizBAmBonBrxCDn8PhNBoEd+fMcjYeLEVX0Zx1RoYXCAJCGZ/RJWHBooaN0aHICoXYBpHNnbnLEII2StImQAXOgTfpDWaNmamr86ixCoF3Zwfc+66VHgDfpo3R4boqjYW10zROIo2ZlZc4AA0+oomZ2zgAO1tyjZ2VurXRlc3RuZXQtdjMxLjCiZ2jEICYLIAmgk6iGi3lYci+l5Ubt5+0X5NhcTHivsEUmkO3Somx2zgAO2sSkbm90ZcQItFF5Ofz60nGjcmN2xCC0xiJopMM1UPWKbdS4yiOcnx0Qs0Gqfho2485h+/z5iqNzbmTEILTGImikwzVQ9Ypt1LjKI5yfHRCzQap+GjbjzmH7/PmKpHR5cGWjcGF5' ) ), }; @@ -709,9 +680,8 @@ describe('signLogicSigTransaction', () => { const expected = { txID: 'D7H6THOHOCEWJYNWMKHVOR2W36KAJXSGG6DMNTHTBWONBCG4XATA', blob: new Uint8Array( - Buffer.from( - 'gqRsc2lngaFsxAUBIAEBIqN0eG6Ko2FtdM0DT6NmZWXNCniiZnYzomdoxCAmCyAJoJOohot5WHIvpeVG7eftF+TYXEx4r7BFJpDt0qJsdj2kbm90ZcQDewzIo3JjdsQgoImqaSLjuZj63/bNSAjd+eAh5JROOJ6j1cY4eGaJGX6lcmVrZXnEIDAhUOuXI/Dnhg1MAE4rbltxOOB+7lUduJbsxucZf2DUo3NuZMQg9nYtrHWxmX1sLJYYBoBQdJDXlREv/n+3YLJzivnH8a2kdHlwZaNwYXk=', - 'base64' + algosdk.base64ToBytes( + 'gqRsc2lngaFsxAUBIAEBIqN0eG6Ko2FtdM0DT6NmZWXNCniiZnYzomdoxCAmCyAJoJOohot5WHIvpeVG7eftF+TYXEx4r7BFJpDt0qJsdj2kbm90ZcQDewzIo3JjdsQgoImqaSLjuZj63/bNSAjd+eAh5JROOJ6j1cY4eGaJGX6lcmVrZXnEIDAhUOuXI/Dnhg1MAE4rbltxOOB+7lUduJbsxucZf2DUo3NuZMQg9nYtrHWxmX1sLJYYBoBQdJDXlREv/n+3YLJzivnH8a2kdHlwZaNwYXk=' ) ), }; diff --git a/tests/cucumber/steps/steps.js b/tests/cucumber/steps/steps.js index 48f760c07..01707f75e 100644 --- a/tests/cucumber/steps/steps.js +++ b/tests/cucumber/steps/steps.js @@ -5,7 +5,6 @@ const path = require('path'); const algosdk = require('../../../src/index'); const nacl = require('../../../src/nacl/naclWrappers'); -const { concatArrays } = require('../../../src/utils/utils'); const maindir = path.dirname(path.dirname(path.dirname(__dirname))); @@ -177,6 +176,19 @@ module.exports = function getSteps(options) { return boxRefArray; } + function concatArrays(...arrs) { + const size = arrs.reduce((sum, arr) => sum + arr.length, 0); + const c = new Uint8Array(size); + + let offset = 0; + for (let i = 0; i < arrs.length; i++) { + c.set(arrs[i], offset); + offset += arrs[i].length; + } + + return c; + } + Given('a kmd client', function () { this.kcl = new algosdk.Kmd(kmdToken, 'http://localhost', 60001); return this.kcl; @@ -1026,7 +1038,7 @@ module.exports = function getSteps(options) { unitname: unitName, assetname: assetName, url: assetURL, - metadatahash: algosdk.bytesToBase64(metadataHash), + metadatahash: metadataHash, managerkey: manager, reserveaddr: reserve, freezeaddr: freeze, @@ -1092,7 +1104,7 @@ module.exports = function getSteps(options) { unitname: unitName, assetname: assetName, url: assetURL, - metadatahash: algosdk.bytesToBase64(metadataHash), + metadatahash: metadataHash, managerkey: manager, reserveaddr: reserve, freezeaddr: freeze, @@ -4499,9 +4511,7 @@ module.exports = function getSteps(options) { .do(); assert.deepStrictEqual(boxes.length, resp.boxes.length); - const actualBoxes = new Set( - resp.boxes.map((b) => algosdk.base64ToBytes(b.name)) - ); + const actualBoxes = new Set(resp.boxes.map((b) => b.name)); const expectedBoxes = new Set(boxes); assert.deepStrictEqual(expectedBoxes, actualBoxes); } @@ -4548,9 +4558,7 @@ module.exports = function getSteps(options) { } assert.deepStrictEqual(boxes.length, resp.boxes.length); - const actualBoxes = new Set( - resp.boxes.map((b) => algosdk.base64ToBytes(b.name)) - ); + const actualBoxes = new Set(resp.boxes.map((b) => b.name)); const expectedBoxes = new Set(boxes); assert.deepStrictEqual(expectedBoxes, actualBoxes); } From 792cfe067c304b6a1291fd85372c91f8a65a416e Mon Sep 17 00:00:00 2001 From: algochoi <86622919+algochoi@users.noreply.github.com> Date: Wed, 19 Jul 2023 19:06:48 -0400 Subject: [PATCH 26/34] Fix node tests --- src/composer.ts | 7 ++++--- src/encoding/binarydata.ts | 25 ++++++------------------- 2 files changed, 10 insertions(+), 22 deletions(-) diff --git a/src/composer.ts b/src/composer.ts index 3f3e2eb23..ecef91d18 100644 --- a/src/composer.ts +++ b/src/composer.ts @@ -16,6 +16,7 @@ import { SimulateRequestTransactionGroup, SimulateResponse, } from './client/v2/algod/models/types'; +import { base64ToBytes } from './encoding/binarydata'; import * as encoding from './encoding/encoding'; import { assignGroupID } from './group'; import { makeApplicationCallTxnFromObject } from './makeTxn'; @@ -781,7 +782,7 @@ export class AtomicTransactionComposer { try { returnedResult.txInfo = pendingInfo; if (method.returns.type !== 'void') { - const logs = pendingInfo.logs || []; + const logs: string[] = pendingInfo.logs || []; if (logs.length === 0) { throw new Error( `App call transaction did not log a return value ${JSON.stringify( @@ -790,13 +791,13 @@ export class AtomicTransactionComposer { ); } - const lastLog: Uint8Array = logs[logs.length - 1]; + const lastLog: Uint8Array = base64ToBytes(logs[logs.length - 1]); if ( lastLog.byteLength < 4 || !arrayEqual(lastLog.slice(0, 4), RETURN_PREFIX) ) { throw new Error( - `App call transaction did not log a return value ${JSON.stringify( + `App call transaction did not log a ABI return value ${JSON.stringify( pendingInfo )}` ); diff --git a/src/encoding/binarydata.ts b/src/encoding/binarydata.ts index 382c5302a..2cac230d8 100644 --- a/src/encoding/binarydata.ts +++ b/src/encoding/binarydata.ts @@ -9,18 +9,9 @@ export function base64ToBytes(base64String: string): Uint8Array { if (isNode()) { return new Uint8Array(Buffer.from(base64String, 'base64')); } - if (typeof base64String !== 'string') { - throw new Error(`base64String is not string: ${base64String}`); - } /* eslint-env browser */ - try { - const binString = atob(base64String); - return Uint8Array.from(binString, (m) => m.codePointAt(0)); - } catch (err) { - throw new Error( - `base64String is invalid: ${base64String}; ${typeof base64String};` - ); - } + const binString = atob(base64String); + return Uint8Array.from(binString, (m) => m.codePointAt(0)); } /** @@ -44,14 +35,10 @@ export function bytesToBase64(byteArray: Uint8Array): string { return Buffer.from(byteArray).toString('base64'); } /* eslint-env browser */ - try { - const binString = Array.from(byteArray, (x) => - String.fromCodePoint(x) - ).join(''); - return btoa(binString); - } catch (err) { - throw new Error(`byteArray is invalid: ${byteArray}; ${typeof byteArray}`); - } + const binString = Array.from(byteArray, (x) => String.fromCodePoint(x)).join( + '' + ); + return btoa(binString); } /** From 3d8bff692d371ff41c787584fc3b11dac09f4d47 Mon Sep 17 00:00:00 2001 From: algochoi <86622919+algochoi@users.noreply.github.com> Date: Thu, 20 Jul 2023 00:34:29 -0400 Subject: [PATCH 27/34] Add alternative path for decoding composer responses --- examples/asa.ts | 2 +- src/composer.ts | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/examples/asa.ts b/examples/asa.ts index e6060d200..41a3dbc4c 100644 --- a/examples/asa.ts +++ b/examples/asa.ts @@ -49,7 +49,7 @@ async function main() { console.log(`Asset Params: ${JSON.stringify(assetInfo.params)}`); // example: ASSET_INFO - await new Promise((f) => setTimeout(f, 2000)); // sleep to ensure indexer is caught up + await new Promise((f) => setTimeout(f, 5000)); // sleep to ensure indexer is caught up // example: INDEXER_LOOKUP_ASSET const indexer = getLocalIndexerClient(); diff --git a/src/composer.ts b/src/composer.ts index ecef91d18..88582ede6 100644 --- a/src/composer.ts +++ b/src/composer.ts @@ -782,7 +782,7 @@ export class AtomicTransactionComposer { try { returnedResult.txInfo = pendingInfo; if (method.returns.type !== 'void') { - const logs: string[] = pendingInfo.logs || []; + const logs = pendingInfo.logs || []; if (logs.length === 0) { throw new Error( `App call transaction did not log a return value ${JSON.stringify( @@ -790,8 +790,12 @@ export class AtomicTransactionComposer { )}` ); } - - const lastLog: Uint8Array = base64ToBytes(logs[logs.length - 1]); + let lastLog: Uint8Array; + if (typeof logs[logs.length - 1] === 'string') { + lastLog = base64ToBytes(logs[logs.length - 1]); + } else { + lastLog = Uint8Array.from(logs[logs.length - 1]); + } if ( lastLog.byteLength < 4 || !arrayEqual(lastLog.slice(0, 4), RETURN_PREFIX) From e7aa3d3f3694a82a67f69c837777198777ca70ae Mon Sep 17 00:00:00 2001 From: algochoi <86622919+algochoi@users.noreply.github.com> Date: Wed, 26 Jul 2023 20:45:44 -0400 Subject: [PATCH 28/34] Remove browser buffer dependency, fix cucumber tests --- .eslintrc.js | 10 ----- package-lock.json | 81 ---------------------------------- package.json | 1 - src/encoding/binarydata.ts | 1 - src/transaction.ts | 2 +- tests/cucumber/browser/test.js | 13 ++++-- tests/cucumber/steps/steps.js | 40 ++++++++++------- 7 files changed, 34 insertions(+), 114 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index fcd70fb75..33bc5cf41 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -15,16 +15,6 @@ module.exports = { }, plugins: ['@typescript-eslint', 'eslint-plugin-tsdoc'], rules: { - 'no-restricted-globals': [ - 'error', - { - // This is to ensure that we use the 'buffer' package in the browser. In Node it doesn't - // make a difference. - name: 'Buffer', - message: - "Explictly import Buffer with `import { Buffer } from 'buffer'`", - }, - ], 'no-constant-condition': ['error', { checkLoops: false }], 'no-restricted-syntax': ['error', 'LabeledStatement', 'WithStatement'], 'no-plusplus': ['error', { allowForLoopAfterthoughts: true }], diff --git a/package-lock.json b/package-lock.json index 4ecdb811c..8a1b57f1f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,6 @@ "license": "MIT", "dependencies": { "algo-msgpack-with-bigint": "^2.1.1", - "buffer": "^6.0.3", "cross-fetch": "^4.0.0-alpha.5", "hi-base32": "^0.5.1", "js-sha256": "^0.9.0", @@ -1241,25 +1240,6 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, "node_modules/becke-ch--regex--s0-0-v1--base--pl--lib": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/becke-ch--regex--s0-0-v1--base--pl--lib/-/becke-ch--regex--s0-0-v1--base--pl--lib-1.4.0.tgz", @@ -1400,29 +1380,6 @@ "url": "https://opencollective.com/browserslist" } }, - "node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, "node_modules/buffer-crc32": { "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", @@ -4042,25 +3999,6 @@ "node": ">=0.10.0" } }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, "node_modules/ignore": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", @@ -9052,11 +8990,6 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, - "base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" - }, "becke-ch--regex--s0-0-v1--base--pl--lib": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/becke-ch--regex--s0-0-v1--base--pl--lib/-/becke-ch--regex--s0-0-v1--base--pl--lib-1.4.0.tgz", @@ -9170,15 +9103,6 @@ "node-releases": "^1.1.71" } }, - "buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, "buffer-crc32": { "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", @@ -11162,11 +11086,6 @@ "safer-buffer": ">= 2.1.2 < 3" } }, - "ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" - }, "ignore": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", diff --git a/package.json b/package.json index 655ae4164..e2f62b29e 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,6 @@ }, "dependencies": { "algo-msgpack-with-bigint": "^2.1.1", - "buffer": "^6.0.3", "cross-fetch": "^4.0.0-alpha.5", "hi-base32": "^0.5.1", "js-sha256": "^0.9.0", diff --git a/src/encoding/binarydata.ts b/src/encoding/binarydata.ts index 2cac230d8..5e1e07982 100644 --- a/src/encoding/binarydata.ts +++ b/src/encoding/binarydata.ts @@ -1,4 +1,3 @@ -import { Buffer } from 'buffer'; import { isNode } from '../utils/utils'; /** diff --git a/src/transaction.ts b/src/transaction.ts index 32f0c954a..2cd2969dd 100644 --- a/src/transaction.ts +++ b/src/transaction.ts @@ -1260,7 +1260,7 @@ export class Transaction implements TransactionStorageStructure { (forPrinting.reKeyTo as Address).publicKey ); if (typeof forPrinting.genesisHash !== 'string') - forPrinting.genesisHash = bytesToBase64(forPrinting.genesisHash); // TODO: double check this + forPrinting.genesisHash = bytesToBase64(forPrinting.genesisHash); return forPrinting; } diff --git a/tests/cucumber/browser/test.js b/tests/cucumber/browser/test.js index e276efcb3..ab190ff5f 100644 --- a/tests/cucumber/browser/test.js +++ b/tests/cucumber/browser/test.js @@ -1,11 +1,9 @@ /* eslint-env browser */ -const { Buffer } = require('buffer'); const assert = require('assert'); const sha512 = require('js-sha512'); const nacl = require('tweetnacl'); window.assert = assert; -window.Buffer = Buffer; window.keyPairFromSecretKey = function keyPairFromSecretKey(sk) { return nacl.sign.keyPair.fromSecretKey(sk); @@ -25,7 +23,16 @@ window.loadResource = async function loadResource(resource) { throw new Error(`Failed to load resource (${res.status}): ${resource}`); } - return Buffer.from(await res.arrayBuffer()); + return new Uint8Array(await res.arrayBuffer()); +}; + +window.loadResourceAsJson = async function loadResource(resource) { + const res = await fetch(`/features/resources/${resource}`); + if (!res.ok) { + throw new Error(`Failed to load resource (${res.status}): ${resource}`); + } + + return res.json(); }; window.steps = { diff --git a/tests/cucumber/steps/steps.js b/tests/cucumber/steps/steps.js index 01707f75e..44a2310b1 100644 --- a/tests/cucumber/steps/steps.js +++ b/tests/cucumber/steps/steps.js @@ -40,6 +40,10 @@ async function loadResource(res) { }); } +async function loadResourceAsJson(res) { + return JSON.parse(await loadResource(res)); +} + // START OBJECT CREATION FUNCTIONS /** @@ -2786,7 +2790,7 @@ module.exports = function getSteps(options) { sources = [ new algosdk.modelsv2.DryrunSource({ fieldName: 'lsig', - source: data.toString('utf8'), + source: new TextDecoder().decode(data), txnIndex: 0, }), ]; @@ -4371,17 +4375,18 @@ module.exports = function getSteps(options) { Given( 'a dryrun response file {string} and a transaction at index {string}', async function (drrFile, txId) { - const drContents = await loadResource(drrFile); - const js = parseJSON(drContents); - const drr = new algosdk.DryrunResult(js); + const drContents = await loadResourceAsJson(drrFile); + const drr = new algosdk.DryrunResult(drContents); this.txtrace = drr.txns[parseInt(txId)]; } ); Then('calling app trace produces {string}', async function (expected) { const traceString = this.txtrace.appTrace(); - const expectedString = (await loadResource(expected)).toString(); - assert.equal(traceString, expectedString); + const expectedString = new TextDecoder().decode( + await loadResource(expected) + ); + assert.deepStrictEqual(traceString, expectedString); }); When( @@ -4573,7 +4578,7 @@ module.exports = function getSteps(options) { ); Given('a source map json file {string}', async function (srcmap) { - const js = parseJSON(await loadResource(srcmap)); + const js = await loadResourceAsJson(srcmap); this.sourcemap = new algosdk.SourceMap(js); }); @@ -4583,7 +4588,7 @@ module.exports = function getSteps(options) { const buff = Object.entries(this.sourcemap.pcToLine).map( ([pc, line]) => `${pc}:${line}` ); - assert.equal(buff.join(';'), mapping); + assert.deepStrictEqual(buff.join(';'), mapping); } ); @@ -4591,7 +4596,7 @@ module.exports = function getSteps(options) { 'getting the line associated with a pc {string} equals {string}', function (pc, expectedLine) { const actualLine = this.sourcemap.getLineForPc(parseInt(pc)); - assert.equal(actualLine, parseInt(expectedLine)); + assert.deepStrictEqual(actualLine, parseInt(expectedLine)); } ); @@ -4599,7 +4604,7 @@ module.exports = function getSteps(options) { 'getting the last pc associated with a line {string} equals {string}', function (line, expectedPc) { const actualPcs = this.sourcemap.getPcsForLine(parseInt(line)); - assert.equal(actualPcs.pop(), parseInt(expectedPc)); + assert.deepStrictEqual(actualPcs.pop(), parseInt(expectedPc)); } ); @@ -4618,8 +4623,10 @@ module.exports = function getSteps(options) { Then( 'the resulting source map is the same as the json {string}', async function (expectedJsonPath) { - const expected = await loadResource(expectedJsonPath); - assert.equal(this.rawSourceMap, expected.toString().trim()); + const expected = new TextDecoder() + .decode(await loadResource(expectedJsonPath)) + .trim(); + assert.deepStrictEqual(this.rawSourceMap, expected); } ); @@ -4628,12 +4635,11 @@ module.exports = function getSteps(options) { async function (bytecodeFilename, sourceFilename) { const bytecode = await loadResource(bytecodeFilename); const resp = await this.v2Client.disassemble(bytecode).do(); - const expectedSource = await loadResource(sourceFilename); - - assert.deepStrictEqual( - resp.result.toString('UTF-8'), - expectedSource.toString('UTF-8') + const expectedSource = new TextDecoder().decode( + await loadResource(sourceFilename) ); + + assert.deepStrictEqual(resp.result.toString('UTF-8'), expectedSource); } ); From 50e03cf358c119529a9bb4019962d9cabb4fe723 Mon Sep 17 00:00:00 2001 From: algochoi <86622919+algochoi@users.noreply.github.com> Date: Thu, 27 Jul 2023 09:50:15 -0400 Subject: [PATCH 29/34] Revert cucumber node index.js file to use buffer again --- tests/cucumber/steps/index.js | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/tests/cucumber/steps/index.js b/tests/cucumber/steps/index.js index 2afa99e3d..828b73ab4 100644 --- a/tests/cucumber/steps/index.js +++ b/tests/cucumber/steps/index.js @@ -13,7 +13,6 @@ const { } = require('cucumber'); const express = require('express'); const ServerMock = require('mock-http-server'); -const algosdk = require('../../../src/index'); const getSteps = require('./steps'); const cucumberPath = path.dirname(__dirname); @@ -275,7 +274,7 @@ function setupMockServerForResponses(fileName, jsonDirectory, mockServer) { } if (fileName.endsWith('base64')) { headers = { 'content-type': 'application/msgpack', ...corsHeaders }; - body = algosdk.base64ToBytes(resultString); + body = Buffer.from(resultString, 'base64'); } let statusCode = 200; if (fileName.indexOf('Error') > -1) { @@ -451,11 +450,11 @@ for (const name of Object.keys(steps.given)) { if (fileName.endsWith('base64')) { format = 'msgp'; } - if (ArrayBuffer.isView(body1)) { - body1 = algosdk.bytesToBase64(body1); + if (Buffer.isBuffer(body1)) { + body1 = body1.toString('base64'); } - if (ArrayBuffer.isView(body2)) { - body2 = algosdk.bytesToBase64(body2); + if (Buffer.isBuffer(body2)) { + body2 = body2.toString('base64'); } return fn.call(this, body2 || body1, format); }); @@ -478,11 +477,11 @@ for (const name of Object.keys(steps.given)) { if (fileName.endsWith('base64')) { format = 'msgp'; } - if (ArrayBuffer.isView(body1)) { - body1 = algosdk.bytesToBase64(body1); + if (Buffer.isBuffer(body1)) { + body1 = body1.toString('base64'); } - if (ArrayBuffer.isView(body2)) { - body2 = algosdk.bytesToBase64(body2); + if (Buffer.isBuffer(body2)) { + body2 = body2.toString('base64'); } return fn.call(this, body2 || body1, status, format); }); From d7a4dfe7ad26ccc67b2bd62606ed790f9d9f7460 Mon Sep 17 00:00:00 2001 From: algochoi <86622919+algochoi@users.noreply.github.com> Date: Thu, 27 Jul 2023 09:52:02 -0400 Subject: [PATCH 30/34] Fix some conversion methods in err messages --- tests/cucumber/steps/steps.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/cucumber/steps/steps.js b/tests/cucumber/steps/steps.js index 44a2310b1..4f817b59b 100644 --- a/tests/cucumber/steps/steps.js +++ b/tests/cucumber/steps/steps.js @@ -4169,7 +4169,7 @@ module.exports = function getSteps(options) { [...actualSignedTxns], [...expectedSignedTxns], `Got ${actualSignedTxns - .map((stxn) => stxn.toString('base64')) + .map((stxn) => algosdk.bytesToBase64(stxn)) .join(',')}` ); } @@ -4207,8 +4207,8 @@ module.exports = function getSteps(options) { assert.deepStrictEqual( actualResult.rawReturnValue, expectedReturnValue, - `Actual return value for method at index ${i} does not match expected. Actual: ${actualResult.rawReturnValue.toString( - 'base64' + `Actual return value for method at index ${i} does not match expected. Actual: ${algosdk.bytesToBase64( + actualResult.rawReturnValue )}` ); From 950d3ff5d5ab4c0cb2d10784778556a9a2978225 Mon Sep 17 00:00:00 2001 From: algochoi <86622919+algochoi@users.noreply.github.com> Date: Thu, 27 Jul 2023 10:15:25 -0400 Subject: [PATCH 31/34] Update src/encoding/binarydata.ts Co-authored-by: Eric Warehime --- src/encoding/binarydata.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/encoding/binarydata.ts b/src/encoding/binarydata.ts index 5e1e07982..cac2805c2 100644 --- a/src/encoding/binarydata.ts +++ b/src/encoding/binarydata.ts @@ -77,8 +77,8 @@ export function hexToBytes(hexString: string): Uint8Array { hex = hexString.padStart(1, '0'); } const byteArray = new Uint8Array(hex.length / 2); - for (let i = 0, j = 0; i < hex.length / 2; i++, j += 2) { - byteArray[i] = parseInt(hex.slice(j, j + 2), 16); + for (let i = 0; i < hex.length / 2; i++) { + byteArray[i] = parseInt(hex.slice(2*i, 2*i + 2), 16); } return byteArray; } From 7463f4e89d5aef1537dc1303118bb1846185a708 Mon Sep 17 00:00:00 2001 From: algochoi <86622919+algochoi@users.noreply.github.com> Date: Thu, 27 Jul 2023 10:37:23 -0400 Subject: [PATCH 32/34] Run prettier on commit suggestion --- src/encoding/binarydata.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/encoding/binarydata.ts b/src/encoding/binarydata.ts index cac2805c2..be0fdef24 100644 --- a/src/encoding/binarydata.ts +++ b/src/encoding/binarydata.ts @@ -78,7 +78,7 @@ export function hexToBytes(hexString: string): Uint8Array { } const byteArray = new Uint8Array(hex.length / 2); for (let i = 0; i < hex.length / 2; i++) { - byteArray[i] = parseInt(hex.slice(2*i, 2*i + 2), 16); + byteArray[i] = parseInt(hex.slice(2 * i, 2 * i + 2), 16); } return byteArray; } From ee3e2e12b1260fad5a966352d16dfb256f0906e2 Mon Sep 17 00:00:00 2001 From: algochoi <86622919+algochoi@users.noreply.github.com> Date: Thu, 27 Jul 2023 14:27:48 -0400 Subject: [PATCH 33/34] Add toString conversion for buffers --- tests/cucumber/steps/steps.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/cucumber/steps/steps.js b/tests/cucumber/steps/steps.js index 4f817b59b..16525ed6b 100644 --- a/tests/cucumber/steps/steps.js +++ b/tests/cucumber/steps/steps.js @@ -41,7 +41,7 @@ async function loadResource(res) { } async function loadResourceAsJson(res) { - return JSON.parse(await loadResource(res)); + return JSON.parse((await loadResource(res)).toString()); } // START OBJECT CREATION FUNCTIONS From 624bf925f88db5c64c2847c3eb88d8371476c3a7 Mon Sep 17 00:00:00 2001 From: algochoi <86622919+algochoi@users.noreply.github.com> Date: Thu, 27 Jul 2023 14:28:51 -0400 Subject: [PATCH 34/34] Update tests/cucumber/browser/test.js Co-authored-by: Jason Paulos --- tests/cucumber/browser/test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/cucumber/browser/test.js b/tests/cucumber/browser/test.js index ab190ff5f..45ae7b977 100644 --- a/tests/cucumber/browser/test.js +++ b/tests/cucumber/browser/test.js @@ -26,7 +26,7 @@ window.loadResource = async function loadResource(resource) { return new Uint8Array(await res.arrayBuffer()); }; -window.loadResourceAsJson = async function loadResource(resource) { +window.loadResourceAsJson = async function loadResourceAsJson(resource) { const res = await fetch(`/features/resources/${resource}`); if (!res.ok) { throw new Error(`Failed to load resource (${res.status}): ${resource}`);