UNPKG

@aeternity/aepp-sdk

Version:

SDK for the æternity blockchain

116 lines (111 loc) 4.33 kB
import { Buffer as _Buffer } from "buffer"; import AccountBase from './Base.js'; import { ArgumentError, NotImplementedError } from '../utils/errors.js'; import { decode } from '../utils/encoder.js'; import { buildTx } from '../tx/builder/index.js'; import { Tag } from '../tx/builder/constants.js'; export const CLA = 0xe0; export const GET_ADDRESS = 0x02; export const SIGN_TRANSACTION = 0x04; export const GET_APP_CONFIGURATION = 0x06; export const SIGN_PERSONAL_MESSAGE = 0x08; /** * Ledger wallet account class * @category account */ export default class AccountLedger extends AccountBase { /** * @param transport - Connection to Ledger to use * @param index - Index of account * @param address - Address of account */ constructor(transport, index, address) { super(); this.transport = transport; this.index = index; this.address = address; transport.decorateAppAPIMethods(this, ['signTransaction', 'signMessage'], 'w0w'); } /** * @deprecated Use `unsafeSign` method instead */ // eslint-disable-next-line class-methods-use-this async sign() { return this.unsafeSign(); } // eslint-disable-next-line class-methods-use-this async unsafeSign() { throw new NotImplementedError('RAW signing using Ledger HW'); } // eslint-disable-next-line class-methods-use-this async signTypedData() { throw new NotImplementedError('Typed data signing using Ledger HW'); } // eslint-disable-next-line class-methods-use-this async signDelegation() { throw new NotImplementedError('signing delegation using Ledger HW'); } async signTransaction(tx, { innerTx, networkId } = {}) { if (innerTx != null) throw new NotImplementedError('innerTx option in AccountLedger'); if (networkId == null) throw new ArgumentError('networkId', 'provided', networkId); const rawTx = decode(tx); let offset = 0; const headerLength = 4 + 1 + 4; const networkIdBuffer = _Buffer.from(networkId); const toSend = []; while (offset !== rawTx.length) { const maxChunkSize = offset === 0 ? 150 - headerLength - networkIdBuffer.length : 150; const chunkSize = offset + maxChunkSize > rawTx.length ? rawTx.length - offset : maxChunkSize; const buffer = _Buffer.alloc(offset === 0 ? headerLength + networkIdBuffer.length + chunkSize : chunkSize); if (offset === 0) { let bufferOffset = buffer.writeUInt32BE(this.index, 0); bufferOffset = buffer.writeUInt32BE(rawTx.length, bufferOffset); bufferOffset = buffer.writeUInt8(networkIdBuffer.length, bufferOffset); bufferOffset += networkIdBuffer.copy(buffer, bufferOffset, 0, networkIdBuffer.length); rawTx.copy(buffer, bufferOffset, 0, 150 - bufferOffset); } else { rawTx.copy(buffer, 0, offset, offset + chunkSize); } toSend.push(buffer); offset += chunkSize; } const response = await toSend.reduce(async (previous, data, i) => { await previous; return this.transport.send(CLA, SIGN_TRANSACTION, i === 0 ? 0x00 : 0x80, 0x00, data); }, Promise.resolve(_Buffer.alloc(0))); const signatures = [response.subarray(0, 64)]; return buildTx({ tag: Tag.SignedTx, encodedTx: rawTx, signatures }); } async signMessage(messageStr) { let offset = 0; const message = _Buffer.from(messageStr); const toSend = []; while (offset !== message.length) { const maxChunkSize = offset === 0 ? 150 - 4 - 4 : 150; const chunkSize = offset + maxChunkSize > message.length ? message.length - offset : maxChunkSize; const buffer = _Buffer.alloc(offset === 0 ? 4 + 4 + chunkSize : chunkSize); if (offset === 0) { buffer.writeUInt32BE(this.index, 0); buffer.writeUInt32BE(message.length, 4); message.copy(buffer, 4 + 4, offset, offset + chunkSize); } else { message.copy(buffer, 0, offset, offset + chunkSize); } toSend.push(buffer); offset += chunkSize; } const response = await toSend.reduce(async (previous, data, i) => { await previous; return this.transport.send(CLA, SIGN_PERSONAL_MESSAGE, i === 0 ? 0x00 : 0x80, 0x00, data); }, Promise.resolve(_Buffer.alloc(0))); return response.subarray(0, 64); } } //# sourceMappingURL=Ledger.js.map