]> git.codecow.com Git - libnemo.git/commitdiff
Refactor accounts to instantiate synchronously. Remove index from accounts since...
authorChris Duncan <chris@zoso.dev>
Mon, 13 Apr 2026 05:32:57 +0000 (22:32 -0700)
committerChris Duncan <chris@zoso.dev>
Mon, 13 Apr 2026 05:32:57 +0000 (22:32 -0700)
src/lib/account/index.ts
src/lib/block.ts
src/lib/rolodex.ts
src/lib/tools.ts
src/lib/wallet/accounts.ts
test/test.derive-accounts.mjs
test/test.import-wallet.mjs
test/test.refresh-accounts.mjs
test/test.wallet-sign.mjs

index 5c5e2ffb1e38b030a740e290b56146f6095dc1e8..817239789495b53fa7ed345ce274ad7aadd4eb9f 100644 (file)
@@ -10,12 +10,6 @@ import { Address } from './address'
 import { _refresh } from './refresh'\r
 import { _validate } from './validate'\r
 \r
-type KeyPair = {\r
-       index?: number\r
-       privateKey?: string | Uint8Array<ArrayBuffer>\r
-       publicKey?: string | Uint8Array<ArrayBuffer>\r
-}\r
-\r
 /**\r
  * Represents a single Nano address and the associated public key. To include\r
  * the matching private key, it must be known at the time of object\r
@@ -25,16 +19,11 @@ type KeyPair = {
 export class Account {\r
        [key: string]: any\r
 \r
-       static #isInternal: boolean = false\r
-       static get isInternal (): boolean { return this.#isInternal }\r
-       /**\r
-       * @returns {'Account'}\r
-       */\r
+       /** @returns {'Account'} */\r
        static get DB_NAME (): 'Account' { return 'Account' }\r
 \r
+       #publicKey: Uint8Array<ArrayBuffer> = new Uint8Array(32)\r
        #address?: Address\r
-       #index?: number\r
-       #publicKey: Uint8Array<ArrayBuffer>\r
 \r
        #confirmed_balance?: bigint\r
        #confirmed_height?: number\r
