From a399a390311d59582806f73207daad6a6346bfe8 Mon Sep 17 00:00:00 2001 From: "markin.io" Date: Wed, 8 Dec 2021 11:54:04 +0300 Subject: [PATCH 1/6] Implements proper casting for types during for rehydrateState --- .../types/Storage/methods/rehydrateState.js | 107 +++++++++++++++--- 1 file changed, 94 insertions(+), 13 deletions(-) diff --git a/packages/wallet-lib/src/types/Storage/methods/rehydrateState.js b/packages/wallet-lib/src/types/Storage/methods/rehydrateState.js index 4381086714a..040c79bf8e2 100644 --- a/packages/wallet-lib/src/types/Storage/methods/rehydrateState.js +++ b/packages/wallet-lib/src/types/Storage/methods/rehydrateState.js @@ -1,9 +1,98 @@ const { merge } = require('lodash'); -const { InstantLock } = require('@dashevo/dashcore-lib'); +const { InstantLock, Transaction, BlockHeader } = require('@dashevo/dashcore-lib'); const { hasMethod } = require('../../../utils'); const mergeHelper = (initial = {}, additional = {}) => merge(initial, additional); const { REHYDRATE_STATE_FAILED, REHYDRATE_STATE_SUCCESS } = require('../../../EVENTS'); +const logger = require("../../../logger"); + +const storeTypesSchema = { + "transactions": { + "*": Transaction + }, + "instantLocks": { + "*": InstantLock + }, + "wallets": { + "*": { + "addresses": { + "external": { + "*": { + "utxos": { + "*": function (item) { + // TODO: resolve type inconsistency for address utxos + try { + return new Transaction.UnspentOutput(item); + } catch (e) { + return new Transaction.Output(item); + } + } + } + } + }, + "internal": { + "*": { + "utxos": { + "*": function (item) { + // TODO: resolve type inconsistency for address utxos + try { + return new Transaction.UnspentOutput(item); + } catch (e) { + return new Transaction.Output(item); + } + } + } + } + } + } + } + }, + "chains": { + "*": { + "blockHeaders": { + "*": BlockHeader + } + } + } +} + +const rehydrateItem = (item, name) => { + if (!item) { + return null; + } + + const itemSchema = storeTypesSchema[name]; + + if (!itemSchema) { + logger.silly(`Storage.rehydrateState(): no types schema defined for item "${name}"`); + return item; + } + + const ensureTypes = (schema, item) => { + Object.entries(schema).forEach(([schemaKey, schemaValue]) => { + if (schemaValue.constructor.name !== "Object") { + const clazz = schemaValue; + if (schemaKey === "*") { + Object.keys(item).forEach((itemKey) => { + item[itemKey] = new clazz(item[itemKey]) + }) + } else { + item[schemaKey] = new clazz(item[schemaKey]) + } + } else { + if (schemaKey === "*") { + Object.values(item).forEach((itemValue) => ensureTypes(schemaValue, itemValue)) + } else { + ensureTypes(schemaValue, item[schemaKey]) + } + } + }) + } + + ensureTypes(itemSchema, item) + + return item +} /** * Fetch the state from the persistence adapter @@ -13,26 +102,18 @@ const rehydrateState = async function rehydrateState() { if (this.rehydrate && this.lastRehydrate === null) { try { const transactions = (this.adapter && hasMethod(this.adapter, 'getItem')) - ? (await this.adapter.getItem('transactions') || this.store.transactions) + ? (rehydrateItem(await this.adapter.getItem('transactions'), 'transactions') || this.store.transactions) : this.store.transactions; const wallets = (this.adapter && hasMethod(this.adapter, 'getItem')) - ? (await this.adapter.getItem('wallets') || this.store.wallets) + ? (rehydrateItem(await this.adapter.getItem('wallets'), 'wallets') || this.store.wallets) : this.store.wallets; const chains = (this.adapter && hasMethod(this.adapter, 'getItem')) - ? (await this.adapter.getItem('chains') || this.store.chains) + ? (rehydrateItem(await this.adapter.getItem('chains'), 'chains') || this.store.chains) : this.store.chains; const instantLocks = (this.adapter && hasMethod(this.adapter, 'getItem')) - ? (await this.adapter.getItem('instantLocks') || this.store.instantLocks) + ? (rehydrateItem(await this.adapter.getItem('instantLocks'), 'instantLocks') || this.store.instantLocks) : this.store.instantLocks; - // We need to keep deserialized instant locks - Object.keys(instantLocks).forEach((transactionHash) => { - const instantLock = instantLocks[transactionHash]; - if (!(instantLock instanceof InstantLock)) { - instantLocks[transactionHash] = new InstantLock(instantLock); - } - }); - this.store.transactions = mergeHelper(this.store.transactions, transactions); this.store.wallets = mergeHelper(this.store.wallets, wallets); this.store.chains = mergeHelper(this.store.chains, chains); From 6167d1d8cb5597e9139a4dcf70005e1120d18e15 Mon Sep 17 00:00:00 2001 From: "markin.io" Date: Wed, 8 Dec 2021 13:44:01 +0300 Subject: [PATCH 2/6] Refactor rehydrateState.js and provide error handling in case of invalid data schema --- .../types/Storage/methods/rehydrateState.js | 169 +++++++++--------- 1 file changed, 88 insertions(+), 81 deletions(-) diff --git a/packages/wallet-lib/src/types/Storage/methods/rehydrateState.js b/packages/wallet-lib/src/types/Storage/methods/rehydrateState.js index 040c79bf8e2..2ac4dc377b4 100644 --- a/packages/wallet-lib/src/types/Storage/methods/rehydrateState.js +++ b/packages/wallet-lib/src/types/Storage/methods/rehydrateState.js @@ -4,95 +4,90 @@ const { hasMethod } = require('../../../utils'); const mergeHelper = (initial = {}, additional = {}) => merge(initial, additional); const { REHYDRATE_STATE_FAILED, REHYDRATE_STATE_SUCCESS } = require('../../../EVENTS'); -const logger = require("../../../logger"); +const logger = require('../../../logger'); const storeTypesSchema = { - "transactions": { - "*": Transaction + transactions: { + '*': Transaction, }, - "instantLocks": { - "*": InstantLock + instantLocks: { + '*': InstantLock, }, - "wallets": { - "*": { - "addresses": { - "external": { - "*": { - "utxos": { - "*": function (item) { + wallets: { + '*': { + addresses: { + external: { + '*': { + utxos: { + // eslint-disable-next-line func-names + '*': function (item) { // TODO: resolve type inconsistency for address utxos try { return new Transaction.UnspentOutput(item); } catch (e) { return new Transaction.Output(item); } - } - } - } + }, + }, + }, }, - "internal": { - "*": { - "utxos": { - "*": function (item) { + internal: { + '*': { + utxos: { + // eslint-disable-next-line func-names + '*': function (item) { // TODO: resolve type inconsistency for address utxos try { return new Transaction.UnspentOutput(item); } catch (e) { return new Transaction.Output(item); } - } - } - } - } - } - } + }, + }, + }, + }, + }, + }, }, - "chains": { - "*": { - "blockHeaders": { - "*": BlockHeader - } - } - } -} - -const rehydrateItem = (item, name) => { - if (!item) { - return null; - } - - const itemSchema = storeTypesSchema[name]; + chains: { + '*': { + blockHeaders: { + '*': BlockHeader, + }, + }, + }, +}; - if (!itemSchema) { - logger.silly(`Storage.rehydrateState(): no types schema defined for item "${name}"`); - return item; - } +const castItemTypes = (item, schema) => { + Object.entries(schema).forEach(([schemaKey, schemaValue]) => { + if (schemaValue.constructor.name !== 'Object') { + const Clazz = schemaValue; + if (schemaKey === '*') { + Object.keys(item).forEach((itemKey) => { + if (!item[itemKey]) { + throw new Error(`No item key "${itemKey}" found for item ${JSON.stringify(item)}`); + } - const ensureTypes = (schema, item) => { - Object.entries(schema).forEach(([schemaKey, schemaValue]) => { - if (schemaValue.constructor.name !== "Object") { - const clazz = schemaValue; - if (schemaKey === "*") { - Object.keys(item).forEach((itemKey) => { - item[itemKey] = new clazz(item[itemKey]) - }) - } else { - item[schemaKey] = new clazz(item[schemaKey]) - } + // eslint-disable-next-line no-param-reassign + item[itemKey] = new Clazz(item[itemKey]); + }); } else { - if (schemaKey === "*") { - Object.values(item).forEach((itemValue) => ensureTypes(schemaValue, itemValue)) - } else { - ensureTypes(schemaValue, item[schemaKey]) + if (!item[schemaKey]) { + throw new Error(`No item key "${schemaKey}" found for item ${JSON.stringify(item)}`); } - } - }) - } - ensureTypes(itemSchema, item) + // eslint-disable-next-line no-param-reassign + item[schemaKey] = new Clazz(item[schemaKey]); + } + } else if (schemaKey === '*') { + Object.values(item).forEach((itemValue) => castItemTypes(itemValue, schemaValue)); + } else { + castItemTypes(item[schemaKey], schemaValue); + } + }); - return item -} + return item; +}; /** * Fetch the state from the persistence adapter @@ -101,23 +96,35 @@ const rehydrateItem = (item, name) => { const rehydrateState = async function rehydrateState() { if (this.rehydrate && this.lastRehydrate === null) { try { - const transactions = (this.adapter && hasMethod(this.adapter, 'getItem')) - ? (rehydrateItem(await this.adapter.getItem('transactions'), 'transactions') || this.store.transactions) - : this.store.transactions; - const wallets = (this.adapter && hasMethod(this.adapter, 'getItem')) - ? (rehydrateItem(await this.adapter.getItem('wallets'), 'wallets') || this.store.wallets) - : this.store.wallets; - const chains = (this.adapter && hasMethod(this.adapter, 'getItem')) - ? (rehydrateItem(await this.adapter.getItem('chains'), 'chains') || this.store.chains) - : this.store.chains; - const instantLocks = (this.adapter && hasMethod(this.adapter, 'getItem')) - ? (rehydrateItem(await this.adapter.getItem('instantLocks'), 'instantLocks') || this.store.instantLocks) - : this.store.instantLocks; + const storeItemsKeys = ['transactions', 'wallets', 'chains', 'instantLocks']; + const storeItems = {}; + + // Obtain items from storage adapter + for (let i = 0; i < storeItemsKeys.length; i += 1) { + const itemKey = storeItemsKeys[i]; + + let item; + if (this.adapter && hasMethod(this.adapter, 'getItem')) { + // eslint-disable-next-line no-await-in-loop + item = await this.adapter.getItem(itemKey); + } + + storeItems[itemKey] = item || this.store[itemKey]; + } + + // Cast store items to correct data types + try { + castItemTypes(storeItems, storeTypesSchema); + } catch (e) { + logger.error('Error casting storage items types: possibly data schema mismatch'); + throw e; + } + + // Merge with the current items in store + Object.keys(storeItems).forEach((itemKey) => { + this.store[itemKey] = mergeHelper(this.store[itemKey], storeItems[itemKey]); + }); - this.store.transactions = mergeHelper(this.store.transactions, transactions); - this.store.wallets = mergeHelper(this.store.wallets, wallets); - this.store.chains = mergeHelper(this.store.chains, chains); - this.store.instantLocks = mergeHelper(this.store.instantLocks, instantLocks); this.lastRehydrate = +new Date(); this.emit(REHYDRATE_STATE_SUCCESS, { type: REHYDRATE_STATE_SUCCESS, payload: null }); } catch (e) { From 9d42cd9f2fb94bf3f062d86d28b648fa077c195f Mon Sep 17 00:00:00 2001 From: "markin.io" Date: Thu, 9 Dec 2021 12:18:07 +0300 Subject: [PATCH 3/6] Fill rehydrateState.spec.js with test --- .../types/Storage/methods/rehydrateState.js | 14 +- .../Storage/methods/rehydrateState.spec.js | 220 +++++++++++++++++- 2 files changed, 228 insertions(+), 6 deletions(-) diff --git a/packages/wallet-lib/src/types/Storage/methods/rehydrateState.js b/packages/wallet-lib/src/types/Storage/methods/rehydrateState.js index 2ac4dc377b4..9cca533ca94 100644 --- a/packages/wallet-lib/src/types/Storage/methods/rehydrateState.js +++ b/packages/wallet-lib/src/types/Storage/methods/rehydrateState.js @@ -96,12 +96,16 @@ const castItemTypes = (item, schema) => { const rehydrateState = async function rehydrateState() { if (this.rehydrate && this.lastRehydrate === null) { try { - const storeItemsKeys = ['transactions', 'wallets', 'chains', 'instantLocks']; - const storeItems = {}; - + const storeItems = { + transactions: null, + wallets: null, + chains: null, + instantLocks: null + }; + const keys = Object.keys(storeItems) // Obtain items from storage adapter - for (let i = 0; i < storeItemsKeys.length; i += 1) { - const itemKey = storeItemsKeys[i]; + for (let i = 0; i < keys.length; i += 1) { + const itemKey = keys[i]; let item; if (this.adapter && hasMethod(this.adapter, 'getItem')) { diff --git a/packages/wallet-lib/src/types/Storage/methods/rehydrateState.spec.js b/packages/wallet-lib/src/types/Storage/methods/rehydrateState.spec.js index 310107f04c6..5c59971fa66 100644 --- a/packages/wallet-lib/src/types/Storage/methods/rehydrateState.spec.js +++ b/packages/wallet-lib/src/types/Storage/methods/rehydrateState.spec.js @@ -1,8 +1,226 @@ const { expect } = require('chai'); const rehydrateState = require('./rehydrateState'); +const { Transaction, BlockHeader, InstantLock } = require("@dashevo/dashcore-lib"); + +const storeMock = { + "transactions": { + "d37eb9f1b41c45134926d418486f2d8f57778cb949f4069a0b4c91955934913b": { + "hash": "d37eb9f1b41c45134926d418486f2d8f57778cb949f4069a0b4c91955934913b", + "version": 2, + "inputs": [ + { + "prevTxId": "ba657cdff1bdf2010e2b394f7db81aa429a94574c7fdcc5da4a8c5be751bd419", + "outputIndex": 1, + "sequenceNumber": 4294967294, + "script": "483045022100eb7f103a5755e79a25179f289b74033d13e7b5a252a4911bba1c908d0db4361002203a664917ebbb4f5c1d81409898c05f807e23dd324d4458f32a6fc5b42ad8e3830121024b181f43670ebc67826e07885170029e01fd830bfcfa43862d694224d8c7e162", + "scriptString": "72 0x3045022100eb7f103a5755e79a25179f289b74033d13e7b5a252a4911bba1c908d0db4361002203a664917ebbb4f5c1d81409898c05f807e23dd324d4458f32a6fc5b42ad8e38301 33 0x024b181f43670ebc67826e07885170029e01fd830bfcfa43862d694224d8c7e162" + } + ], + "outputs": [ + { + "satoshis": 82716538, + "script": "76a9142f7d620394f5604854e495e6a78773287651faab88ac" + }, + { + "satoshis": 105580000, + "script": "76a91428a46d7ae4d50ec3a5dbb847b01a60818905e98e88ac" + } + ], + "nLockTime": 627066 + }, + "26faad59f6f3aef120323fb3aa9b0a3aaccf56ae770ff83099e3e86324d3a0da": { + "hash": "26faad59f6f3aef120323fb3aa9b0a3aaccf56ae770ff83099e3e86324d3a0da", + "version": 3, + "inputs": [ + { + "prevTxId": "d37eb9f1b41c45134926d418486f2d8f57778cb949f4069a0b4c91955934913b", + "outputIndex": 1, + "sequenceNumber": 4294967295, + "script": "4730440220645a3cfe6798b2d4e5943209c2f241725c0e809c82bd3985743854bbebfeca48022036fd8bf98960d4d1deea37e5cc5833cb64178bc2e27a1628f83250e9e2ec69290121024c61a9a159104ad5e027754b19514347c5ee4a7f5ede8cc379f5f987f2fdb0b0", + "scriptString": "71 0x30440220645a3cfe6798b2d4e5943209c2f241725c0e809c82bd3985743854bbebfeca48022036fd8bf98960d4d1deea37e5cc5833cb64178bc2e27a1628f83250e9e2ec692901 33 0x024c61a9a159104ad5e027754b19514347c5ee4a7f5ede8cc379f5f987f2fdb0b0" + } + ], + "outputs": [ + { + "satoshis": 10000, + "script": "76a9141ec5c66e9789c655ae068d35088b4073345fe0b088ac" + }, + { + "satoshis": 105569753, + "script": "76a91499c256c6f6724b926b7d903b10547bf712faeebd88ac" + } + ], + "nLockTime": 0 + } + }, + "wallets": { + "799ea77395": { + "accounts": { + "m/44'/1'/0'": { + "label": null, + "path": "m/44'/1'/0'", + "network": "testnet", + "blockHeight": 627626, + "blockHash": "00000053b6c3b0b56f64607ad77524922fbb4560306fa31f165ae36e11551d77" + } + }, + "network": "testnet", + "mnemonic": null, + "type": null, + "identityIds": [], + "addresses": { + "external": { + "m/44'/1'/0'/0/0": { + "path": "m/44'/1'/0'/0/0", + "index": 0, + "address": "yQ2LrWYLRdUdDnofwqscghwSgCghd2BMPv", + "transactions": [ + "d37eb9f1b41c45134926d418486f2d8f57778cb949f4069a0b4c91955934913b", + "26faad59f6f3aef120323fb3aa9b0a3aaccf56ae770ff83099e3e86324d3a0da" + ], + "balanceSat": 0, + "unconfirmedBalanceSat": 0, + "utxos": { + "adfc0ad1dd803fc1541f87711e794936c3fd99b763d0b26e77dd463425382833-1": { + "address": "yQ2LrWYLRdUdDnofwqscghwSgCghd2BMPv", + "txid": "26faad59f6f3aef120323fb3aa9b0a3aaccf56ae770ff83099e3e86324d3a0da", + "vout": 1, + "scriptPubKey": "76a91421b4db2de99d02a16092fa0aa0f9bb32d87353a588ac", + "amount": 0.82706400 + } + }, + "fetchedLast": 0, + "used": true + } + }, + "internal": { + "m/44'/1'/0'/1/0": { + "path": "m/44'/1'/0'/1/0", + "index": 0, + "address": "yaLT3TjS7jdDVgAjDBCRSm1rHbsMeLXAx4", + "transactions": [ + "adfc0ad1dd803fc1541f87711e794936c3fd99b763d0b26e77dd463425382833" + ], + "balanceSat": 0, + "unconfirmedBalanceSat": 0, + "utxos": { + "adfc0ad1dd803fc1541f87711e794936c3fd99b763d0b26e77dd463425382833-1": { + "address": "yaLT3TjS7jdDVgAjDBCRSm1rHbsMeLXAx4", + "txid": "26faad59f6f3aef120323fb3aa9b0a3aaccf56ae770ff83099e3e86324d3a0da", + "vout": 1, + "scriptPubKey": "76a91421b4db2de99d02a16092fa0aa0f9bb32d87353a588ac", + "amount": 0.0001 + } + }, + "fetchedLast": 0, + "used": true + } + }, + "misc": {} + } + } + }, + "chains": { + "testnet": { + "name": "testnet", + "blockHeaders": { + "000000059885815cfc06ba74b814200d29658394dbe5d1e93948a8587947747b": { + "hash": "000000059885815cfc06ba74b814200d29658394dbe5d1e93948a8587947747b", + "version": 536870912, + "prevHash": "000000c520efd2047f0b6f0c1c75e0382f8a9b7d76bb140bde3ada10c62e8b0d", + "merkleRoot": "ef292bfb7965402e57dfeb4ee8bad0055c216c4c5a4e549a0ac17a393ae8617b", + "time": 1638950949, + "bits": 503385436, + "nonce": 351770 + }, + "000000b7d508273169da2e0f1c167554d3d4643759361ab8ca338cabbbf5dee4": { + "hash": "000000b7d508273169da2e0f1c167554d3d4643759361ab8ca338cabbbf5dee4", + "version": 536870912, + "prevHash": "0000009b0bb17530c41a8200868e61e8a2d927b3cce7cfac14c3f393ffca5b06", + "merkleRoot": "664d055f0194e01ac64db1ace3a720f4580533d6d999b1cfab7740f8b9c4d642", + "time": 1638884848, + "bits": 503373836, + "nonce": 13494 + }, + }, + "mappedBlockHeaderHeights": { + "627561": "00000145d8a9ab1a71ffdcd01657d284c67593b27f9ca244fc202632bad7145d", + "627574": "000000801bafea9630d9c6a341963912e7faff067e79b8b9b57910b62f736d3e", + "627626": "00000053b6c3b0b56f64607ad77524922fbb4560306fa31f165ae36e11551d77" + }, + "blockHeight": 627626, + "fees": { + "minRelay": 1000 + } + } + }, + "instantLocks": { + "d37eb9f1b41c45134926d418486f2d8f57778cb949f4069a0b4c91955934913b": { + "inputs": [ + { + "outpointHash": "3188b2bfb238cb07c1822944088fff59d665af1f00a72d2beee8b88457201beb", + "outpointIndex": 1 + } + ], + "txid": "d37eb9f1b41c45134926d418486f2d8f57778cb949f4069a0b4c91955934913b", + "signature": "0628537fd9b44b5d2441724780183bea34f44e82fea7a7057337c562858bc9dabfe3541c8a7c9bd4677887dfaa2b02b90c483fe223590a05d6ab8670221aacf046731aa462a8e9f08271434ed6cbfaa1ec51c2be71f6e0a7d9612795b1a0f050" + }, + "26faad59f6f3aef120323fb3aa9b0a3aaccf56ae770ff83099e3e86324d3a0da": { + "inputs": [ + { + "outpointHash": "b5cdbdae1f43ef324326b5519e2e670afa9203e2f37115c3c6ac51db968b3726", + "outpointIndex": 1 + } + ], + "txid": "26faad59f6f3aef120323fb3aa9b0a3aaccf56ae770ff83099e3e86324d3a0da", + "signature": "913ab2cf9bb6d918f0d2d12c5fef9ba9652ce93f625cebd83241746b36bdc6505e0385e1875576a92a5d49d74ec8098315e90c8688ccd41ab4fdc8df43bd83fa53081a65651bc30ca2957e4c2e98388465b19fac7b61f7b86393d777c2d26e66" + }, + } +} + describe('Storage - rehydrateState', () => { - it('should rehydrate the state', () => { + const storage = { + rehydrate: true, + lastRehydrate: null, + adapter: { + getItem: async (key) => { + return storeMock[key]; + } + }, + store: { + transactions: {}, + wallets: {}, + chains: {}, + instantLocks: {} + }, + emit: () => {} + } + + + it('should rehydrate the state', async () => { + await rehydrateState.call(storage); + Object.values(storage.store.transactions).forEach(tx => { + expect(tx instanceof Transaction).to.be.true; + }); + + Object.values(storage.store.instantLocks).forEach(isLock => { + expect(isLock instanceof InstantLock).to.be.true; + }); + + Object.values(storage.store.wallets).forEach(wallet => { + const { internal, external } = wallet.addresses; + Object.values({ ...internal, ...external }).forEach(address => { + Object.values(address.utxos).forEach(utxo => { + expect(utxo instanceof Transaction.UnspentOutput).to.be.true; + }); + }); + }); + Object.values(storage.store.chains).forEach(chain => { + Object.values(chain.blockHeaders).forEach(blockHeader => { + expect(blockHeader instanceof BlockHeader).to.be.true; + }) + }) }); }); From 2b7d8aafddf8f14108de0cc700ef24b12b50f679 Mon Sep 17 00:00:00 2001 From: "markin.io" Date: Thu, 9 Dec 2021 13:28:05 +0300 Subject: [PATCH 4/6] Fix eslint --- .../wallet-lib/src/types/Storage/methods/rehydrateState.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/wallet-lib/src/types/Storage/methods/rehydrateState.js b/packages/wallet-lib/src/types/Storage/methods/rehydrateState.js index 9cca533ca94..d729281051f 100644 --- a/packages/wallet-lib/src/types/Storage/methods/rehydrateState.js +++ b/packages/wallet-lib/src/types/Storage/methods/rehydrateState.js @@ -100,9 +100,9 @@ const rehydrateState = async function rehydrateState() { transactions: null, wallets: null, chains: null, - instantLocks: null + instantLocks: null, }; - const keys = Object.keys(storeItems) + const keys = Object.keys(storeItems); // Obtain items from storage adapter for (let i = 0; i < keys.length; i += 1) { const itemKey = keys[i]; From 5939efe4503f53c2afbcaf9a18883c98db302f7e Mon Sep 17 00:00:00 2001 From: "markin.io" Date: Fri, 10 Dec 2021 09:44:27 +0300 Subject: [PATCH 5/6] Simplify schema and remove not needed check for the item key --- .../types/Storage/methods/rehydrateState.js | 23 ++----------------- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/packages/wallet-lib/src/types/Storage/methods/rehydrateState.js b/packages/wallet-lib/src/types/Storage/methods/rehydrateState.js index d729281051f..342489cf2e0 100644 --- a/packages/wallet-lib/src/types/Storage/methods/rehydrateState.js +++ b/packages/wallet-lib/src/types/Storage/methods/rehydrateState.js @@ -16,22 +16,7 @@ const storeTypesSchema = { wallets: { '*': { addresses: { - external: { - '*': { - utxos: { - // eslint-disable-next-line func-names - '*': function (item) { - // TODO: resolve type inconsistency for address utxos - try { - return new Transaction.UnspentOutput(item); - } catch (e) { - return new Transaction.Output(item); - } - }, - }, - }, - }, - internal: { + '*': { '*': { utxos: { // eslint-disable-next-line func-names @@ -64,16 +49,12 @@ const castItemTypes = (item, schema) => { const Clazz = schemaValue; if (schemaKey === '*') { Object.keys(item).forEach((itemKey) => { - if (!item[itemKey]) { - throw new Error(`No item key "${itemKey}" found for item ${JSON.stringify(item)}`); - } - // eslint-disable-next-line no-param-reassign item[itemKey] = new Clazz(item[itemKey]); }); } else { if (!item[schemaKey]) { - throw new Error(`No item key "${schemaKey}" found for item ${JSON.stringify(item)}`); + throw new Error(`No schema key "${schemaKey}" found for item ${JSON.stringify(item)}`); } // eslint-disable-next-line no-param-reassign From cc4684824ad6457f3c29c88ee75ad42fe6acc61b Mon Sep 17 00:00:00 2001 From: "markin.io" Date: Fri, 10 Dec 2021 12:57:23 +0300 Subject: [PATCH 6/6] Fixes transport mock for the test --- packages/wallet-lib/src/test/mocks/TransportMock.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/wallet-lib/src/test/mocks/TransportMock.js b/packages/wallet-lib/src/test/mocks/TransportMock.js index ea3ab08df9a..e1c51bbdfb6 100644 --- a/packages/wallet-lib/src/test/mocks/TransportMock.js +++ b/packages/wallet-lib/src/test/mocks/TransportMock.js @@ -6,7 +6,16 @@ class TransportMock { this.getBestBlockHeight = sinonSandbox.stub().returns(42); this.subscribeToTransactionsWithProofs = sinonSandbox.stub().returns(transactionStreamMock); - this.getBlockHeaderByHeight = sinonSandbox.stub().returns({ hash: 123 }); + this.getBlockHeaderByHeight = sinonSandbox.stub() + .returns({ + hash: '000000059885815cfc06ba74b814200d29658394dbe5d1e93948a8587947747b', + version: 536870912, + prevHash: '000000c520efd2047f0b6f0c1c75e0382f8a9b7d76bb140bde3ada10c62e8b0d', + merkleRoot: 'ef292bfb7965402e57dfeb4ee8bad0055c216c4c5a4e549a0ac17a393ae8617b', + time: 1638950949, + bits: 503385436, + nonce: 351770, + }); this.on = sinonSandbox.stub(); this.subscribeToBlocks = sinonSandbox.stub(); this.getIdentityIdsByPublicKeyHash = sinonSandbox.stub().returns([null]);