From 3a052ea3109e212fb962c1691051dcc169f9343d Mon Sep 17 00:00:00 2001 From: Jason Paulos Date: Fri, 25 Sep 2020 11:25:51 -0400 Subject: [PATCH] Add way to encode/decode addresses from binary (#216) * Add way to encode/decode addresses from binary --- README.md | 24 +++++++++++++++++++++++- src/main.js | 22 +++++++++++++++++++++- tests/3.Address.js | 23 ++++++++++++----------- 3 files changed, 56 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index e4d0b7dc5..855944bff 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,7 @@ Example result "gorilla fortune learn marble essay uphold defense hover index effort ice atom figure will improve mom indoor mansion people elder hill material donkey abandon gown" ``` -#### Mnemonic to secret sey +#### Mnemonic to secret key ```javascript var secret_key = algosdk.mnemonicToSecretKey(mnemonic); ``` @@ -75,6 +75,28 @@ Example result true ``` +#### Encode/decode addresses +These two functions let you convert addresses between their string and binary representations. +```javascript +var decoded = algosdk.decodeAddress("IB3NJALXLDX5JLYCD4TMTMLVCKDRZNS4JONHMIWD6XM7DSKYR7MWHI6I7U"); +var encoded = algosdk.encodeAddress(decoded.publicKey); +console.log('Decoded:', decoded); +console.log('Encoded:', encoded); +``` +Result +```text +Decoded: { + publicKey: Uint8Array(32) [ + 64, 118, 212, 129, 119, 88, 239, 212, + 175, 2, 31, 38, 201, 177, 117, 18, + 135, 28, 182, 92, 75, 154, 118, 34, + 195, 245, 217, 241, 201, 88, 143, 217 + ], + checksum: Uint8Array(4) [ 99, 163, 200, 253 ] +} +Encoded: IB3NJALXLDX5JLYCD4TMTMLVCKDRZNS4JONHMIWD6XM7DSKYR7MWHI6I7U +``` + #### Sign a transaction In order to create and sign a transaction, create first an object with the relevant properties. There is no need to specify the `from` address, it is computed directly from the secretKey. diff --git a/src/main.js b/src/main.js index f64b8be35..4c35c6cdb 100644 --- a/src/main.js +++ b/src/main.js @@ -37,13 +37,31 @@ function generateAccount() { /** * isValidAddress takes an Algorand address and checks if valid. - * @param addr Algorand address + * @param {string} addr Algorand address * @returns {boolean} true if valid, false otherwise */ function isValidAddress(addr) { return address.isValidAddress(addr); } +/** + * encodeAddress takes an Algorand address as a Uint8Array and encodes it into a string with checksum. + * @param {Uint8Array} addr a raw Algorand address + * @returns {string} the address and checksum encoded as a string. + */ +function encodeAddress(addr) { + return address.encode(addr); +} + +/** + * decodeAddress takes an Algorand address in string form and decodes it into a Uint8Array. + * @param {string} addr an Algorand address with checksum. + * @returns {{publicKey: Uint8Array, checksum: Uint8Array}} the decoded form of the address's public key and checksum + */ +function decodeAddress(addr) { + return address.decode(addr) +} + /** * mnemonicToSecretKey takes a mnemonic string and returns the corresponding Algorand address and its secret key. * @param mn 25 words Algorand mnemonic @@ -1181,6 +1199,8 @@ function makeApplicationNoOpTxn(from, suggestedParams, appIndex, module.exports = { isValidAddress, + encodeAddress, + decodeAddress, generateAccount, secretKeyToMnemonic, mnemonicToSecretKey, diff --git a/tests/3.Address.js b/tests/3.Address.js index 4261c020c..bb6636220 100644 --- a/tests/3.Address.js +++ b/tests/3.Address.js @@ -1,38 +1,39 @@ let assert = require('assert'); let nacl = require("../src/nacl/naclWrappers"); let address = require("../src/encoding/address"); +let algosdk = require("../src/main"); describe('address', function () { describe('#isValid', function () { it('should verify a valid Algorand address', function () { - assert.ok(address.isValidAddress("MO2H6ZU47Q36GJ6GVHUKGEBEQINN7ZWVACMWZQGIYUOE3RBSRVYHV4ACJI")); + assert.ok(algosdk.isValidAddress("MO2H6ZU47Q36GJ6GVHUKGEBEQINN7ZWVACMWZQGIYUOE3RBSRVYHV4ACJI")); }); it('should fail to verify an invalid Algorand address', function () { - assert.strictEqual(address.isValidAddress("MO2H6ZU47Q36GJ6GVHUKGEBEQINN7ZWVACMWZQGIYUOE3RBSRVYHV4ACJG"), false); + assert.strictEqual(algosdk.isValidAddress("MO2H6ZU47Q36GJ6GVHUKGEBEQINN7ZWVACMWZQGIYUOE3RBSRVYHV4ACJG"), false); }); }); describe('encode, decode', function () { it('should be able to encode and verify an address', function () { let pk = nacl.randomBytes(32); - let addr = address.encode(pk); - assert.ok(address.isValidAddress(addr)); + let addr = algosdk.encodeAddress(pk); + assert.ok(algosdk.isValidAddress(addr)); }); it('should be able to encode and decode an address', function () { let pk = nacl.randomBytes(32); - let addr = address.encode(pk); - let d = address.decode(addr); + let addr = algosdk.encodeAddress(pk); + let d = algosdk.decodeAddress(addr); assert.deepStrictEqual(new Uint8Array(d.publicKey), pk); }); }); describe('from multisig preimage', function () { it('should match main repo code', function () { - const addr1 = address.decode("XMHLMNAVJIMAW2RHJXLXKKK4G3J3U6VONNO3BTAQYVDC3MHTGDP3J5OCRU"); - const addr2 = address.decode("HTNOX33OCQI2JCOLZ2IRM3BC2WZ6JUILSLEORBPFI6W7GU5Q4ZW6LINHLA"); - const addr3 = address.decode("E6JSNTY4PVCY3IRZ6XEDHEO6VIHCQ5KGXCIQKFQCMB2N6HXRY4IB43VSHI"); + const addr1 = algosdk.decodeAddress("XMHLMNAVJIMAW2RHJXLXKKK4G3J3U6VONNO3BTAQYVDC3MHTGDP3J5OCRU"); + const addr2 = algosdk.decodeAddress("HTNOX33OCQI2JCOLZ2IRM3BC2WZ6JUILSLEORBPFI6W7GU5Q4ZW6LINHLA"); + const addr3 = algosdk.decodeAddress("E6JSNTY4PVCY3IRZ6XEDHEO6VIHCQ5KGXCIQKFQCMB2N6HXRY4IB43VSHI"); const params = { version: 1, threshold: 2, @@ -40,8 +41,8 @@ describe('address', function () { }; const expectAddr = "UCE2U2JC4O4ZR6W763GUQCG57HQCDZEUJY4J5I6VYY4HQZUJDF7AKZO5GM"; let actualAddr = address.fromMultisigPreImg(params); - let actualAddrEnc = address.encode(actualAddr); - assert.ok(address.isValidAddress(actualAddrEnc)); + let actualAddrEnc = algosdk.encodeAddress(actualAddr); + assert.ok(algosdk.isValidAddress(actualAddrEnc)); assert.deepStrictEqual(actualAddrEnc, expectAddr); }); })