]> git.codecow.com Git - libnemo.git/commitdiff
Scrap overcomplicated block methods to and from.
authorChris Duncan <chris@zoso.dev>
Thu, 7 Aug 2025 18:39:44 +0000 (11:39 -0700)
committerChris Duncan <chris@zoso.dev>
Thu, 7 Aug 2025 18:39:44 +0000 (11:39 -0700)
src/lib/block.ts
src/lib/ledger.ts
src/lib/tools.ts

index 44b8be7707a6c352f00901f2c3ce225b5af2f1fc..b88d36042aa99d1e15eebc729d55b4648466a7d8 100644 (file)
@@ -176,57 +176,39 @@ export class Block {
        }
 
        /**
-       * Set the subtype and link to configure this as a change representative block.
+       * Set the subtype, link, and target account to configure this as a change
+       * representative block.
        *
-       * @returns {Block} This block so that additional calls can be chained
+       * @param {(string|Account)} account - Account to choose as representative, or its address or public key
+       * @returns {Block} This block with link, representative, and subtype configured
        */
-       change (): Block {
-               if (this.subtype != null) {
-                       throw new Error(`Block is already configured as ${this.subtype}`)
-               }
+       change (representative: string | Account): Block
+       change (representative: unknown): Block {
+               const { link, representative: rep, subtype } = this
                try {
+                       if (this.subtype != null) {
+                               throw new Error(`Block already configured as ${this.subtype}`)
+                       }
                        this.subtype = 'change'
+
+                       if (typeof representative !== 'string' && !(representative instanceof Account)) {
+                               throw new TypeError('Invalid account')
+                       }
+                       this.representative = (typeof representative === 'string')
+                               ? Account.import(representative)
+                               : representative
+
                        this.link = hex.toBytes(BURN_PUBLIC_KEY)
 
                        return this
                } catch (err) {
-                       this.subtype = undefined
-                       this.link = undefined
+                       this.link = link
+                       this.representative = rep
+                       this.subtype = subtype
                        throw new TypeError('Failed to configure send block', { cause: err })
                }
        }
 
-       /**
-       * Set a block hash as the source send of a receive block.
-       *
-       * @param {string} hash - Hash of send block to be received
-       * @returns {Block} This block so that additional calls can be chained
-       */
-       from (hash: string): Block
-       /**
-       * Set a send block as the source of a receive block.
-       *
-       * @param {Block} block - Send block to be received
-       * @returns {Block} This block so that additional calls can be chained
-       */
-       from (block: Block): Block
-       from (send: unknown): Block {
-               try {
-                       if (typeof send !== 'string' && !(send instanceof Block)) {
-                               throw new TypeError('Invalid send to be received')
-                       }
-                       if (this.subtype !== 'receive') {
-                               throw new TypeError('Invalid subtype')
-                       }
-                       this.link = (typeof send === 'string')
-                               ? hex.toBytes(send)
-                               : send.hash
-                       return this
-               } catch (err) {
-                       throw new Error('Failed to receive a corresponding send', { cause: err })
-               }
-       }
-
        /**
        * Calculates proof-of-work using a pool of Web Workers.
        *
@@ -288,54 +270,45 @@ export class Block {
        }
 
        /**
-       * Set the amount of nano that this block will receive from a paired send.
-       *
-       * @param {bigint} amount - Amount that was sent from sender in raw
-       * @returns {Block} This block so that additional calls can be chained
-       */
-       receive (amount: bigint): Block
-       /**
-       * Set the amount of nano that this block will receive from a paired send.
-       *
-       * @param {number} amount - Amount that was sent from sender in nano (10³⁰ raw)
-       * @returns {Block} This block so that additional calls can be chained
-       */
-       receive (amount: number): Block
-       /**
-       * Set the amount of nano that this block will receive from a paired send.
+       * Set the amount of nano that this block will receive from a corresponding
+       * send block.
        *
-       * @param {string} amount - Amount that was sent from sender in raw
-       * @returns {Block} This block so that additional calls can be chained
+       * @param {(string|Block)} sendBlock - Corresponding send block or its hash
+       * @param {(bigint|number|string)} amount - Amount to be received from sender
+       * @param {string} [unit] - Unit of measure for amount. Default: "NANO" (10³⁰ RAW)
+       * @returns {Block} This block with balance, link, and subtype configured
        */
-       receive (amount: string): Block
-       receive (amount: unknown): Block {
-               const currentBalance = this.balance
+       receive (sendBlock: string | Block, amount: bigint | number | string, unit?: string): Block
+       receive (sendBlock: unknown, amount: unknown, unit: unknown): Block {
+               const { balance, link, subtype } = this
                try {
                        if (this.subtype != null) {
-                               throw new Error(`Block is already configured as ${this.subtype}`)
+                               throw new Error(`Block already configured as ${this.subtype}`)
                        }
                        this.subtype = 'receive'
-                       switch (typeof amount) {
-                               case 'bigint': {
-                                       this.balance += amount
-                                       break
-                               }
-                               case 'number': {
-                                       this.balance += BigInt(amount) * (1n << 30n)
-                                       break
-                               }
-                               case 'string': {
-                                       this.balance += BigInt(amount)
-                                       break
-                               }
-                               default: {
-                                       throw new TypeError('Invalid amount')
-                               }
+
+                       unit ??= UNITS.RAW
+                       if (typeof unit !== 'string' || typeof UNITS[unit] !== 'number') {
+                               throw new TypeError('Invalid unit')
                        }
+
+                       if (typeof amount !== 'bigint' && typeof amount !== 'number' && typeof amount !== 'string') {
+                               throw new TypeError('Invalid amount')
+                       }
+                       this.balance += BigInt(amount) * (1n << BigInt(UNITS[unit.toUpperCase()]))
+
+                       if (typeof sendBlock !== 'string' && !(sendBlock instanceof Block)) {
+                               throw new TypeError('Invalid send block')
+                       }
+                       this.link = (typeof sendBlock === 'string')
+                               ? hex.toBytes(sendBlock)
+                               : sendBlock.hash
+
                        return this
                } catch (err) {
-                       this.subtype = undefined
-                       this.balance = currentBalance
+                       this.balance = balance
+                       this.link = link
+                       this.subtype = subtype
                        throw new TypeError('Failed to configure receive block', { cause: err })
                }
        }
@@ -343,52 +316,46 @@ export class Block {
        /**
        * Set the amount of nano that this block will send to a recipient account.
        *
-       * @param {bigint} amount - Amount to send to recipient in raw
-       * @returns {Block} This block so that additional calls can be chained
-       */
-       send (amount: bigint): Block
-       /**
-       * Set the amount of nano that this block will send to a recipient account.
-       *
-       * @param {number} amount - Amount to send to recipient in nano (10³⁰ raw)
-       * @returns {Block} This block so that additional calls can be chained
-       */
-       send (amount: number): Block
-       /**
-       * Set the amount of nano that this block will send to a recipient account.
-       *
-       * @param {string} amount - Amount to send to recipient in raw
-       * @returns {Block} This block so that additional calls can be chained
+       * @param {(string|Account)} account - Account to target or its address or public key
+       * @param {(bigint|number|string)} amount - Amount to send to recipient
+       * @param {string} [unit] - Unit of measure for amount. Default: "NANO" (10³⁰ RAW)
+       * @returns {Block} This block with balance, link, and subtype configured
        */
-       send (amount: string): Block
-       send (amount: unknown): Block {
-               const currentBalance = this.balance
+       send (account: string | Account, amount: bigint | number | string, unit?: string): Block
+       send (account: unknown, amount: unknown, unit: unknown): Block {
+               const { balance, link, subtype } = this
                try {
                        if (this.subtype != null) {
-                               throw new Error(`Block is already configured as ${this.subtype}`)
+                               throw new Error(`Block already configured as ${this.subtype}`)
                        }
                        this.subtype = 'send'
-                       switch (typeof amount) {
-                               case 'bigint': {
-                                       this.balance -= amount
-                                       break
-                               }
-                               case 'number': {
-                                       this.balance -= BigInt(amount) * (1n << 30n)
-                                       break
-                               }
-                               case 'string': {
-                                       this.balance -= BigInt(amount)
-                                       break
-                               }
-                               default: {
-                                       throw new TypeError('Invalid amount')
-                               }
+
+                       unit ??= UNITS.RAW
+                       if (typeof unit !== 'string' || typeof UNITS[unit] !== 'number') {
+                               throw new TypeError('Invalid unit')
+                       }
+
+                       if (typeof amount !== 'bigint' && typeof amount !== 'number' && typeof amount !== 'string') {
+                               throw new TypeError('Invalid amount')
+                       }
+                       this.balance -= BigInt(amount) * (1n << BigInt(UNITS[unit.toUpperCase()]))
+
+                       if (this.balance < 0) {
+                               throw new RangeError('Insufficient funds', { cause: this.balance })
                        }
+
+                       if (typeof account !== 'string' && !(account instanceof Account)) {
+                               throw new TypeError('Invalid account')
+                       }
+                       this.link = (typeof account === 'string')
+                               ? hex.toBytes(Account.import(account).publicKey)
+                               : hex.toBytes(account.publicKey)
+
                        return this
                } catch (err) {
-                       this.subtype = undefined
-                       this.balance = currentBalance
+                       this.balance = balance
+                       this.link = link
+                       this.subtype = subtype
                        throw new TypeError('Failed to configure send block', { cause: err })
                }
        }
@@ -474,50 +441,6 @@ export class Block {
 
        }
 
-       /**
-       * Set the recipient of a send block or the target representative of a change
-       * block.
-       *
-       * @param {string} account - Address or public key of Account to target
-       * @returns {Block} This block so that additional calls can be chained
-       */
-       to (account: string): Block
-       /**
-       * Set the recipient of a send block or the target representative of a change
-       * block.
-       *
-       * @param {Account} account - Account to target
-       * @returns {Block} This block so that additional calls can be chained
-       */
-       to (account: Account): Block
-       to (account: unknown): Block {
-               try {
-                       if (typeof account !== 'string' && !(account instanceof Account)) {
-                               throw new TypeError('Invalid account')
-                       }
-                       switch (this.subtype) {
-                               case 'change': {
-                                       this.representative = (typeof account === 'string')
-                                               ? Account.import(account)
-                                               : account
-                                       break
-                               }
-                               case 'send': {
-                                       this.link = (typeof account === 'string')
-                                               ? hex.toBytes(Account.import(account).publicKey)
-                                               : hex.toBytes(account.publicKey)
-                                       break
-                               }
-                               default: {
-                                       throw new TypeError('Invalid subtype')
-                               }
-                       }
-                       return this
-               } catch (err) {
-                       throw new Error('Failed to change to, or send to, an Account', { cause: err })
-               }
-       }
-
        /**
        * Verifies the signature of the block. If a key is not provided, the public
        * key of the block's account will be used if it exists.
index 79da5bbbf0c4b36d79d60f5f6242f34fdd7b0c8d..962cfee3310649bb68283a3b89222e28c62c9ec0 100644 (file)
@@ -356,12 +356,10 @@ export class Ledger extends Wallet {
                await testWallet.unlock('')\r
                const testAccount = await testWallet.account(0)\r
                const testOpenBlock = new Block(testAccount.address, '0', testAccount.publicKey, testAccount.address,)\r
-                       .receive('0')\r
-                       .from(testAccount.publicKey)\r
+                       .receive(testAccount.publicKey, 0)\r
                await testWallet.sign(0, testOpenBlock)\r
                const testSendBlock = new Block(testAccount.address, '0', bytes.toHex(testOpenBlock.hash), testAccount.address)\r
-                       .send(0)\r
-                       .to(testAccount.address)\r
+                       .send(testAccount.address, 0)\r
                const testSignature = await testWallet.sign(0, testOpenBlock, 'hex')\r
                try {\r
                        const signature = await this.sign(0, testSendBlock, 'hex', testOpenBlock)\r
index 727c508677a97cc18bb4d0ed0e1d8aec182d71fe..94e81193f1cb297dbd5387c45ee07aa7877053f1 100644 (file)
@@ -137,8 +137,7 @@ export async function sweep (
        for (const account of accounts) {
                if (account.representative?.address && account.frontier && account.index) {
                        const block = await (await new Block(account)
-                               .send(account.balance ?? 0n)
-                               .to(recipientAccount)
+                               .send(recipientAccount, account.balance ?? 0n)
                                .pow())
                                .sign(wallet, account.index)
                        const blockRequest: Promise<void> = new Promise(async (resolve) => {