import { bytes, dec, hex } from './convert'
import { NanoNaCl } from './nano-nacl'
import { Rpc } from './rpc'
+import { Wallet } from './wallet'
/**
* Represents a block as defined by the Nano cryptocurrency protocol. The Block
*
* @param {string} [key] - Hexadecimal-formatted private key to use for signing
*/
- async sign (key?: string): Promise<string>
+ async sign (key: string): Promise<Block>
+ /**
+ * Signs the block using a Wallet. If successful, the result is stored in
+ * the object's `signature` property. The wallet must be unlocked prior to
+ * signing.
+ *
+ * @param {Wallet} wallet - Wallet to use for signing
+ * @param {number} index - Account in wallet to use for signing
+ */
+ async sign (wallet: Wallet, index: number): Promise<Block>
/**
* Signs the block using a Ledger hardware wallet. If that fails, an error is
* thrown with the status code from the device.
* @param {number} index - Account index between 0x0 and 0x7fffffff
* @param {object} [frontier] - JSON of frontier block for offline signing
*/
- async sign (index?: number, frontier?: ChangeBlock | ReceiveBlock | SendBlock): Promise<string>
- async sign (input?: number | string, frontier?: ChangeBlock | ReceiveBlock | SendBlock): Promise<string> {
- if (typeof input === 'number') {
- const index = input
- const { Ledger } = await import('./ledger')
- const ledger = await Ledger.create()
- await ledger.connect()
- if (frontier) {
- try {
- await ledger.updateCache(index, frontier)
- } catch (err) {
- console.warn('Error updating Ledger cache of previous block, attempting signature anyway', err)
- }
- }
- try {
- this.signature = await ledger.sign(index, this as SendBlock | ReceiveBlock | ChangeBlock)
- return this.signature
- } catch (err) {
- throw new Error('Failed to sign block with Ledger', { cause: err })
- }
- } else if (typeof input === 'string') {
- try {
+ async sign (index: number, frontier?: Block): Promise<Block>
+ async sign (input: unknown, param?: unknown): Promise<Block> {
+ try {
+ if (typeof input !== 'string' && typeof input !== 'number' && !(input instanceof Wallet)) {
+ throw new TypeError('Invalid input')
+
+ } else if (typeof input === 'string') {
const sig = await NanoNaCl.detached(hex.toBytes(this.hash), hex.toBytes(input))
this.signature = bytes.toHex(sig)
- return this.signature
- } catch (err) {
- throw new Error(`Failed to sign block with private key`, { cause: err })
+ return this
+
+ } else if (input instanceof Wallet && typeof param === 'number') {
+ const sig = await input.sign(param, this as SendBlock | ReceiveBlock | ChangeBlock)
+ if (this.signature !== sig) {
+ throw new Error('Wallet signature does not match block signature')
+ }
+ return this
+
+ } else if (typeof input === 'number') {
+ const index = input
+ const { Ledger } = await import('./ledger')
+ const ledger = await Ledger.create()
+ await ledger.connect()
+ if (param && (param instanceof ChangeBlock || param instanceof ReceiveBlock || param instanceof SendBlock)) {
+ try {
+ await ledger.updateCache(index, param)
+ } catch (err) {
+ console.warn('Error updating Ledger cache of previous block, attempting signature anyway', err)
+ }
+ }
+ this.signature = await ledger.sign(index, this as SendBlock | ReceiveBlock | ChangeBlock)
+ return this
+
+ } else {
+ throw new TypeError('invalid key for block signature', { cause: typeof input })
}
- } else {
- throw new TypeError('invalid key for block signature', { cause: typeof input })
+ } catch (err) {
+ console.error(err)
+ throw new Error('Failed to sign block', { cause: err })
}
+
}
/**