UNPKG

@ledgerhq/hw-app-algorand

Version:
106 lines 3.8 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const bip32_path_1 = __importDefault(require("bip32-path")); const errors_1 = require("@ledgerhq/errors"); const utils_1 = require("./utils"); const CHUNK_SIZE = 250; // const P1_FIRST = 0x00; const P1_MORE = 0x80; const P1_WITH_ACCOUNT_ID = 0x01; const P2_LAST = 0x00; const P2_MORE = 0x80; const SW_OK = 0x9000; const SW_CANCEL = 0x6986; const P1_WITH_REQUEST_USER_APPROVAL = 0x80; // algo spec const CLA = 0x80; const INS_GET_PUBLIC_KEY = 0x03; const INS_SIGN_MSGPACK = 0x08; /** * Algorand API * * @example * import Algorand from "@ledgerhq/hw-app-algorand"; * const algo = new Algorand(transport) */ class Algorand { transport; constructor(transport) { this.transport = transport; transport.decorateAppAPIMethods(this, ["getAddress", "sign"], "ALGO"); } /** * get Algorant address for a given BIP 32 path. * @param path a path in BIP 32 format * @option boolDisplay optionally enable or not the display * @return an object with a publicKey, address and (optionally) chainCode * @example * cosmos.getAddress("44'/283'/0'/0/0").then(o => o.address) */ getAddress(path, boolDisplay) { const bipPath = bip32_path_1.default.fromString(path).toPathArray(); const buf = Buffer.alloc(4); buf.writeUInt32BE(bipPath[2], 0); return this.transport .send(CLA, INS_GET_PUBLIC_KEY, boolDisplay ? P1_WITH_REQUEST_USER_APPROVAL : 0, 0, buf, [ SW_OK, ]) .then(response => { const buffer = Buffer.from(response.slice(0, 32)); const publicKey = buffer.toString("hex"); const address = (0, utils_1.encodeAddress)(buffer); return { publicKey, address, }; }); } foreach(arr, callback) { function iterate(index, array, result) { if (index >= array.length) { return result; } else return callback(array[index], index).then(function (res) { result.push(res); return iterate(index + 1, array, result); }); } return Promise.resolve().then(() => iterate(0, arr, [])); } async sign(path, message) { const bipPath = bip32_path_1.default.fromString(path).toPathArray(); const buf = Buffer.alloc(4); buf.writeUInt32BE(bipPath[2], 0); const chunks = []; const buffer = Buffer.concat([buf, Buffer.from(message, "hex")]); for (let i = 0; i < buffer.length; i += CHUNK_SIZE) { let end = i + CHUNK_SIZE; if (i > buffer.length) { end = buffer.length; } chunks.push(buffer.slice(i, end)); } let response = {}; return this.foreach(chunks, (data, j) => this.transport .send(CLA, INS_SIGN_MSGPACK, j === 0 ? P1_WITH_ACCOUNT_ID : P1_MORE, j + 1 === chunks.length ? P2_LAST : P2_MORE, data, [SW_OK, SW_CANCEL]) .then(apduResponse => (response = apduResponse))).then(() => { const errorCodeData = response; if (errorCodeData === 0x6986) { throw new errors_1.UserRefusedOnDevice(); } let signature = null; if (response.length > 0) { signature = response.slice(0, response.length); } return { signature: signature, }; }); } } exports.default = Algorand; //# sourceMappingURL=Algorand.js.map