]> git.codecow.com Git - libnemo.git/commitdiff
Refactor block signing method to include wallet option.
authorChris Duncan <chris@zoso.dev>
Wed, 6 Aug 2025 04:21:57 +0000 (21:21 -0700)
committerChris Duncan <chris@zoso.dev>
Wed, 6 Aug 2025 04:21:57 +0000 (21:21 -0700)
src/lib/block.ts

index 5148f5aed0e0a5fe8ebdcfada01af2b0456ace22..0261a3bc3f466c5afe74b0735bb2db604e6b3e2e 100644 (file)
@@ -8,6 +8,7 @@ import { BURN_ADDRESS, PREAMBLE, DIFFICULTY_RECEIVE, DIFFICULTY_SEND } from './c
 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
@@ -292,7 +293,16 @@ abstract class 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.
@@ -303,37 +313,47 @@ abstract class Block {
        * @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 })
                }
+
        }
 
        /**