@@ -53,14 +42,13 @@ export class Account {
        #representative_block?: string\r
        #weight?: bigint\r
 \r
+       get publicKey (): string { return bytes.toHex(this.#publicKey) }\r
        get address (): string {\r
-               if (this.#address == null) {\r
+               if (this.#address === undefined) {\r
                        throw new Error('Account not found')\r
                }\r
                return this.#address.toString()\r
        }\r
-       get index (): number | undefined { return this.#index }\r
-       get publicKey (): string { return bytes.toHex(this.#publicKey) }\r
 \r
        get confirmed_balance (): bigint | undefined { return this.#confirmed_balance }\r
        get confirmed_height (): number | undefined { return this.#confirmed_height }\r
@@ -88,7 +76,7 @@ export class Account {
                if (v instanceof (this.constructor as typeof Account)) {\r
                        this.#confirmed_representative = v\r
                } else if (typeof v === 'string') {\r
-                       this.#confirmed_representative = (this.constructor as typeof Account).load(v)\r
+                       this.#confirmed_representative = new Account(v)\r
                } else {\r
                        throw new TypeError(`Invalid argument for account confirmed representative: ${v}`)\r
                }\r
@@ -104,7 +92,7 @@ export class Account {
                if (v instanceof (this.constructor as typeof Account) || v === undefined) {\r
                        this.#representative = v\r
                } else if (typeof v === 'string') {\r
-                       this.#representative = (this.constructor as typeof Account).load(v)\r
+                       this.#representative = new Account(v)\r
                } else {\r
                        throw new TypeError(`Invalid argument for account representative: ${v}`)\r
                }\r
@@ -112,22 +100,12 @@ export class Account {
        set representative_block (v: string | undefined) { this.#representative_block = v }\r
        set weight (v: bigint | number | string) { this.#weight = BigInt(v) }\r
 \r
-       private constructor (address: Address, publicKey: Uint8Array<ArrayBuffer>, index?: number) {\r
-               if (!(this.constructor as typeof Account).isInternal) {\r
-                       throw new Error('Account cannot be instantiated directly. Use `load()` instead.')\r
-               }\r
-               this.#address = address\r
-               this.#publicKey = publicKey\r
-               this.#index = index\r
-       }\r
-\r
        /**\r
         * Releases variable references to allow garbage collection.\r
         */\r
        destroy (): void {\r
-               this.#address = undefined\r
-               this.#index = undefined\r
                this.#publicKey.fill(0)\r
+               this.#address = undefined\r
 \r
                this.#confirmed_balance = undefined\r
                this.#confirmed_height = undefined\r
@@ -153,9 +131,8 @@ export class Account {
         */\r
        toJSON () {\r
                return {\r
-                       address: this.address,\r
-                       index: this.index,\r
                        publicKey: this.publicKey,\r
+                       address: this.address,\r
                        confirmed_balance: this.confirmed_balance?.toString(),\r
                        confirmed_height: this.confirmed_height?.toString(),\r
                        confirmed_frontier: this.confirmed_frontier,\r
@@ -177,55 +154,60 @@ export class Account {
         * @param {string} address - Address of the account\r
         * @returns {Account} A new Account object\r
         */\r
-       static load (address: string): Account\r
+       constructor (address: string)\r
        /**\r
-        * Instantiates Account objects from their Nano addresses.\r
-        * @param {string[]} addresses - Addresses of the accounts\r
-        * @returns {Account[]} Array of new Account objects\r
-        */\r
-       static load (addresses: string[]): Account[]\r
-       /**\r
-        * Instantiates an Account object from its public key. It is unable to sign\r
-        * blocks or messages since it has no private key.\r
-        * @param {string | Uint8Array<ArrayBuffer>} publicKey - Public key of the account\r
+        * Instantiates an Account object from its public key.\r
+        * @param {(string | Uint8Array<ArrayBuffer>)} publicKey - Public key of the account\r
         * @returns {Account} A new Account object\r
         */\r
-       static load (publicKey: string | Uint8Array<ArrayBuffer>): Account\r
-       /**\r
-        * Instantiates Account objects from their public keys. They are unable to sign\r
-        * blocks or messages since they have no private key.\r
-        * @param {string | Uint8Array<ArrayBuffer>[]} publicKeys - Public keys of the accounts\r
-        * @returns {Account[]} Array of new Account objects\r
-        */\r
-       static load (publicKeys: string | Uint8Array<ArrayBuffer>[]): Account[]\r
+       constructor (publicKey: string | ArrayBuffer | Uint8Array<ArrayBuffer>)\r
        /**\r
-        * Instantiates an Account object from its public key. It is unable to sign\r
-        * blocks or messages since it has no private key.\r
-        * @param {KeyPair} keypair - Index and keys of the account\r
+        * Instantiates an Account object from its public or private key.\r
+        *\r
+        * If the key is indicated as private, then it is copied locally, used to\r
+        * derive the corresponding public key, and finally zeroed out; the user is\r
+        * responsible for securely handling the original input.\r
+        * @param {(string | Uint8Array<ArrayBuffer>)} key - Public or private key of the account\r
+        * @param {string} type - Indicates which type the key is\r
         * @returns {Account} A new Account object\r
         */\r
-       static load (keypair: KeyPair): Account\r
-       /**\r
-        * Instantiates Account objects from their public keys. They are unable to sign\r
-        * blocks or messages since they have no private key.\r
-        * @param {KeyPair[]} keypairs - Indexes and keys of the accounts\r
-        * @returns {Account[]} Array of new Account objects\r
-        */\r
-       static load (keypairs: KeyPair[]): Account[]\r
-       /**\r
-        * Instantiates Account objects from their private keys which are used to\r
-        * derive public keys and then discarded.\r
-        * @param {(string | Uint8Array<ArrayBuffer> | KeyPair | (string | Uint8Array<ArrayBuffer> | KeyPair)[])} input - Indexes and keys of the accounts\r
-        * @returns {(Account | Account[])} Array of new Account objects\r
-        */\r
-       static load (input: string | Uint8Array<ArrayBuffer> | KeyPair | (string | Uint8Array<ArrayBuffer> | KeyPair)[], type?: 'private'): Account | Account[] {\r
-               const isInputArray = Array.isArray(input)\r
-               const inputs = isInputArray ? input : [input]\r
-               if (this.#isKeyPairs(inputs) && type === 'private') {\r
-                       const r = this.#fromPrivate(inputs)\r
-                       return isInputArray ? r : r[0]\r
+       constructor (key: string | ArrayBuffer | Uint8Array<ArrayBuffer>, type: 'public' | 'private')\r
+       constructor (input: unknown, type: unknown = 'public') {\r
+               if (type === 'private') {\r
+                       try {\r
+                               if (typeof input === 'string' && RegExp(`^[A-F0-9]{${ACCOUNT_KEY_HEX_LENGTH}}$`, 'i').test(input)) {\r
+                                       input = hex.toBytes(input)\r
+                               }\r
+                               if (input instanceof Uint8Array) {\r
+                                       input = input.buffer\r
+                               }\r
+                               if (!(input instanceof ArrayBuffer) || input.byteLength !== ACCOUNT_KEY_BYTE_LENGTH) {\r
+                                       throw new TypeError('Invalid private key')\r
+                               }\r
+                               const prv = new Uint8Array(input.slice())\r
+                               try {\r
+                                       this.#publicKey = nano25519_derive(prv)\r
+                                       this.#address = new Address(this.#publicKey)\r
+                               } finally {\r
+                                       prv.fill(0)\r
+                               }\r
+                       } catch (err) {\r
+                               throw new Error('Failed to import Account from private key', { cause: err })\r
+                       }\r
                } else {\r
-                       return isInputArray ? this.#fromPublic(inputs) : this.#fromPublic(inputs)[0]\r
+                       try {\r
+                               if (input instanceof Uint8Array) {\r
+                                       input = input.buffer\r
+                               }\r
+                               if (typeof input !== 'string' && !(input instanceof ArrayBuffer)) {\r
+                                       throw new TypeError('Invalid argument')\r
+                               }\r
+                               this.#address = new Address(input)\r
+                               this.#publicKey = this.#address.toPublicKey()\r
+                       } catch (err) {\r
+                               console.error(err)\r
+                               throw new TypeError('Failed to import Account from public data', { cause: { err } })\r
+                       }\r
                }\r
        }\r
 \r
@@ -248,121 +230,4 @@ export class Account {
        static validate (address: string): asserts address is string {\r
                return _validate(address)\r
        }\r
-\r
-       /**\r
-       * Instantiates an Account object from its private key which is used to derive\r
-       * the corresponding public key and then discarded.\r
-       *\r
-       * @param {KeyPair} keypairs - Indexes and keys of the accounts\r
-       * @returns {Promise<Account[]>} Promise for new Account objects\r
-       */\r
-       static #fromPrivate (keypairs: KeyPair[]): Account[] {\r
-               try {\r
-                       const accounts: Account[] = []\r
-                       for (let keypair of keypairs) {\r
-                               let { index, privateKey } = keypair\r
-                               if (index == null) {\r
-                                       throw new RangeError('Index missing for Account')\r
-                               }\r
-                               if (typeof privateKey === 'string' && RegExp(`^[A-F0-9]{${ACCOUNT_KEY_HEX_LENGTH}}$`, 'i').test(privateKey)) {\r
-                                       privateKey = hex.toBytes(privateKey)\r
-                               }\r
-                               if (!(privateKey instanceof Uint8Array) || privateKey.every(v => v === 0)) {\r
-                                       throw new TypeError('Invalid private key')\r
-                               }\r
-                               if (privateKey.byteLength !== ACCOUNT_KEY_BYTE_LENGTH) {\r
-                                       throw new TypeError(`Private key must be ${ACCOUNT_KEY_BYTE_LENGTH} bytes`)\r
-                               }\r
-                               const publicKey = nano25519_derive(privateKey)\r
-                               const address = new Address(publicKey)\r
-                               this.#isInternal = true\r
-                               const account = new this(address, publicKey, index)\r
-                               this.#isInternal = false\r
-                               accounts.push(account)\r
-                       }\r
-                       return accounts\r
-               } catch (err) {\r
-                       throw new Error('Failed to import Accounts from private keys', { cause: err })\r
-               }\r
-       }\r
-\r
-       /**\r
-       * Instantiates Account objects from public data, each specifying either its\r
-       * public key or its Nano address.\r
-       *\r
-       * @param {(string | Uint8Array<ArrayBuffer>|KeyPair)[]} input - Public keys or addresses of the accounts\r
-       * @returns {Account[]} The instantiated Account objects\r
-       */\r
-       static #fromPublic (input: (string | Uint8Array<ArrayBuffer> | KeyPair)[] | unknown): Account[] {\r
-               try {\r
-                       const keypairs = this.#isKeyPairs(input)\r
-                               ? input\r
-                               : this.#isKeys(input)\r
-                                       ? input.map(i => { return { publicKey: i } as KeyPair })\r
-                                       : []\r
-                       if (keypairs.length === 0) {\r
-                               throw new TypeError('Invalid public input for Account')\r
-                       }\r
-\r
-                       const accounts: Account[] = []\r
-                       for (let keypair of keypairs) {\r
-                               if (keypair.publicKey == null) {\r
-                                       throw new TypeError('Account address or public key is required', { cause: keypair.publicKey })\r
-                               }\r
-                               const { index } = keypair\r
-                               const address = new Address(keypair.publicKey)\r
-                               const publicKey = address.toPublicKey()\r
-                               this.#isInternal = true\r
-                               const account = new this(address, publicKey, index)\r
-                               this.#isInternal = false\r
-                               accounts.push(account)\r
-                       }\r
-                       return accounts\r
-               } catch (err) {\r
-                       console.error(err)\r
-                       throw new TypeError('Failed to import Account from public data', { cause: { err } })\r
-               }\r
-       }\r
-\r
-       static #isKey (input: unknown): input is string | Uint8Array<ArrayBuffer> {\r
-               return typeof input === 'string' || (input instanceof Uint8Array && 'buffer' in input)\r
-       }\r
-\r
-       static #isKeys (input: unknown): input is (string | Uint8Array<ArrayBuffer>)[] {\r
-               if (Array.isArray(input)) {\r
-                       for (const i of input) {\r
-                               if (!this.#isKey(i)) {\r
-                                       return false\r
-                               }\r
-                       }\r
-               }\r
-               return true\r
-       }\r
-\r
-       static #isKeyPair (input: unknown): input is KeyPair {\r
-               if (typeof input === 'object') {\r
-                       const obj = input as Record<string, unknown>\r
-                       if ('index' in obj && typeof obj.index === 'number') {\r
-                               return true\r
-                       }\r
-                       if ('publicKey' in obj && this.#isKey(obj.publicKey)) {\r
-                               return true\r
-                       }\r
-                       if ('privateKey' in obj && this.#isKey(obj.privateKey)) {\r
-                               return true\r
-                       }\r
-               }\r
-               return false\r
-       }\r
-\r
-       static #isKeyPairs (input: unknown): input is KeyPair[] {\r
-               if (Array.isArray(input)) {\r
-                       for (const i of input) {\r
-                               if (!this.#isKeyPair(i)) {\r
-                                       return false\r
-                               }\r
-                       }\r
-               }\r
-               return true\r
-       }\r
 }\r
index 17f5bc362d88ca6abfbc410be80863a922575cbb..4f9d057d83daf14a1b679f0f12e1a1dead1e2b52 100644 (file)
@@ -94,10 +94,10 @@ export class Block {
        constructor (account: unknown, balance: unknown, previous: unknown, representative: unknown) {
                try {
                        if (typeof account === 'string') {
-                               account = Account.load(account)
+                               account = new Account(account)
                        }
                        if (typeof representative === 'string') {
-                               representative = Account.load(representative)
+                               representative = new Account(representative)
                        }
                        if (!(account instanceof Account)) {
                                throw new TypeError('Invalid account')
@@ -201,7 +201,7 @@ export class Block {
                                throw new TypeError('Invalid account')
                        }
                        this.representative = (typeof representative === 'string')
-                               ? Account.load(representative)
+                               ? new Account(representative)
                                : representative
 
                        this.link = hex.toBytes(BURN_PUBLIC_KEY)
@@ -356,7 +356,7 @@ export class Block {
                                throw new TypeError('Invalid account', { cause: account })
                        }
                        this.link = (typeof account === 'string')
-                               ? hex.toBytes(Account.load(account).publicKey)
+                               ? hex.toBytes(new Account(account).publicKey)
                                : hex.toBytes(account.publicKey)
 
                        return this
index dcdb70561f463d97f105a6bb07e21bfe6bf4bff3..1b8d00a26238043ec3a7167d875e873f8ae23dff 100644 (file)
@@ -47,7 +47,7 @@ export class Rolodex {
                        .replaceAll('<', '\\u003c')
                        .replaceAll('>', '\\u003e')
                        .replaceAll('\\', '\\u005c')
-               const account = Account.load(address)
+               const account = new Account(address)
 
                try {
                        const existingName = await this.getName(account.address)
@@ -185,7 +185,7 @@ export class Rolodex {
        static async verify (name: string, signature: string, ...data: string[]): Promise<boolean> {
                const addresses = await this.getAddresses(name)
                for (const address of addresses) {
-                       const { publicKey } = Account.load(address)
+                       const { publicKey } = new Account(address)
                        const verified = await Tools.verify(publicKey, signature, ...data)
                        if (verified) {
                                return true
index ce548e5e3438a12ca2eb155fa8932e5b2e8a6cb5..e6ae8fae006a3686c386a2f215898a172387168c 100644 (file)
@@ -180,7 +180,7 @@ export class Tools {
 
                const blockQueue: Promise<void>[] = []
                const results: SweepResult[] = []
-               const recipientAccount = Account.load(recipient)
+               const recipientAccount = new Account(recipient)
                const accounts = await wallet.refresh(rpc, from, to)
 
                for (const [index, account] of accounts) {
index 7e8f7f574753256126865c24a7343e11095f450f..771e8cdf8571c36752668d3bbeac5f02bed964ac 100644 (file)
@@ -33,27 +33,26 @@ export async function _accounts (type: WalletType, accounts: Map<number, Account
                                if (status !== 'OK' || publicKey == null) {
                                        throw new Error(`Error getting Ledger account: ${status}`)
                                }
-                               publicAccounts.push(Account.load({ index, publicKey }))
+                               const account = new Account(publicKey)
+                               output.set(index, account)
+                               accounts.set(index, account)
                        }
                } else {
                        const promises = []
                        for (const index of indexes) {
-                               promises.push(vault.request<ArrayBuffer>({
+                               promises.push(vault.request<number | ArrayBuffer>({
                                        action: 'derive',
                                        index
                                }))
                        }
                        const publicKeys = await Promise.all(promises)
-                       if (publicKeys.length > 0) {
-                               publicAccounts.push(...Account.load(publicKeys))
-                       }
-               }
-               for (const a of publicAccounts) {
-                       if (a.index == null) {
-                               throw new RangeError('Index missing for Account')
+                       for (const { index, publicKey } of publicKeys) {
+                               if (typeof index === 'number' && publicKey instanceof ArrayBuffer) {
+                                       const account = new Account(publicKey)
+                                       output.set(index, account)
+                                       accounts.set(index, account)
+                               }
                        }
-                       output.set(a.index, a)
-                       accounts.set(a.index, a)
                }
        }
        if (isSingle) {
index 8d208266b1d542ab4193e708be6bd792fb7c7d2d..7b7a062f83b4ebced9df11dcdb4b39a4b3f09af4 100644 (file)
@@ -17,7 +17,6 @@ await Promise.all([
 \r
                        assert.equal(account.publicKey, NANO_TEST_VECTORS.PUBLIC_0)\r
                        assert.equal(account.address, NANO_TEST_VECTORS.ADDRESS_0)\r
-                       assert.equal(account.index, 0)\r
 \r
                        const accounts = await wallet.accounts()\r
                        assert.exists(accounts.get(0))\r
@@ -37,13 +36,11 @@ await Promise.all([
                        assert.exists(account1)\r
                        assert.equal(account1.publicKey, NANO_TEST_VECTORS.PUBLIC_1)\r
                        assert.equal(account1.address, NANO_TEST_VECTORS.ADDRESS_1)\r
-                       assert.equal(account1.index, 1)\r
 \r
                        const account2 = accounts.get(2)\r
                        assert.exists(account2)\r
                        assert.equal(account2.publicKey, NANO_TEST_VECTORS.PUBLIC_2)\r
                        assert.equal(account2.address, NANO_TEST_VECTORS.ADDRESS_2)\r
-                       assert.equal(account2.index, 2)\r
 \r
                        await assert.resolves(wallet.destroy())\r
                })\r
@@ -57,7 +54,6 @@ await Promise.all([
                        for (let i = 0x70000000; i < 0x7000000f; i++) {\r
                                const a = accounts.get(i)\r
                                assert.exists(a)\r
-                               assert.equal(a.index, i)\r
                                assert.exists(a.address)\r
                                assert.exists(a.publicKey)\r
                        }\r
@@ -73,7 +69,6 @@ await Promise.all([
 \r
                        assert.equal(account.publicKey, NANO_TEST_VECTORS.PUBLIC_0)\r
                        assert.equal(account.address, NANO_TEST_VECTORS.ADDRESS_0)\r
-                       assert.equal(account.index, 0)\r
 \r
                        const accounts = await restored.accounts()\r
                        assert.exists(accounts.get(0))\r
@@ -93,7 +88,6 @@ await Promise.all([
 \r
                        assert.equal(account.publicKey, NANO_TEST_VECTORS.BLAKE2B_PUBLIC_1)\r
                        assert.equal(account.address, NANO_TEST_VECTORS.BLAKE2B_ADDRESS_1)\r
-                       assert.equal(account.index, 1)\r
 \r
                        const accounts = await wallet.accounts(1)\r
                        const account1 = accounts.get(1)\r
@@ -116,13 +110,11 @@ await Promise.all([
                        assert.exists(account2)\r
                        assert.exists(account2.publicKey)\r
                        assert.exists(account2.address)\r
-                       assert.equal(account2.index, 2)\r
 \r
                        const account3 = accounts.get(3)\r
                        assert.exists(account3)\r
                        assert.exists(account3.publicKey)\r
                        assert.exists(account3.address)\r
-                       assert.equal(account3.index, 3)\r
 \r
                        await assert.resolves(wallet.destroy())\r
                })\r
@@ -136,7 +128,6 @@ await Promise.all([
                        for (let i = 0x70000000; i < 0x7000000f; i++) {\r
                                const a = accounts.get(i)\r
                                assert.exists(a)\r
-                               assert.equal(a.index, i)\r
                                assert.exists(a.address)\r
                                assert.exists(a.publicKey)\r
                        }\r
@@ -152,7 +143,6 @@ await Promise.all([
 \r
                        assert.equal(account.publicKey, NANO_TEST_VECTORS.BLAKE2B_PUBLIC_1)\r
                        assert.equal(account.address, NANO_TEST_VECTORS.BLAKE2B_ADDRESS_1)\r
-                       assert.equal(account.index, 1)\r
 \r
                        const accounts = await restored.accounts(1)\r
                        assert.exists(accounts.get(1))\r
index 461d6f680782fbddc0a19ec77c02dccf630b01c3..669856ab491f571c86fec01b85070384c0e538cc 100644 (file)
@@ -305,7 +305,7 @@ await Promise.all([
                        const wallet = await Wallet.load('BIP-44', NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.MNEMONIC, NANO_TEST_VECTORS.PASSWORD)\r
                        await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
                        const account = await wallet.account()\r
-                       const legacy = Account.load(NANO_TEST_VECTORS.ADDRESS_0.replace('nano_', 'xrb_'))\r
+                       const legacy = new Account(NANO_TEST_VECTORS.ADDRESS_0.replace('nano_', 'xrb_'))\r
 \r
                        assert.equal(account.address, legacy.address)\r
                        assert.equal(NANO_TEST_VECTORS.ADDRESS_0, legacy.address)\r
index 914052aafee24f0f9f8571dac8a3f6146451cb3f..2fe0898705a7c58224faadd2db316b9ae66f6d4f 100644 (file)
@@ -171,7 +171,6 @@ await Promise.all([
                                const account = accounts.get(i)
                                assert.exists(account)
                                assert.ok(account instanceof Account)
-                               assert.equal(account.index, i)
                                assert.equal(account.balance, 0n)
                                assert.equal(account.receivable, 0n)
                        }
index a6e7296dbf5345a3260d02dd57b1e39a5bce7fc2..5763d94a5513b09d47a3b200646955d9279aae19 100644 (file)
@@ -15,11 +15,8 @@ await Promise.all([
                        const wallet = await Wallet.load('BIP-44', NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED)\r
                        await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
                        const account = await wallet.account()\r
-                       if (account.index == null) {\r
-                               throw new Error('Account index missing')\r
-                       }\r
                        const data = crypto.randomUUID()\r
-                       const signature = await wallet.sign(account.index, data)\r
+                       const signature = await wallet.sign(0, data)\r
 \r
                        assert.ok(await Tools.verify(account.publicKey, signature, data))\r
                        await assert.resolves(wallet.destroy())\r
@@ -29,12 +26,9 @@ await Promise.all([
                        const wallet = await Wallet.load('BIP-44', NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED)\r
                        await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
                        const account = await wallet.account()\r
-                       if (account.index == null) {\r
-                               throw new Error('Account index missing')\r
-                       }\r
                        const sendBlock = await new Block(account.address, '5618869000000000000000000000000', '92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D', 'nano_1stofnrxuz3cai7ze75o174bpm7scwj9jn3nxsn8ntzg784jf1gzn1jjdkou')\r
                                .send('nano_1q3hqecaw15cjt7thbtxu3pbzr1eihtzzpzxguoc37bj1wc5ffoh7w74gi6p', '2000000000000000000000000000000')\r
-                               .sign(wallet, account.index)\r
+                               .sign(wallet, 0)\r
 \r
                        assert.ok(await sendBlock.verify(account.publicKey))\r
                        await assert.resolves(wallet.destroy())\r
@@ -44,17 +38,13 @@ await Promise.all([
                        const wallet = await Wallet.load('BIP-44', NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED)\r
                        await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
                        const account = await wallet.account()\r
-                       if (account.index == null) {\r
-                               throw new Error('Account index missing')\r
-                       }\r
-                       assert.equal(account.index, 0)\r
 \r
                        const sendBlock = await new Block(account.address, '5618869000000000000000000000000', '92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D', 'nano_1stofnrxuz3cai7ze75o174bpm7scwj9jn3nxsn8ntzg784jf1gzn1jjdkou')\r
                                .send('nano_1q3hqecaw15cjt7thbtxu3pbzr1eihtzzpzxguoc37bj1wc5ffoh7w74gi6p', '2000000000000000000000000000000')\r
-                               .sign(wallet, account.index)\r
+                               .sign(wallet, 0)\r
                        assert.ok(await sendBlock.verify(account.publicKey))\r
 \r
-                       const wrongAccount = Account.load('nano_1q3hqecaw15cjt7thbtxu3pbzr1eihtzzpzxguoc37bj1wc5ffoh7w74gi6p')\r
+                       const wrongAccount = new Account('nano_1q3hqecaw15cjt7thbtxu3pbzr1eihtzzpzxguoc37bj1wc5ffoh7w74gi6p')\r
                        assert.equal(await sendBlock.verify(wrongAccount.publicKey), false)\r
 \r
                        await assert.resolves(wallet.destroy())\r