UNPKG

@ledgerhq/hw-app-helium

Version:
261 lines 9.71 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const errors_1 = require("@ledgerhq/errors"); const address_1 = __importDefault(require("@helium/address")); const proto_1 = __importDefault(require("@helium/proto")); const serialization_1 = require("./serialization"); const P1_NON_CONFIRM = 0x00; const P1_CONFIRM = 0x01; const LEDGER_CLA = 0xe0; const CLA_OFFSET = 0x00; const INS = { GET_VERSION: 0x01, GET_ADDR: 0x02, SIGN_PAYMENT: 0x08, SIGN_VALIDATOR_STAKE: 0x09, SIGN_VALIDATOR_TXFER: 0x0a, SIGN_VALIDATOR_UNSTAKE: 0x0b, SIGN_TOKEN_BURN: 0x0c, SIGN_TRANSFER_SEC_TXN: 0x0d, }; /** * Helium API * * @param transport a transport for sending commands to a device * @param scrambleKey a scramble key * * @example * import Helium from "@ledgerhq/hw-app-helium"; * const helium = new Helium(transport); */ class Helium { transport; constructor(transport, scrambleKey = "helium_default_scramble_key") { this.transport = transport; this.transport.decorateAppAPIMethods(this, [ "getVersion", "getAddress", "signPaymentV2", "signTokenBurnV1", "signStakeValidatorV1", "signUnstakeValidatorV1", "signTransferValidatorStakeV1", ], scrambleKey); } /** * Get application version. * * @returns version object * * @example * helium.getVersion().then(r => r.version) */ async getVersion() { const [major, minor, patch] = await this.sendToDevice(INS.GET_VERSION, P1_NON_CONFIRM, 0, Buffer.from([])); return { version: `${major}.${minor}.${patch}`, }; } /** * Get Helium address (public key) for a BIP32 path. * * @param path a BIP32 path * @param display flag to show display * @param accountIndex index of account address * @returns an object with the address field * * @example * helium.getAddress("44'/904'/0'/0'/0'").then(r => r.address) */ async getAddress(path, display, accountIndex = 0) { const pathBuffer = (0, serialization_1.pathToBuffer)(path); const addressBuffer = await this.sendToDevice(INS.GET_ADDR, display ? P1_CONFIRM : P1_NON_CONFIRM, accountIndex, pathBuffer); const address = address_1.default.fromBin(addressBuffer.slice(1, 34)); return { index: addressBuffer.slice(0, 1)[0], address: address.b58, publicKey: Buffer.from(address.publicKey).toString("hex"), }; } /** * Sign a Helium `PaymentV2` transaction. * * @param txn a PaymentV2 transaction * @param accountIndex index of account address * * @returns an object with the signed transaction and signature * * @example * import { PaymentV2 } from '@helium/transactions' * const txn = new PaymentV2({ ... }) * helium.signTransaction(txn).then(r => r.signature) */ async signPaymentV2(txn, accountIndex = 0) { const payload = (0, serialization_1.serializePaymentV2)(txn); const response = await this.sendToDevice(INS.SIGN_PAYMENT, accountIndex, CLA_OFFSET, payload); if (response.length === 1) throw "User has declined."; const decoded = proto_1.default.helium.blockchain_txn_payment_v2.decode(response); const signature = decoded.signature; txn.signature = signature; return { signature, txn, }; } /** * Sign a Helium `TokenBurnV1` transaction. * * @param txn a TokenBurnV1 transaction * @param accountIndex index of account address * * @returns an object with the signed transaction and signature * * @example * import { TokenBurnV1 } from '@helium/transactions' * const txn = new TokenBurnV1({ ... }) * helium.signTransaction(txn).then(r => r.signature) */ async signTokenBurnV1(txn, accountIndex = 0) { const payload = (0, serialization_1.serializeTokenBurnV1)(txn); const response = await this.sendToDevice(INS.SIGN_TOKEN_BURN, accountIndex, CLA_OFFSET, payload); if (response.length === 1) throw "User has declined."; const decoded = proto_1.default.helium.blockchain_txn_token_burn_v1.decode(response); const signature = decoded.signature; txn.signature = signature; return { signature, txn, }; } /** * Sign a Helium `StakeValidatorV1` transaction. * * @param txn a StakeValidatorV1 transaction * @param accountIndex index of account address * * @returns an object with the signed transaction and signature * * @example * import { StakeValidatorV1 } from '@helium/transactions' * const txn = new StakeValidatorV1({ ... }) * helium.signTransaction(txn).then(r => r.signature) */ async signStakeValidatorV1(txn, accountIndex = 0) { const payload = (0, serialization_1.serializeStakeValidatorV1)(txn); const response = await this.sendToDevice(INS.SIGN_VALIDATOR_STAKE, accountIndex, CLA_OFFSET, payload); if (response.length === 1) throw "User has declined."; const decoded = proto_1.default.helium.blockchain_txn_stake_validator_v1.decode(response); const signature = decoded.ownerSignature; txn.ownerSignature = signature; return { signature, txn, }; } /** * Sign a Helium `UnstakeValidatorV1` transaction. * * @param txn a UnstakeValidatorV1 transaction * @param accountIndex index of account address * * @returns an object with the signed transaction and signature * * @example * import { UnstakeValidatorV1 } from '@helium/transactions' * const txn = new UnstakeValidatorV1({ ... }) * helium.signTransaction(txn).then(r => r.signature) */ async signUnstakeValidatorV1(txn, accountIndex = 0) { const payload = (0, serialization_1.serializeUnstakeValidatorV1)(txn); const response = await this.sendToDevice(INS.SIGN_VALIDATOR_UNSTAKE, accountIndex, CLA_OFFSET, payload); if (response.length === 1) throw "User has declined."; const decoded = proto_1.default.helium.blockchain_txn_unstake_validator_v1.decode(response); const signature = decoded.ownerSignature; txn.ownerSignature = signature; return { signature, txn, }; } /** * Sign a Helium `TransferValidatorStakeV1` transaction. * * @param txn a TransferValidatorStakeV1 transaction * @param ownerType whether to sign as the old or new owner in the transfer * @param accountIndex index of account address * * @returns an object with the signed transaction and signature * * @example * import { TransferValidatorStakeV1 } from '@helium/transactions' * const txn = new TransferValidatorStakeV1({ ... }, 'old') * helium.signTransaction(txn).then(r => r.signature) */ async signTransferValidatorStakeV1(txn, ownerType, accountIndex = 0) { const payload = (0, serialization_1.serializeTransferValidatorStakeV1)(txn); const response = await this.sendToDevice(INS.SIGN_VALIDATOR_TXFER, accountIndex, CLA_OFFSET, payload); if (response.length === 1) throw "User has declined."; const decoded = proto_1.default.helium.blockchain_txn_transfer_validator_stake_v1.decode(response); const signature = decoded.oldOwnerSignature; if (ownerType === "old") { txn.oldOwnerSignature = signature; } if (ownerType === "new") { txn.newOwnerSignature = signature; } return { signature, txn, }; } /** * Sign a Helium `SecurityExchangeV1` transaction. * * @param txn a SecurityExchangeV1 transaction * @param accountIndex index of account address * * @returns an object with the signed transaction and signature * * @example * import { SecurityExchangeV1 } from '@helium/transactions' * const txn = new SecurityExchangeV1({ ... }) * helium.signTransaction(txn).then(r => r.signature) */ async signSecurityExchangeV1(txn, accountIndex = 0) { const payload = (0, serialization_1.serializeSecurityExchangeV1)(txn); const response = await this.sendToDevice(INS.SIGN_TRANSFER_SEC_TXN, accountIndex, CLA_OFFSET, payload); if (response.length === 1) throw "User has declined."; const decoded = proto_1.default.helium.blockchain_txn_security_exchange_v1.decode(response); const signature = decoded.signature; txn.signature = signature; return { signature, txn, }; } async sendToDevice(instruction, p1, p2 = 0x00, payload) { const acceptStatusList = [errors_1.StatusCodes.OK]; const reply = await this.transport.send(LEDGER_CLA, instruction, p1, p2, payload, acceptStatusList); this.throwOnFailure(reply); return reply.slice(0, reply.length - 2); } throwOnFailure(reply) { // transport makes sure reply has a valid length const status = reply.readUInt16BE(reply.length - 2); switch (status) { default: return; } } } exports.default = Helium; //# sourceMappingURL=Helium.js.map