From 5c69005a4d8330792daeffb6bbc7947ac5ea6f82 Mon Sep 17 00:00:00 2001 From: yanguoyu <841185308@qq.com> Date: Tue, 9 May 2023 19:19:26 +0800 Subject: [PATCH 1/3] fix: fix some bugs 1. When append scripts are empty means remove append scripts, so remove empty judgment 2. resultFormatters should not return null. Because the Method will ignore null or undefined. 3. When clear cache start monitor should start node right now and only delete current wallet sync progress. --- .../src/block-sync-renderer/sync/light-connector.ts | 3 --- packages/neuron-wallet/src/database/chain/index.ts | 7 ++++--- packages/neuron-wallet/src/services/indexer.ts | 2 +- packages/neuron-wallet/src/services/multisig.ts | 5 +++++ packages/neuron-wallet/src/services/sync-progress.ts | 7 +++++++ packages/neuron-wallet/src/utils/ckb-rpc.ts | 8 +++++--- .../neuron-wallet/tests/controllers/multisig.test.ts | 9 +++++++++ .../neuron-wallet/tests/controllers/sync-api.test.ts | 3 +++ .../neuron-wallet/tests/services/light-runner.test.ts | 6 ++++++ 9 files changed, 40 insertions(+), 10 deletions(-) diff --git a/packages/neuron-wallet/src/block-sync-renderer/sync/light-connector.ts b/packages/neuron-wallet/src/block-sync-renderer/sync/light-connector.ts index 40d13300a6..125b49e124 100644 --- a/packages/neuron-wallet/src/block-sync-renderer/sync/light-connector.ts +++ b/packages/neuron-wallet/src/block-sync-renderer/sync/light-connector.ts @@ -301,9 +301,6 @@ export default class LightConnector extends Connector { } async appendScript(scripts: AppendScript[]) { - if (!scripts.length) { - return - } this.initSyncProgress(scripts) } } diff --git a/packages/neuron-wallet/src/database/chain/index.ts b/packages/neuron-wallet/src/database/chain/index.ts index 5e29bfbffe..ea3eb234c0 100644 --- a/packages/neuron-wallet/src/database/chain/index.ts +++ b/packages/neuron-wallet/src/database/chain/index.ts @@ -1,23 +1,24 @@ import { getConnection } from 'typeorm' import MultisigOutputChangedSubject from 'models/subjects/multisig-output-db-changed-subject' +import SyncProgressService from 'services/sync-progress' import InputEntity from './entities/input' import OutputEntity from './entities/output' import TransactionEntity from './entities/transaction' import SyncInfoEntity from './entities/sync-info' import IndexerTxHashCache from './entities/indexer-tx-hash-cache' import MultisigOutput from './entities/multisig-output' -import SyncProgress from './entities/sync-progress' /* * Clean local sqlite storage */ export const clean = async () => { await Promise.all([ - ...[InputEntity, OutputEntity, TransactionEntity, IndexerTxHashCache, MultisigOutput, SyncProgress].map(entity => { + ...[InputEntity, OutputEntity, TransactionEntity, IndexerTxHashCache, MultisigOutput].map(entity => { return getConnection() .getRepository(entity) .clear() - }) + }), + SyncProgressService.clear() ]) MultisigOutputChangedSubject.getSubject().next('reset') diff --git a/packages/neuron-wallet/src/services/indexer.ts b/packages/neuron-wallet/src/services/indexer.ts index 7d70189f63..4f2f01837e 100644 --- a/packages/neuron-wallet/src/services/indexer.ts +++ b/packages/neuron-wallet/src/services/indexer.ts @@ -30,7 +30,7 @@ export default class IndexerService { } if (!NodeService.getInstance().isCkbNodeExternal) { - await startMonitor('ckb') + await startMonitor('ckb', true) } } diff --git a/packages/neuron-wallet/src/services/multisig.ts b/packages/neuron-wallet/src/services/multisig.ts index 89012ff0ea..c45543df38 100644 --- a/packages/neuron-wallet/src/services/multisig.ts +++ b/packages/neuron-wallet/src/services/multisig.ts @@ -11,6 +11,7 @@ import NetworksService from './networks' import Multisig from 'models/multisig' import SyncProgress, { SyncAddressType } from 'database/chain/entities/sync-progress' import { NetworkType } from 'models/network' +import WalletService from './wallets' const max64Int = '0x' + 'f'.repeat(16) export default class MultisigService { @@ -334,9 +335,13 @@ export default class MultisigService { } static async getMultisigConfigForLight() { + const currentWallet = WalletService.getInstance().getCurrent() const multisigConfigs = await getConnection() .getRepository(MultisigConfig) .createQueryBuilder() + .where({ + walletId: currentWallet?.id + }) .getMany() return multisigConfigs.map(v => ({ walletId: v.walletId, diff --git a/packages/neuron-wallet/src/services/sync-progress.ts b/packages/neuron-wallet/src/services/sync-progress.ts index 98598d4c25..61f298923b 100644 --- a/packages/neuron-wallet/src/services/sync-progress.ts +++ b/packages/neuron-wallet/src/services/sync-progress.ts @@ -108,4 +108,11 @@ export default class SyncProgressService { .where({ hash: In(hashes) }) .getMany() } + + static async clear() { + const currentWallet = WalletService.getInstance().getCurrent() + await getConnection() + .getRepository(SyncProgress) + .delete({ walletId: currentWallet?.id }) + } } diff --git a/packages/neuron-wallet/src/utils/ckb-rpc.ts b/packages/neuron-wallet/src/utils/ckb-rpc.ts index e0f6acc08f..5e460d9a4e 100644 --- a/packages/neuron-wallet/src/utils/ckb-rpc.ts +++ b/packages/neuron-wallet/src/utils/ckb-rpc.ts @@ -91,7 +91,7 @@ const lightRPCProperties: Record[0] paramsFormatters: [paramsFormatter.toHash], resultFormatters: (result: { status: 'fetched' | 'fetching' | 'added' | 'not_found', data?: RPC.TransactionWithStatus }) => { if (result.status === 'fetched' && result.data) {return resultFormatter.toTransactionWithStatus(result.data)} - return null + return result } } } @@ -117,7 +117,7 @@ export class LightRPC extends Base { ) => Promise<{ lastCursor: HexString, txs: { txHash: HexString, txIndex: HexString, blockNumber: CKBComponents.BlockNumber }[]}> getTransactionInLight: Base['getTransaction'] - fetchTransaction: (hash: string) => Promise + fetchTransaction: (hash: string) => Promise getGenesisBlock: () => Promise exceptionMethods = ['getCurrentEpoch', 'getEpochByNumber', 'getBlockHash', 'getLiveCell'] @@ -151,7 +151,9 @@ export class LightRPC extends Base { if (!tx?.transaction) { tx = await CommonUtils.retry(3, 100, async () => { const tmp = await this.fetchTransaction(hash) - if (tmp === null) {throw new Error('Not fetch the transaction current')} + if ('status' in tmp) { + throw new Error(`transaction ${hash} status: ${tmp.status}`) + } return tmp }) if (!tx) {throw new Error(`Fetch transaction tx failed, please try it later: ${hash}`)} diff --git a/packages/neuron-wallet/tests/controllers/multisig.test.ts b/packages/neuron-wallet/tests/controllers/multisig.test.ts index 6a135ee333..f83962734c 100644 --- a/packages/neuron-wallet/tests/controllers/multisig.test.ts +++ b/packages/neuron-wallet/tests/controllers/multisig.test.ts @@ -18,6 +18,15 @@ jest.mock('electron', () => ({ getFocusedWindow: jest.fn() } })) +jest.mock('services/wallets', () => ({ + getInstance() { + return { + getCurrent() { + return jest.fn() + } + } + } +})) jest.mock('../../src/services/multisig') const MultiSigServiceMock = MultisigService as jest.MockedClass diff --git a/packages/neuron-wallet/tests/controllers/sync-api.test.ts b/packages/neuron-wallet/tests/controllers/sync-api.test.ts index 53d10e68a8..fcb367eefa 100644 --- a/packages/neuron-wallet/tests/controllers/sync-api.test.ts +++ b/packages/neuron-wallet/tests/controllers/sync-api.test.ts @@ -47,6 +47,9 @@ jest.doMock('services/ckb-runner', () => ({ jest.mock('undici', () => ({ request: () => jest.fn()() })) +jest.mock('services/multisig', () => ({ + syncMultisigOutput: () => jest.fn() +})) describe('SyncApiController', () => { const emitter = new Emitter() diff --git a/packages/neuron-wallet/tests/services/light-runner.test.ts b/packages/neuron-wallet/tests/services/light-runner.test.ts index 9f8c886ae7..11b3d85557 100644 --- a/packages/neuron-wallet/tests/services/light-runner.test.ts +++ b/packages/neuron-wallet/tests/services/light-runner.test.ts @@ -19,6 +19,7 @@ const spawnMock = jest.fn() const loggerErrorMock = jest.fn() const loggerInfoMock = jest.fn() const transportsGetFileMock = jest.fn() +const cleanMock = jest.fn() function resetMock() { mockFn.mockReset() @@ -38,6 +39,7 @@ function resetMock() { loggerErrorMock.mockReset() loggerInfoMock.mockReset() transportsGetFileMock.mockReset() + cleanMock.mockReset() } jest.doMock('../../src/env', () => ({ @@ -67,6 +69,10 @@ jest.doMock('../../src/services/settings', () => ({ } })) +jest.doMock('../../src/database/chain', () => ({ + clean: cleanMock +})) + jest.doMock('process', () => ({ get platform() { return platformMock() From f980651d7f3175f68b118f2e5f879d60cd96aaec Mon Sep 17 00:00:00 2001 From: yanguoyu <841185308@qq.com> Date: Tue, 9 May 2023 19:21:30 +0800 Subject: [PATCH 2/3] fix: Rename function name. --- packages/neuron-wallet/src/database/chain/index.ts | 2 +- packages/neuron-wallet/src/services/sync-progress.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/neuron-wallet/src/database/chain/index.ts b/packages/neuron-wallet/src/database/chain/index.ts index ea3eb234c0..a0bde9834a 100644 --- a/packages/neuron-wallet/src/database/chain/index.ts +++ b/packages/neuron-wallet/src/database/chain/index.ts @@ -18,7 +18,7 @@ export const clean = async () => { .getRepository(entity) .clear() }), - SyncProgressService.clear() + SyncProgressService.clearCurrentWalletProgress() ]) MultisigOutputChangedSubject.getSubject().next('reset') diff --git a/packages/neuron-wallet/src/services/sync-progress.ts b/packages/neuron-wallet/src/services/sync-progress.ts index 61f298923b..100a9458fe 100644 --- a/packages/neuron-wallet/src/services/sync-progress.ts +++ b/packages/neuron-wallet/src/services/sync-progress.ts @@ -109,7 +109,7 @@ export default class SyncProgressService { .getMany() } - static async clear() { + static async clearCurrentWalletProgress() { const currentWallet = WalletService.getInstance().getCurrent() await getConnection() .getRepository(SyncProgress) From 101826517d7b02e494ecd36712df6ef550599226 Mon Sep 17 00:00:00 2001 From: yanguoyu <841185308@qq.com> Date: Thu, 11 May 2023 19:09:20 +0800 Subject: [PATCH 3/3] fix: Save number to sqlite when field is `timestamp` or `blockNumber` --- .../src/block-sync-renderer/sync/queue.ts | 8 +++++-- .../tests/block-sync-renderer/queue.test.ts | 21 ++++++++++++++----- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/packages/neuron-wallet/src/block-sync-renderer/sync/queue.ts b/packages/neuron-wallet/src/block-sync-renderer/sync/queue.ts index 8d39e238ae..e08667a452 100644 --- a/packages/neuron-wallet/src/block-sync-renderer/sync/queue.ts +++ b/packages/neuron-wallet/src/block-sync-renderer/sync/queue.ts @@ -10,6 +10,7 @@ import AssetAccountInfo from 'models/asset-account-info' import { Address as AddressInterface } from "models/address" import AddressParser from 'models/address-parser' import Multisig from 'models/multisig' +import BlockHeader from 'models/chain/block-header' import TxAddressFinder from './tx-address-finder' import IndexerConnector from './indexer-connector' import IndexerCacheService from './indexer-cache-service' @@ -134,8 +135,11 @@ export default class Queue { blockHashes.map(v => ['getHeader', v]) ).exec() headers.forEach((blockHeader, idx) => { - txs[idx].timestamp = blockHeader!.timestamp - txs[idx].blockNumber = blockHeader!.number + if (blockHeader) { + const header = BlockHeader.fromSDK(blockHeader) + txs[idx].timestamp = header.timestamp + txs[idx].blockNumber = header.number + } }) return txs } diff --git a/packages/neuron-wallet/tests/block-sync-renderer/queue.test.ts b/packages/neuron-wallet/tests/block-sync-renderer/queue.test.ts index eb964cdee8..9ca3175cab 100644 --- a/packages/neuron-wallet/tests/block-sync-renderer/queue.test.ts +++ b/packages/neuron-wallet/tests/block-sync-renderer/queue.test.ts @@ -73,7 +73,8 @@ const generateFakeTx = (id: string, publicKeyHash: string = '0x') => { lock: Script.fromObject({ hashType: ScriptHashType.Type, codeHash: '0x' + id.repeat(64), args: publicKeyHash }) }) ] - fakeTx.blockNumber = '1' + fakeTx.blockNumber = '0x1' + fakeTx.timestamp = '0x1880a3fa5bc' const fakeTxWithStatus = { transaction: fakeTx, txStatus: new TxStatus('0x' + id.repeat(64), TxStatusType.Committed) @@ -81,6 +82,14 @@ const generateFakeTx = (id: string, publicKeyHash: string = '0x') => { return fakeTxWithStatus } +const fakeBlockHeader = { + version: '0x0', + epoch: '0x0', + hash: `0x${'0'.repeat(64)}`, + parentHash: `0x${'0'.repeat(64)}`, + timestamp: '0x0', + number: '0x0', +} describe('queue', () => { let queue: Queue const fakeNodeUrl = 'http://fakenode:8114' @@ -216,7 +225,7 @@ describe('queue', () => { stubbedGetTransactionFn.mockResolvedValue(fakeTxWithStatus1) stubbedRPCCreateBatchRequestExecFn .mockResolvedValueOnce(fakeTxs) - .mockResolvedValueOnce(fakeTxs.map(v => ({ timestamp: v.transaction.timestamp, number: v.transaction.blockNumber }))) + .mockResolvedValueOnce(fakeTxs.map(v => ({ ...fakeBlockHeader, timestamp: v.transaction.timestamp, number: v.transaction.blockNumber }))) stubbedTransactionsSubject.next({ txHashes: fakeTxs.map(v => v.transaction.hash), params: fakeTxs[0].transaction.blockNumber }) }) describe('when saving transactions is succeeded', () => { @@ -226,7 +235,8 @@ describe('queue', () => { const lockHashes = ['0x1f2615a8dde4e28ca736ff763c2078aff990043f4cbf09eb4b3a58a140a0862d'] const tx = Transaction.fromSDK(fakeTxWithStatus2.transaction.toSDK()) tx.blockHash = fakeTxWithStatus2.txStatus.blockHash! - tx.blockNumber = fakeTxWithStatus2.transaction.blockNumber + tx.blockNumber = BigInt(fakeTxWithStatus2.transaction.blockNumber!).toString() + tx.timestamp = BigInt(fakeTxWithStatus2.transaction.timestamp!).toString() expect(stubbedTxAddressFinderConstructor).toHaveBeenCalledWith( lockHashes, [new AssetAccountInfo().generateAnyoneCanPayScript(addressInfo.blake160).computeHash()], @@ -238,7 +248,8 @@ describe('queue', () => { for (const { transaction } of fakeTxs) { const tx = Transaction.fromSDK(transaction.toSDK()) tx.blockHash = fakeTxWithStatus2.txStatus.blockHash! - tx.blockNumber = fakeTxWithStatus2.transaction.blockNumber + tx.blockNumber = BigInt(fakeTxWithStatus2.transaction.blockNumber!).toString() + tx.timestamp = BigInt(fakeTxWithStatus2.transaction.timestamp!).toString() expect(stubbedSaveFetchFn).toHaveBeenCalledWith(tx) } }) @@ -260,7 +271,7 @@ describe('queue', () => { stubbedSaveFetchFn.mockRejectedValueOnce(err) stubbedRPCCreateBatchRequestExecFn .mockResolvedValueOnce(fakeTxs) - .mockResolvedValueOnce(fakeTxs.map(v => ({ timestamp: v.transaction.timestamp, number: v.transaction.blockNumber }))) + .mockResolvedValueOnce(fakeTxs.map(v => ({ ...fakeBlockHeader, timestamp: v.transaction.timestamp, number: v.transaction.blockNumber }))) stubbedTransactionsSubject.next({ txHashes: fakeTxs.map(v => v.transaction.hash), params: fakeTxs[0].transaction.blockNumber }) await flushPromises() })