@ledgerhq/hw-app-helium
Version:
Ledger Hardware Wallet Helium Application API
261 lines • 9.71 kB
JavaScript
;
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