import { Wallet } from '../wallet'
import { _account } from './account'
import { _cache } from './cache'
-import { _connect } from './connect'
-import { queue } from './queue'
-import { signBlock, signNonce } from './sign'
-import { _open } from './open'
import { _close } from './close'
+import { _connect } from './connect'
import { _disconnect } from './disconnect'
+import { _open } from './open'
+import { queue } from './queue'
+import { _sign } from './sign'
export type LedgerStatus = 'UNSUPPORTED' | 'DISCONNECTED' | 'BUSY' | 'LOCKED' | 'CONNECTED'
export type LedgerTransport = typeof TransportHID | typeof TransportBLE | typeof TransportUSB
*/
static async sign (index: number, block: Block, frontier?: Block): Promise<string>
static async sign (index: number, data: string | Block, frontier?: Block): Promise<string> {
- try {
- if (typeof index !== 'number') {
- throw new TypeError('Index must be a number', { cause: index })
- }
- if (index < 0 || index >= HARDENED_OFFSET) {
- throw new RangeError(`Index outside allowed range 0-${HARDENED_OFFSET}`, { cause: index })
- }
- if (typeof data !== 'string' && !(data instanceof Block)) {
- throw new TypeError('Data to be signed must be a string nonce or a Block', { cause: data })
- }
- if (frontier != null) {
- const { status } = await _cache(this.#transport, index, frontier)
- if (status !== 'OK') {
- throw new Error('Failed to cache frontier block in ledger', { cause: status })
- }
- }
- console.log('Waiting for signature confirmation on Ledger device...')
- const { status, signature, hash } = data instanceof Block
- ? await signBlock(this.#transport, index, data)
- : await signNonce(this.#transport, index, utf8.toBytes(data))
- if (status !== 'OK') {
- throw new Error('Signing with ledger failed', { cause: status })
- }
- if (data instanceof Block && hash !== data.hash) {
- throw new Error('Hash from Ledger does not match hash from block', { cause: `${hash} | ${data.hash}` })
- }
- if (signature == null) {
- throw new Error('Ledger silently failed to return signature')
- }
- return signature
- } catch (err) {
- console.error('Ledger.sign()', err)
- throw new Error('Failed to sign block with Ledger', { cause: err })
- }
+ return queue(async () => _sign(this.#transport, index, data, frontier))
}
/**
import { Account } from '../account'
import { Block } from '../block'
import { HARDENED_OFFSET } from '../constants'
-import { bytes, dec, hex } from '../convert'
+import { bytes, dec, hex, utf8 } from '../convert'
+import { _cache } from './cache'
import { queue } from './queue'
+export async function _sign (transport: LedgerTransport, index: number, data: string | Block, frontier?: Block): Promise<string> {
+ try {
+ if (typeof index !== 'number') {
+ throw new TypeError('Index must be a number', { cause: index })
+ }
+ if (index < 0 || index >= HARDENED_OFFSET) {
+ throw new RangeError(`Index outside allowed range 0-${HARDENED_OFFSET}`, { cause: index })
+ }
+ if (typeof data !== 'string' && !(data instanceof Block)) {
+ throw new TypeError('Data to be signed must be a string nonce or a Block', { cause: data })
+ }
+ if (frontier != null) {
+ const { status } = await _cache(transport, index, frontier)
+ if (status !== 'OK') {
+ throw new Error('Failed to cache frontier block in ledger', { cause: status })
+ }
+ }
+ console.log('Waiting for signature confirmation on Ledger device...')
+ const { status, signature, hash } = data instanceof Block
+ ? await signBlock(transport, index, data)
+ : await signNonce(transport, index, utf8.toBytes(data))
+ if (status !== 'OK') {
+ throw new Error('Signing with ledger failed', { cause: status })
+ }
+ if (data instanceof Block && hash !== data.hash) {
+ throw new Error('Hash from Ledger does not match hash from block', { cause: `${hash} | ${data.hash}` })
+ }
+ if (signature == null) {
+ throw new Error('Ledger silently failed to return signature')
+ }
+ return signature
+ } catch (err) {
+ console.error('Ledger.sign()', err)
+ throw new Error('Failed to sign block with Ledger', { cause: err })
+ }
+}
+
/**
* Sign a block with the Ledger device.
*
* @param {object} block - Block data to sign
* @returns {Promise} Status, signature, and block hash
*/
-export async function signBlock (transport: LedgerTransport, index: number, block: Block): Promise<LedgerSignResponse> {
+async function signBlock (transport: LedgerTransport, index: number, block: Block): Promise<LedgerSignResponse> {
if (block.signature !== undefined) {
throw new TypeError('Block signature already exists', { cause: block.signature })
}
* @param {Uint8Array} nonce - 128-bit value to sign
* @returns {Promise} Status and signature
*/
-export async function signNonce (transport: LedgerTransport, index: number, nonce: Uint8Array<ArrayBuffer>): Promise<LedgerSignResponse> {
+async function signNonce (transport: LedgerTransport, index: number, nonce: Uint8Array<ArrayBuffer>): Promise<LedgerSignResponse> {
return queue<LedgerSignResponse>(async () => {
if (typeof index !== 'number' || index < 0 || index >= HARDENED_OFFSET) {
throw new TypeError('Invalid account index')