From 6003676c7fb01c4ecafbe6650f0e81a8442063e1 Mon Sep 17 00:00:00 2001 From: James Chen Date: Wed, 13 Nov 2019 17:11:06 +0800 Subject: [PATCH 01/12] refactor: Add a simple json store to persist addresses --- .../neuron-wallet/src/database/address/dao.ts | 328 +++++++++--------- .../neuron-wallet/src/services/addresses.ts | 35 +- .../tests/database/address/balance.test.ts | 39 +-- .../tests/database/address/dao.test.ts | 58 ++-- .../tests/services/address.test.ts | 64 ++-- 5 files changed, 227 insertions(+), 297 deletions(-) diff --git a/packages/neuron-wallet/src/database/address/dao.ts b/packages/neuron-wallet/src/database/address/dao.ts index b6eed992c4..f39c116dca 100644 --- a/packages/neuron-wallet/src/database/address/dao.ts +++ b/packages/neuron-wallet/src/database/address/dao.ts @@ -1,13 +1,12 @@ -import { Not, In } from 'typeorm' import { AddressType } from 'models/keys/address' import { TransactionsService } from 'services/tx' import CellsService from 'services/cells' import LockUtils from 'models/lock-utils' import { TransactionStatus } from 'types/cell-types' import { OutputStatus } from 'services/tx/params' -import AddressEntity, { AddressVersion } from './entities/address' -import { getConnection } from './ormconfig' +import { AddressVersion } from './entities/address' import NodeService from 'services/node' +import Store from 'models/store' export interface Address { walletId: string @@ -27,24 +26,20 @@ export interface Address { } export default class AddressDao { - public static create = async (addresses: Address[]): Promise => { - const addressEntities: AddressEntity[] = addresses.map(address => { - const addressEntity = new AddressEntity() - addressEntity.walletId = address.walletId - addressEntity.address = address.address - addressEntity.path = address.path - addressEntity.addressType = address.addressType - addressEntity.addressIndex = address.addressIndex - addressEntity.txCount = address.txCount || 0 - addressEntity.blake160 = address.blake160 - addressEntity.version = address.version - addressEntity.liveBalance = address.liveBalance || '0' - addressEntity.sentBalance = address.sentBalance || '0' - addressEntity.pendingBalance = address.pendingBalance || '0' - return addressEntity + public static create = (addresses: Address[]): Address[] => { + const result = addresses.map(address => { + address.txCount = address.txCount || 0 + address.liveBalance = address.liveBalance || '0' + address.sentBalance = address.sentBalance || '0' + address.pendingBalance = address.pendingBalance || '0' + address.balance = (BigInt(address.liveBalance) + BigInt(address.sentBalance)).toString() + return address }) + return AddressStore.add(result) + } - return getConnection().manager.save(addressEntities) + public static getAll(): Address[] { + return AddressStore.getAll() } // txCount include all txs in db @@ -56,190 +51,177 @@ export default class AddressDao { public static updateTxCountAndBalance = async ( address: string, url: string = NodeService.getInstance().core.rpc.node.url - ): Promise => { - const addressEntities = await getConnection() - .getRepository(AddressEntity) - .find({ - address, - }) + ): Promise => { + const all = AddressStore.getAll() + const toUpdate = all.filter(value => { + return value.address === address + }) + const others = all.filter(value => { + return value.address !== address + }) const txCount: number = await TransactionsService.getCountByAddressAndStatus(address, [ TransactionStatus.Pending, TransactionStatus.Success, ], url) const lockUtils = new LockUtils(await LockUtils.systemScript(url)) - const entities = await Promise.all( - addressEntities.map(async entity => { - const addressEntity = entity - addressEntity.txCount = txCount - const lockHashes: string[] = lockUtils.addressToAllLockHashes(addressEntity.address) - addressEntity.liveBalance = await CellsService.getBalance(lockHashes, OutputStatus.Live) - addressEntity.sentBalance = await CellsService.getBalance(lockHashes, OutputStatus.Sent) - addressEntity.pendingBalance = await CellsService.getBalance(lockHashes, OutputStatus.Pending) - return addressEntity + const result = await Promise.all( + toUpdate.map(async entity => { + const item = entity + item.txCount = txCount + const lockHashes: string[] = lockUtils.addressToAllLockHashes(item.address) + item.liveBalance = await CellsService.getBalance(lockHashes, OutputStatus.Live) + item.sentBalance = await CellsService.getBalance(lockHashes, OutputStatus.Sent) + item.pendingBalance = await CellsService.getBalance(lockHashes, OutputStatus.Pending) + item.balance = (BigInt(item.liveBalance) + BigInt(item.sentBalance)).toString() + return item }) ) - return getConnection().manager.save(entities) - } - - public static nextUnusedAddress = async ( - walletId: string, - version: AddressVersion - ): Promise => { - const addressEntity = await getConnection() - .getRepository(AddressEntity) - .createQueryBuilder('address') - .where({ - walletId, - version, - addressType: AddressType.Receiving, - txCount: 0, - }) - .orderBy('address.addressIndex', 'ASC') - .getOne() - - return addressEntity - } - - public static nextUnusedChangeAddress = async ( - walletId: string, - version: AddressVersion - ): Promise => { - const addressEntity = await getConnection() - .getRepository(AddressEntity) - .createQueryBuilder('address') - .where({ - walletId, - version, - addressType: AddressType.Change, - txCount: 0, - }) - .orderBy('address.addressIndex', 'ASC') - .getOne() + AddressStore.updateAll(toUpdate.concat(others)) + return result + } - return addressEntity + public static nextUnusedAddress(walletId: string, version: AddressVersion): Address | undefined { + const addresses = AddressStore.getAll().filter(value => { + return value.walletId === walletId + && value.version === version + && value.addressType == AddressType.Receiving + && value.txCount === 0 + }) + return addresses.sort((lhs, rhs) => { + return lhs.addressIndex < rhs.addressIndex ? 1 : -1 + })[0] } - public static allAddresses = async (version: AddressVersion): Promise => { - const addressEntities = await getConnection() - .getRepository(AddressEntity) - .createQueryBuilder('address') - .where({ - version, - }) - .getMany() + public static nextUnusedChangeAddress(walletId: string, version: AddressVersion): Address | undefined { + const addresses = AddressStore.getAll().filter(value => { + return value.walletId === walletId + && value.version === version + && value.addressType == AddressType.Change + && value.txCount === 0 + }) + return addresses.sort((lhs, rhs) => { + return lhs.addressIndex < rhs.addressIndex ? 1 : -1 + })[0] + } - return addressEntities + public static allAddresses(version: AddressVersion): Address[] { + const all = AddressStore.getAll() + return all.filter(value => { + return value.version === version + }) } - public static allAddressesByWalletId = async ( - walletId: string, - version: AddressVersion - ): Promise => { - const addressEntities = await getConnection() - .getRepository(AddressEntity) - .createQueryBuilder('address') - .where({ - walletId, - version, - }) - .getMany() - - return addressEntities - } - - public static usedAddressesByWalletId = async ( - walletId: string, - version: AddressVersion - ): Promise => { - const addressEntities = await getConnection() - .getRepository(AddressEntity) - .createQueryBuilder('address') - .where({ - walletId, - version, - txCount: Not(0), - }) - .getMany() + public static allAddressesByWalletId(walletId: string, version: AddressVersion): Address[] { + const all = AddressStore.getAll() + return all.filter(value => { + return value.walletId === walletId && value.version === version + }) + } - return addressEntities + public static usedAddressesByWalletId(walletId: string, version: AddressVersion):Address[] { + const all = AddressStore.getAll() + return all.filter(value => { + return value.walletId === walletId + && value.version === version + && value.txCount !== 0 + }) } - public static findByAddress = async (address: string, walletId: string): Promise => { - const addressEntity = await getConnection() - .getRepository(AddressEntity) - .createQueryBuilder('address') - .where({ - address, - walletId, - }) - .getOne() + public static findByAddress(address: string, walletId: string): Address | undefined { + return AddressStore.getAll().find(value => { + return value.address === address && value.walletId == walletId + }) + } - return addressEntity + public static findByAddresses(addresses: string[]): Address[] { + return AddressStore.getAll().filter(value => { + return addresses.includes(value.address) + }) } - public static findByAddresses = async (addresses: string[]) => { - const addressEntities = await getConnection() - .getRepository(AddressEntity) - .createQueryBuilder('address') - .where({ - address: In(addresses), - }) - .getMany() - return addressEntities - } - - public static maxAddressIndex = async ( - walletId: string, - addressType: AddressType, - version: AddressVersion - ): Promise => { - const addressEntity = await getConnection() - .getRepository(AddressEntity) - .createQueryBuilder('address') - .where({ - walletId, - addressType, - version, - }) - .orderBy('address.addressIndex', 'DESC') - .getOne() + public static maxAddressIndex(walletId: string, addressType: AddressType, version: AddressVersion): Address | undefined { + const addresses = AddressStore.getAll().filter(value => { + return value.walletId === walletId + && value.addressType === addressType + && value.version === version + }) + return addresses.sort((lhs, rhs) => { + return lhs.addressIndex > rhs.addressIndex ? -1 : 1 + })[0] + } - if (!addressEntity) { + public static updateDescription(walletId: string, address: string, description: string): Address | undefined { + const item = AddressDao.findByAddress(address, walletId) + if (!item) { return undefined } + item.description = description + return AddressStore.update(item) + } + + public static deleteByWalletId(walletId: string): Address[] { + const all = AddressStore.getAll() + const toKeep = all.filter(value => { + return value.walletId !== walletId + }) + const deleted = all.filter(value => { + return value.walletId === walletId + }) + AddressStore.updateAll(toKeep) - return addressEntity + return deleted } - public static updateDescription = async (walletId: string, address: string, description: string) => { - const addressEntity = await getConnection() - .getRepository(AddressEntity) - .createQueryBuilder('address') - .where({ - walletId, - address, - }) - .getOne() + public static updateAll(addresses: Address[]) { + AddressStore.updateAll(addresses) + } - if (!addressEntity) { - return undefined + public static deleteAll() { + AddressStore.updateAll([]) + } +} + +/// Persist all addresses as array in `addresses/index.json`. +class AddressStore { + static MODULE_NAME = 'addresses' + static ROOT_KEY = 'addresses' + static store = new Store(AddressStore.MODULE_NAME, 'index.json', '{}') + + static getAll(): Address[] { + const root = AddressStore.store.readSync(AddressStore.ROOT_KEY) + return root || [] + } + + static updateAll(addresses: Address[]) { + AddressStore.store.writeSync(AddressStore.ROOT_KEY, addresses) + } + + static add(addresses: Address[]): Address[] { + const all = AddressStore.getAll() + for (let address of addresses) { + all.push(address) } - addressEntity.description = description - return getConnection().manager.save(addressEntity) + + AddressStore.updateAll(all) + + return addresses } - public static deleteByWalletId = async (walletId: string) => { - const addresses = await getConnection() - .getRepository(AddressEntity) - .createQueryBuilder('address') - .where({ - walletId, - }) - .getMany() - const result = addresses.map(addr => addr.toInterface()) - await getConnection().manager.remove(addresses) - return result + static update(address: Address): Address { + const all = AddressStore.getAll() + const exist = all.findIndex(value => { + return value.walletId === address.walletId && value.address === address.address + }) + if (exist !== -1) { + all[exist] = address + } else { + all.push(address) + } + + AddressStore.updateAll(all) + + return address } } diff --git a/packages/neuron-wallet/src/services/addresses.ts b/packages/neuron-wallet/src/services/addresses.ts index 101d19cafc..5639ee1910 100644 --- a/packages/neuron-wallet/src/services/addresses.ts +++ b/packages/neuron-wallet/src/services/addresses.ts @@ -3,7 +3,7 @@ import { AccountExtendedPublicKey } from 'models/keys/key' import Address, { AddressType } from 'models/keys/address' import LockUtils from 'models/lock-utils' import AddressDao, { Address as AddressInterface } from 'database/address/dao' -import AddressEntity, { AddressVersion } from 'database/address/entities/address' +import { AddressVersion } from 'database/address/entities/address' import AddressCreatedSubject from 'models/subjects/address-created-subject' import NodeService from './node' import ChainInfo from 'models/chain-info' @@ -19,7 +19,7 @@ export interface AddressMetaInfo { export default class AddressService { public static isAddressUsed = async (address: string, walletId: string): Promise => { - const addressEntity = await AddressDao.findByAddress(address, walletId) + const addressEntity = AddressDao.findByAddress(address, walletId) return !!addressEntity } @@ -46,7 +46,7 @@ export default class AddressService { ...addresses.testnetChange, ...addresses.mainnetChange, ] - await AddressDao.create(allAddresses) + AddressDao.create(allAddresses) // TODO: notify address created and pass addressWay AddressService.notifyAddressCreated(allAddresses, isImporting) @@ -72,8 +72,8 @@ export default class AddressService { changeAddressCount: number = 10 ) => { const addressVersion = AddressService.getAddressVersion() - const maxIndexReceivingAddress = await AddressDao.maxAddressIndex(walletId, AddressType.Receiving, addressVersion) - const maxIndexChangeAddress = await AddressDao.maxAddressIndex(walletId, AddressType.Change, addressVersion) + const maxIndexReceivingAddress = AddressDao.maxAddressIndex(walletId, AddressType.Receiving, addressVersion) + const maxIndexChangeAddress = AddressDao.maxAddressIndex(walletId, AddressType.Change, addressVersion) if ( maxIndexReceivingAddress !== undefined && maxIndexReceivingAddress.txCount === 0 && @@ -99,7 +99,7 @@ export default class AddressService { addresses: string[], url: string = NodeService.getInstance().core.rpc.node.url ) => { - let addrs: AddressEntity[] = [] + let addrs: Address[] = [] for (const address of addresses) { const ads = await AddressDao.updateTxCountAndBalance(address, url) addrs = addrs.concat(ads) @@ -197,43 +197,37 @@ export default class AddressService { public static nextUnusedAddress = async (walletId: string): Promise => { const version = AddressService.getAddressVersion() - const addressEntity = await AddressDao.nextUnusedAddress(walletId, version) + const addressEntity = AddressDao.nextUnusedAddress(walletId, version) if (!addressEntity) { return undefined } - return addressEntity.toInterface() + return addressEntity } public static nextUnusedChangeAddress = async (walletId: string): Promise => { const version = AddressService.getAddressVersion() - const addressEntity = await AddressDao.nextUnusedChangeAddress(walletId, version) + const addressEntity = AddressDao.nextUnusedChangeAddress(walletId, version) if (!addressEntity) { return undefined } - return addressEntity.toInterface() + return addressEntity } public static allAddresses = async (): Promise => { const version = AddressService.getAddressVersion() - const addressEntities = await AddressDao.allAddresses(version) - - return addressEntities.map(addr => addr.toInterface()) + return AddressDao.allAddresses(version) } public static allAddressesByWalletId = async (walletId: string): Promise => { const version = AddressService.getAddressVersion() - const addressEntities = await AddressDao.allAddressesByWalletId(walletId, version) - - return addressEntities.map(addr => addr.toInterface()) + return AddressDao.allAddressesByWalletId(walletId, version) } public static usedAddresses = async (walletId: string): Promise => { const version = AddressService.getAddressVersion() - const addressEntities = await AddressDao.usedAddressesByWalletId(walletId, version) - - return addressEntities.map(addr => addr.toInterface()) + return AddressDao.usedAddressesByWalletId(walletId, version) } public static updateDescription = async (walletId: string, address: string, description: string) => { @@ -245,8 +239,7 @@ export default class AddressService { } public static findByAddresses = async (addresses: string[]) => { - const entities = await AddressDao.findByAddresses(addresses) - return entities.map(entity => entity.toInterface()) + return AddressDao.findByAddresses(addresses) } private static getAddressVersion = (): AddressVersion => { diff --git a/packages/neuron-wallet/tests/database/address/balance.test.ts b/packages/neuron-wallet/tests/database/address/balance.test.ts index 3abb13f16f..52156d804e 100644 --- a/packages/neuron-wallet/tests/database/address/balance.test.ts +++ b/packages/neuron-wallet/tests/database/address/balance.test.ts @@ -1,21 +1,10 @@ -import AddressEntity, { AddressVersion } from '../../../src/database/address/entities/address' +import { AddressVersion } from '../../../src/database/address/entities/address' import { AddressType } from '../../../src/models/keys/address' -import initConnection, { getConnection } from '../../../src/database/address/ormconfig' import AddressDao, { Address } from '../../../src/database/address/dao' describe('balance', () => { - beforeAll(async () => { - await initConnection() - }) - - afterAll(async () => { - await getConnection().close() - }) - beforeEach(async () => { - const connection = getConnection() - await connection.dropDatabase() - await connection.synchronize() + AddressDao.deleteAll() }) const generateAddress = ( @@ -43,24 +32,24 @@ describe('balance', () => { it('balance = live + sent - pending', async () => { const address = generateAddress('1000', '100', '300') - const addrs: AddressEntity[] = await AddressDao.create([address]) + const addrs: Address[] = await AddressDao.create([address]) const addr = addrs[0] - expect(addr.balance()).toEqual((1000 + 100).toString()) + expect(addr.balance).toEqual((1000 + 100).toString()) }) it('the balance returned by the toInterface() is correct', async () => { const address = generateAddress('1000', '100', '300') - const addrs: AddressEntity[] = await AddressDao.create([address]) + const addrs: Address[] = AddressDao.create([address]) const addr = addrs[0] - expect(addr.toInterface().balance).toEqual((1000 + 100).toString()) + expect(addr.balance).toEqual((1000 + 100).toString()) }) it('sent to others', async () => { // have 1000, sent to others 200, and refund 800 const addresses = [generateAddress('0', '0', '1000'), generateAddress('0', '800', '0')] - const addrs: AddressEntity[] = await AddressDao.create(addresses) - const balance: bigint = addrs.map(addr => BigInt(addr.balance())).reduce((result, c) => result + c, BigInt(0)) + const addrs: Address[] = await AddressDao.create(addresses) + const balance: bigint = addrs.map(addr => BigInt(addr.balance)).reduce((result, c) => result + c, BigInt(0)) expect(balance).toEqual(BigInt(800)) }) @@ -72,8 +61,8 @@ describe('balance', () => { generateAddress('0', '200', '0'), generateAddress('0', '800', '0'), ] - const addrs: AddressEntity[] = await AddressDao.create(addresses) - const balance: bigint = addrs.map(addr => BigInt(addr.balance())).reduce((result, c) => result + c, BigInt(0)) + const addrs: Address[] = await AddressDao.create(addresses) + const balance: bigint = addrs.map(addr => BigInt(addr.balance)).reduce((result, c) => result + c, BigInt(0)) expect(balance).toEqual(BigInt(1000)) }) @@ -82,8 +71,8 @@ describe('balance', () => { // have 1000, sent to others 200, and refund 790, with 10 shannon fee const addresses = [generateAddress('0', '0', '1000'), generateAddress('0', '790', '0')] - const addrs: AddressEntity[] = await AddressDao.create(addresses) - const balance: bigint = addrs.map(addr => BigInt(addr.balance())).reduce((result, c) => result + c, BigInt(0)) + const addrs: Address[] = await AddressDao.create(addresses) + const balance: bigint = addrs.map(addr => BigInt(addr.balance)).reduce((result, c) => result + c, BigInt(0)) expect(balance).toEqual(BigInt(790)) }) @@ -96,8 +85,8 @@ describe('balance', () => { generateAddress('0', '790', '0'), ] - const addrs: AddressEntity[] = await AddressDao.create(addresses) - const balance: bigint = addrs.map(addr => BigInt(addr.balance())).reduce((result, c) => result + c, BigInt(0)) + const addrs: Address[] = await AddressDao.create(addresses) + const balance: bigint = addrs.map(addr => BigInt(addr.balance)).reduce((result, c) => result + c, BigInt(0)) expect(balance).toEqual(BigInt(990)) }) diff --git a/packages/neuron-wallet/tests/database/address/dao.test.ts b/packages/neuron-wallet/tests/database/address/dao.test.ts index 2f05b462d5..208271f11b 100644 --- a/packages/neuron-wallet/tests/database/address/dao.test.ts +++ b/packages/neuron-wallet/tests/database/address/dao.test.ts @@ -1,6 +1,5 @@ -import AddressEntity, { AddressVersion } from '../../../src/database/address/entities/address' +import { AddressVersion } from '../../../src/database/address/entities/address' import { AddressType } from '../../../src/models/keys/address' -import initConnection, { getConnection } from '../../../src/database/address/ormconfig' import AddressDao, { Address } from '../../../src/database/address/dao' describe('Address Dao tests', () => { @@ -49,27 +48,14 @@ describe('Address Dao tests', () => { version: AddressVersion.Testnet, } - beforeAll(async () => { - await initConnection() - }) - - afterAll(async () => { - await getConnection().close() - }) - beforeEach(async () => { - const connection = getConnection() - await connection.dropDatabase() - await connection.synchronize() + AddressDao.deleteAll() }) it('create', async () => { - await AddressDao.create([address]) + AddressDao.create([address]) - const all = await getConnection() - .getRepository(AddressEntity) - .createQueryBuilder('address') - .getMany() + const all = AddressDao.getAll() expect(all.length).toEqual(1) expect(all[0].address).toEqual(address.address) @@ -90,63 +76,63 @@ describe('Address Dao tests', () => { // }) it('nextUnusedAddress', async () => { - await AddressDao.create([address, usedAddress]) + AddressDao.create([address, usedAddress]) - const addr = await AddressDao.nextUnusedAddress('1', AddressVersion.Testnet) + const addr = AddressDao.nextUnusedAddress('1', AddressVersion.Testnet) expect(addr!.address).toEqual(address.address) - const usedAddr = await AddressDao.nextUnusedAddress('2', AddressVersion.Testnet) + const usedAddr = AddressDao.nextUnusedAddress('2', AddressVersion.Testnet) expect(usedAddr).toBe(undefined) - const mainnetAddr = await AddressDao.nextUnusedAddress('1', AddressVersion.Mainnet) + const mainnetAddr = AddressDao.nextUnusedAddress('1', AddressVersion.Mainnet) expect(mainnetAddr).toBe(undefined) }) it('nextUnusedChangeAddress', async () => { - await AddressDao.create([address, usedAddress, changeAddress]) + AddressDao.create([address, usedAddress, changeAddress]) - const addr = await AddressDao.nextUnusedChangeAddress('1', AddressVersion.Testnet) + const addr = AddressDao.nextUnusedChangeAddress('1', AddressVersion.Testnet) expect(addr!.address).toEqual(changeAddress.address) - const usedAddr = await AddressDao.nextUnusedAddress('2', AddressVersion.Testnet) + const usedAddr = AddressDao.nextUnusedAddress('2', AddressVersion.Testnet) expect(usedAddr).toBe(undefined) - const mainnetAddr = await AddressDao.nextUnusedAddress('1', AddressVersion.Mainnet) + const mainnetAddr = AddressDao.nextUnusedAddress('1', AddressVersion.Mainnet) expect(mainnetAddr).toBe(undefined) }) it('allAddresses', async () => { - await AddressDao.create([address, usedAddress]) + AddressDao.create([address, usedAddress]) - const all = await AddressDao.allAddresses(AddressVersion.Testnet) + const all = AddressDao.allAddresses(AddressVersion.Testnet) - const allMainnet = await AddressDao.allAddresses(AddressVersion.Mainnet) + const allMainnet = AddressDao.allAddresses(AddressVersion.Mainnet) expect(all.length).toEqual(2) expect(allMainnet.length).toEqual(0) }) it('allAddressesByWalletId', async () => { - await AddressDao.create([address, usedAddress]) + AddressDao.create([address, usedAddress]) - const all = await AddressDao.allAddressesByWalletId('1', AddressVersion.Testnet) + const all = AddressDao.allAddressesByWalletId('1', AddressVersion.Testnet) expect(all.length).toEqual(1) }) it('usedAddressByWalletId', async () => { - await AddressDao.create([address, usedAddress]) + AddressDao.create([address, usedAddress]) - const walletOne = await AddressDao.usedAddressesByWalletId('1', AddressVersion.Testnet) + const walletOne = AddressDao.usedAddressesByWalletId('1', AddressVersion.Testnet) expect(walletOne.length).toEqual(0) - const walletTwo = await AddressDao.usedAddressesByWalletId('2', AddressVersion.Testnet) + const walletTwo = AddressDao.usedAddressesByWalletId('2', AddressVersion.Testnet) expect(walletTwo.length).toEqual(1) }) it('findByAddress', async () => { - await AddressDao.create([address, usedAddress]) + AddressDao.create([address, usedAddress]) - const one = await AddressDao.findByAddress(address.address, address.walletId) + const one = AddressDao.findByAddress(address.address, address.walletId) expect(one!.address).toEqual(address.address) }) diff --git a/packages/neuron-wallet/tests/services/address.test.ts b/packages/neuron-wallet/tests/services/address.test.ts index 2fae0cdda5..1d8196bbc8 100644 --- a/packages/neuron-wallet/tests/services/address.test.ts +++ b/packages/neuron-wallet/tests/services/address.test.ts @@ -1,6 +1,5 @@ import AddressService from '../../src/services/addresses' -import initConnection, { getConnection } from '../../src/database/address/ormconfig' -import AddressEntity, { AddressVersion } from '../../src/database/address/entities/address' +import { AddressVersion } from '../../src/database/address/entities/address' import AddressDao, { Address } from '../../src/database/address/dao' import { AddressType } from '../../src/models/keys/address' import { AccountExtendedPublicKey } from '../../src/models/keys/key' @@ -88,18 +87,8 @@ describe('Key tests with db', () => { version: AddressVersion.Testnet, } - beforeAll(async () => { - await initConnection() - }) - - afterAll(async () => { - await getConnection().close() - }) - beforeEach(async () => { - const connection = getConnection() - await connection.dropDatabase() - await connection.synchronize() + AddressDao.deleteAll() }) const generate = async (id: string = walletId) => { @@ -113,10 +102,7 @@ describe('Key tests with db', () => { it('generateAndSave', async () => { await generate() - const all = await getConnection() - .getRepository(AddressEntity) - .createQueryBuilder('address') - .getMany() + const all = AddressDao.getAll() expect(all.length).toEqual((2 + 1) * 2) }) @@ -124,26 +110,23 @@ describe('Key tests with db', () => { it('checkAndGenerateSave', async () => { await generate() - const all = await getConnection() - .getRepository(AddressEntity) - .createQueryBuilder('address') - .getMany() + const all = AddressDao.getAll() const usedAll = all - .filter(one => one.addressType === AddressType.Receiving) .map(one => { - const entity = one - entity.txCount = 1 - return entity + if (one.addressType === AddressType.Receiving) { + const entity = one + entity.txCount = 1 + return entity + } else { + return one + } }) - await getConnection().manager.save(usedAll) + AddressDao.updateAll(usedAll) await checkAndGenerate() - const final = await getConnection() - .getRepository(AddressEntity) - .createQueryBuilder('address') - .getMany() + const final = AddressDao.getAll() expect(final.length).toEqual((2 + 1) * 2 * 2) }) @@ -151,32 +134,29 @@ describe('Key tests with db', () => { it('generateAndSave with two wallet', async () => { await generate() await generate('2') - const all = await getConnection() - .getRepository(AddressEntity) - .createQueryBuilder('address') - .getMany() + const all = AddressDao.getAll() expect(all.length).toEqual((2 + 1) * 2 * 2) }) it('isAddressUsed', async () => { - await AddressDao.create([address, usedAddress]) + AddressDao.create([address, usedAddress]) const used = await AddressService.isAddressUsed(address.address, walletId) expect(used).toBe(true) }) it('nextUnusedAddress', async () => { - await AddressDao.create([address, usedAddress, changeAddress]) + AddressDao.create([address, usedAddress, changeAddress]) const addr = await AddressService.nextUnusedAddress(walletId) - const addrDao = await AddressDao.nextUnusedAddress(walletId, AddressVersion.Testnet) - expect(addr).toEqual(addrDao && addrDao.toInterface()) + const addrDao = AddressDao.nextUnusedAddress(walletId, AddressVersion.Testnet) + expect(addr).toEqual(addrDao) }) it('nextUnusedChangeAddress', async () => { - await AddressDao.create([address, usedAddress, changeAddress]) + AddressDao.create([address, usedAddress, changeAddress]) const addr = await AddressService.nextUnusedChangeAddress(walletId) - const addrDao = await AddressDao.nextUnusedChangeAddress(walletId, AddressVersion.Testnet) - expect(addr).toEqual(addrDao && addrDao.toInterface()) + const addrDao = AddressDao.nextUnusedChangeAddress(walletId, AddressVersion.Testnet) + expect(addr).toEqual(addrDao) }) it('allAddresses', async () => { @@ -194,7 +174,7 @@ describe('Key tests with db', () => { }) it('usedAddress', async () => { - await AddressDao.create([address, usedAddress]) + AddressDao.create([address, usedAddress]) const addr = await AddressService.usedAddresses(walletId) expect(addr).toEqual([]) From 617a9a3cc513397fcc5677b35d3d61b99bd12a30 Mon Sep 17 00:00:00 2001 From: James Chen Date: Wed, 13 Nov 2019 17:24:17 +0800 Subject: [PATCH 02/12] feat: Send address db changed event when address store updates any content --- packages/neuron-wallet/src/database/address/dao.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/packages/neuron-wallet/src/database/address/dao.ts b/packages/neuron-wallet/src/database/address/dao.ts index f39c116dca..1943392334 100644 --- a/packages/neuron-wallet/src/database/address/dao.ts +++ b/packages/neuron-wallet/src/database/address/dao.ts @@ -1,3 +1,4 @@ +import { remote } from 'electron' import { AddressType } from 'models/keys/address' import { TransactionsService } from 'services/tx' import CellsService from 'services/cells' @@ -7,6 +8,7 @@ import { OutputStatus } from 'services/tx/params' import { AddressVersion } from './entities/address' import NodeService from 'services/node' import Store from 'models/store' +import AddressDbChangedSubject from 'models/subjects/address-db-changed-subject' export interface Address { walletId: string @@ -183,6 +185,11 @@ export default class AddressDao { } } +const isRenderer = process && process.type === 'renderer' +const addressDbChangedSubject = isRenderer + ? remote.require('./models/subjects/address-db-changed-subject').default.getSubject() + : AddressDbChangedSubject.getSubject() + /// Persist all addresses as array in `addresses/index.json`. class AddressStore { static MODULE_NAME = 'addresses' @@ -196,6 +203,7 @@ class AddressStore { static updateAll(addresses: Address[]) { AddressStore.store.writeSync(AddressStore.ROOT_KEY, addresses) + AddressStore.changed() } static add(addresses: Address[]): Address[] { @@ -224,4 +232,8 @@ class AddressStore { return address } + + static changed() { + addressDbChangedSubject.next("Updated") + } } From 6f9534040df87df533a431a04ce433a0533656ae Mon Sep 17 00:00:00 2001 From: James Chen Date: Wed, 13 Nov 2019 18:08:17 +0800 Subject: [PATCH 03/12] feat: Remove address sqlite db --- ormconfig-address.json | 21 ---- package.json | 3 +- .../address/{dao.ts => address-dao.ts} | 6 +- .../src/database/address/entities/address.ts | 116 ------------------ .../migrations/1561461669542-AddAddress.ts | 13 -- .../migrations/1562126909151-extendBalance.ts | 24 ---- .../1567485550388-AddTotalBalance.ts | 17 --- .../1573458655136-RemoveTotalBalance.ts | 17 --- .../src/database/address/ormconfig.ts | 51 -------- .../neuron-wallet/src/listeners/address.ts | 3 +- packages/neuron-wallet/src/main.ts | 2 - .../subjects/address-created-subject.ts | 2 +- .../neuron-wallet/src/services/addresses.ts | 16 +-- .../neuron-wallet/src/services/wallets.ts | 2 +- .../src/startup/sync-block-task/indexer.ts | 2 +- .../src/startup/sync-block-task/sync.ts | 2 +- .../src/startup/sync-block-task/task.ts | 2 - .../tests/database/address/balance.test.ts | 3 +- .../tests/database/address/dao.test.ts | 3 +- .../tests/services/address.test.ts | 3 +- 20 files changed, 21 insertions(+), 287 deletions(-) delete mode 100644 ormconfig-address.json rename packages/neuron-wallet/src/database/address/{dao.ts => address-dao.ts} (99%) delete mode 100644 packages/neuron-wallet/src/database/address/entities/address.ts delete mode 100644 packages/neuron-wallet/src/database/address/migrations/1561461669542-AddAddress.ts delete mode 100644 packages/neuron-wallet/src/database/address/migrations/1562126909151-extendBalance.ts delete mode 100644 packages/neuron-wallet/src/database/address/migrations/1567485550388-AddTotalBalance.ts delete mode 100644 packages/neuron-wallet/src/database/address/migrations/1573458655136-RemoveTotalBalance.ts delete mode 100644 packages/neuron-wallet/src/database/address/ormconfig.ts diff --git a/ormconfig-address.json b/ormconfig-address.json deleted file mode 100644 index 89b3d7e5ca..0000000000 --- a/ormconfig-address.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "sqlite", - "synchronize": false, - "migrationsRun": true, - "logging": true, - "database": "address-dev.sqlite", - "entities": [ - "packages/neuron-wallet/dist/database/address/entities/**/*.js" - ], - "migrations": [ - "packages/neuron-wallet/dist/database/address/migrations/**/*.js" - ], - "subscribers": [ - "packages/neuron-wallet/dist/database/address/subscriber/**/*.js" - ], - "cli": { - "entitiesDir": "packages/neuron-wallet/src/database/address/entities", - "migrationsDir": "packages/neuron-wallet/src/database/address/migrations", - "subscribersDir": "packages/neuron-wallet/src/database/address/subscriber" - } -} diff --git a/package.json b/package.json index e4d3b62edf..cca3c7e96c 100644 --- a/package.json +++ b/package.json @@ -34,8 +34,7 @@ "test:e2e": "yarn build && ./scripts/copy-ui-files.sh && lerna run --parallel test:e2e", "lint": "lerna run --stream lint", "postinstall": "lerna run rebuild:nativemodules", - "db:chain": "node ./node_modules/.bin/typeorm", - "db:address": "node ./node_modules/.bin/typeorm --config ormconfig-address.json" + "db:chain": "node ./node_modules/.bin/typeorm" }, "husky": { "hooks": { diff --git a/packages/neuron-wallet/src/database/address/dao.ts b/packages/neuron-wallet/src/database/address/address-dao.ts similarity index 99% rename from packages/neuron-wallet/src/database/address/dao.ts rename to packages/neuron-wallet/src/database/address/address-dao.ts index 1943392334..76b6b28b5e 100644 --- a/packages/neuron-wallet/src/database/address/dao.ts +++ b/packages/neuron-wallet/src/database/address/address-dao.ts @@ -5,11 +5,15 @@ import CellsService from 'services/cells' import LockUtils from 'models/lock-utils' import { TransactionStatus } from 'types/cell-types' import { OutputStatus } from 'services/tx/params' -import { AddressVersion } from './entities/address' import NodeService from 'services/node' import Store from 'models/store' import AddressDbChangedSubject from 'models/subjects/address-db-changed-subject' +export enum AddressVersion { + Testnet = 'testnet', + Mainnet = 'mainnet', +} + export interface Address { walletId: string address: string diff --git a/packages/neuron-wallet/src/database/address/entities/address.ts b/packages/neuron-wallet/src/database/address/entities/address.ts deleted file mode 100644 index 1cdd995d60..0000000000 --- a/packages/neuron-wallet/src/database/address/entities/address.ts +++ /dev/null @@ -1,116 +0,0 @@ -import { remote } from 'electron' -import { Entity, BaseEntity, PrimaryColumn, Column, AfterInsert, AfterUpdate, AfterRemove } from 'typeorm' -import { AddressType } from 'models/keys/address' -import AddressDbChangedSubject from 'models/subjects/address-db-changed-subject' -import { Address as AddressInterface } from '../dao' - -export enum AddressVersion { - Testnet = 'testnet', - Mainnet = 'mainnet', -} - -const isRenderer = process && process.type === 'renderer' -const addressDbChangedSubject = isRenderer - ? remote.require('./models/subjects/address-db-changed-subject').default.getSubject() - : AddressDbChangedSubject.getSubject() - -@Entity() -export default class Address extends BaseEntity { - @PrimaryColumn({ - type: 'varchar', - }) - address!: string - - @PrimaryColumn({ - type: 'varchar', - }) - walletId!: string - - @Column({ - type: 'varchar', - }) - path!: string - - @Column({ - type: 'int', - }) - addressType!: AddressType - - @Column({ - type: 'int', - }) - addressIndex!: number - - @Column({ - type: 'int', - }) - txCount!: number - - @Column({ - type: 'varchar', - }) - blake160!: string - - @Column({ - type: 'varchar', - }) - version!: AddressVersion - - @Column({ - type: 'varchar', - nullable: true, - }) - description?: string - - @Column({ - type: 'varchar', - }) - liveBalance: string = '0' - - @Column() - sentBalance: string = '0' - - @Column() - pendingBalance: string = '0' - - public balance = (): string => { - return (BigInt(this.liveBalance) + BigInt(this.sentBalance)).toString() - } - - public toInterface = (): AddressInterface => { - return { - address: this.address, - walletId: this.walletId, - path: this.path, - addressType: this.addressType, - addressIndex: this.addressIndex, - txCount: this.txCount, - blake160: this.blake160, - version: this.version, - liveBalance: this.liveBalance, - sentBalance: this.sentBalance, - pendingBalance: this.pendingBalance, - balance: this.balance(), - description: this.description, - } - } - - @AfterInsert() - emitInsert() { - this.changed('AfterInsert') - } - - @AfterUpdate() - emitUpdate() { - this.changed('AfterUpdate') - } - - @AfterRemove() - emitRemove() { - this.changed('AfterRemove') - } - - private changed = (event: string) => { - addressDbChangedSubject.next(event) - } -} diff --git a/packages/neuron-wallet/src/database/address/migrations/1561461669542-AddAddress.ts b/packages/neuron-wallet/src/database/address/migrations/1561461669542-AddAddress.ts deleted file mode 100644 index 34bccf8ae8..0000000000 --- a/packages/neuron-wallet/src/database/address/migrations/1561461669542-AddAddress.ts +++ /dev/null @@ -1,13 +0,0 @@ -import {MigrationInterface, QueryRunner} from "typeorm"; - -export class AddAddress1561461669542 implements MigrationInterface { - - public async up(queryRunner: QueryRunner): Promise { - await queryRunner.query(`CREATE TABLE "address" ("address" varchar NOT NULL, "walletId" varchar NOT NULL, "path" varchar NOT NULL, "addressType" integer NOT NULL, "addressIndex" integer NOT NULL, "txCount" integer NOT NULL, "blake160" varchar NOT NULL, "version" varchar NOT NULL, "description" varchar, "balance" varchar NOT NULL, PRIMARY KEY ("address", "walletId"))`); - } - - public async down(queryRunner: QueryRunner): Promise { - await queryRunner.query(`DROP TABLE "address"`); - } - -} diff --git a/packages/neuron-wallet/src/database/address/migrations/1562126909151-extendBalance.ts b/packages/neuron-wallet/src/database/address/migrations/1562126909151-extendBalance.ts deleted file mode 100644 index 516d5befbc..0000000000 --- a/packages/neuron-wallet/src/database/address/migrations/1562126909151-extendBalance.ts +++ /dev/null @@ -1,24 +0,0 @@ -import {MigrationInterface, QueryRunner, TableColumn} from "typeorm"; - -export class extendBalance1562126909151 implements MigrationInterface { - - public async up(queryRunner: QueryRunner): Promise { - await queryRunner.query(`ALTER TABLE 'address' ADD COLUMN 'sentBalance' varchar NOT NULL DEFAULT '0';`) - await queryRunner.query(`ALTER TABLE 'address' ADD COLUMN 'pendingBalance' varchar NOT NULL DEFAULT '0';`) - - await queryRunner.changeColumn('address', 'balance', new TableColumn({ - name: 'liveBalance', - type: 'varchar', - })) - } - - public async down(queryRunner: QueryRunner): Promise { - await queryRunner.dropColumn('address', 'sentBalance') - await queryRunner.dropColumn('address', 'pendingBalance') - await queryRunner.changeColumn('address', 'liveBalance', new TableColumn({ - name: 'balance', - type: 'varchar', - })) - } - -} diff --git a/packages/neuron-wallet/src/database/address/migrations/1567485550388-AddTotalBalance.ts b/packages/neuron-wallet/src/database/address/migrations/1567485550388-AddTotalBalance.ts deleted file mode 100644 index 03b3e5df9b..0000000000 --- a/packages/neuron-wallet/src/database/address/migrations/1567485550388-AddTotalBalance.ts +++ /dev/null @@ -1,17 +0,0 @@ -import {MigrationInterface, QueryRunner, TableColumn} from "typeorm"; - -export class AddTotalBalance1567485550388 implements MigrationInterface { - - public async up(queryRunner: QueryRunner): Promise { - await queryRunner.addColumn('address', new TableColumn({ - name: 'totalBalance', - type: 'varchar', - default: '0', - })) - } - - public async down(queryRunner: QueryRunner): Promise { - await queryRunner.dropColumn('address', 'totalBalance') - } - -} diff --git a/packages/neuron-wallet/src/database/address/migrations/1573458655136-RemoveTotalBalance.ts b/packages/neuron-wallet/src/database/address/migrations/1573458655136-RemoveTotalBalance.ts deleted file mode 100644 index 4bc22a5710..0000000000 --- a/packages/neuron-wallet/src/database/address/migrations/1573458655136-RemoveTotalBalance.ts +++ /dev/null @@ -1,17 +0,0 @@ -import {MigrationInterface, QueryRunner, TableColumn} from "typeorm"; - -export class RemoveTotalBalance1573458655136 implements MigrationInterface { - - public async up(queryRunner: QueryRunner): Promise { - await queryRunner.dropColumn('address', 'totalBalance') - } - - public async down(queryRunner: QueryRunner): Promise { - await queryRunner.addColumn('address', new TableColumn({ - name: 'totalBalance', - type: 'varchar', - default: '0', - })) - } - -} diff --git a/packages/neuron-wallet/src/database/address/ormconfig.ts b/packages/neuron-wallet/src/database/address/ormconfig.ts deleted file mode 100644 index 3aa6ee695a..0000000000 --- a/packages/neuron-wallet/src/database/address/ormconfig.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { createConnection, getConnection as ormGetConnection } from 'typeorm' -import { SqliteConnectionOptions } from 'typeorm/driver/sqlite/SqliteConnectionOptions' -import path from 'path' - -import env from 'env' - -import Address from './entities/address' - -import { AddAddress1561461669542 } from './migrations/1561461669542-AddAddress' -import { extendBalance1562126909151 } from './migrations/1562126909151-extendBalance' -import { AddTotalBalance1567485550388 } from './migrations/1567485550388-AddTotalBalance' -import { RemoveTotalBalance1573458655136 } from './migrations/1573458655136-RemoveTotalBalance' - -const dbPath = path.join(env.fileBasePath, 'address.sqlite') - -const connectionName = 'address' - -const connectOptions = (): SqliteConnectionOptions => { - const database = env.isTestMode ? ':memory:' : dbPath - return { - name: connectionName, - type: 'sqlite', - database, - entities: [Address], - migrations: [ - AddAddress1561461669542, - extendBalance1562126909151, - AddTotalBalance1567485550388, - RemoveTotalBalance1573458655136, - ], - synchronize: false, - migrationsRun: true, - logging: ['error'], - } -} - -export const getConnection = () => { - return ormGetConnection(connectionName) -} - -const setBusyTimeout = async () => { - await getConnection().manager.query(`PRAGMA busy_timeout = 3000;`) -} - -export const initConnection = async () => { - const connectionOptions = connectOptions() - await createConnection(connectionOptions) - await setBusyTimeout() -} - -export default initConnection diff --git a/packages/neuron-wallet/src/listeners/address.ts b/packages/neuron-wallet/src/listeners/address.ts index 6b3994240e..26af7af070 100644 --- a/packages/neuron-wallet/src/listeners/address.ts +++ b/packages/neuron-wallet/src/listeners/address.ts @@ -3,6 +3,7 @@ import { ReplaySubject } from 'rxjs' import { bufferTime } from 'rxjs/operators' import AddressesUsedSubject, { AddressesWithURL } from 'models/subjects/addresses-used-subject' import AddressService from 'services/addresses' +import { Address } from 'database/address/address-dao' import WalletService from 'services/wallets' import { AccountExtendedPublicKey } from 'models/keys/key' @@ -27,7 +28,7 @@ export const register = () => { const url: string = addressesList[addressesList.length - 1].url const uniqueAddresses = [...new Set(addresses)] const addrs = await AddressService.updateTxCountAndBalances(uniqueAddresses, url) - const walletIds: string[] = addrs.map(addr => addr.walletId).filter((value, idx, a) => a.indexOf(value) === idx) + const walletIds: string[] = addrs.map(addr => (addr as Address).walletId).filter((value, idx, a) => a.indexOf(value) === idx) await Promise.all( walletIds.map(async id => { const wallet = WalletService.getInstance().get(id) diff --git a/packages/neuron-wallet/src/main.ts b/packages/neuron-wallet/src/main.ts index 550f1588eb..bb62cfe71e 100644 --- a/packages/neuron-wallet/src/main.ts +++ b/packages/neuron-wallet/src/main.ts @@ -1,7 +1,6 @@ import { app } from 'electron' import AppController from 'controllers/app' -import initConnection from 'database/address/ormconfig' import createSyncBlockTask from 'startup/sync-block-task/create' import { changeLanguage } from 'utils/i18n' @@ -10,7 +9,6 @@ const appController = new AppController() app.on('ready', async () => { changeLanguage(app.getLocale()) - await initConnection() createSyncBlockTask() appController.openWindow() diff --git a/packages/neuron-wallet/src/models/subjects/address-created-subject.ts b/packages/neuron-wallet/src/models/subjects/address-created-subject.ts index 40f5ab3fc9..63ff7968cd 100644 --- a/packages/neuron-wallet/src/models/subjects/address-created-subject.ts +++ b/packages/neuron-wallet/src/models/subjects/address-created-subject.ts @@ -1,5 +1,5 @@ import { ReplaySubject } from 'rxjs' -import { Address } from 'database/address/dao' +import { Address } from 'database/address/address-dao' export default class AddressCreatedSubject { static subject = new ReplaySubject(100) diff --git a/packages/neuron-wallet/src/services/addresses.ts b/packages/neuron-wallet/src/services/addresses.ts index 5639ee1910..d3e080ca53 100644 --- a/packages/neuron-wallet/src/services/addresses.ts +++ b/packages/neuron-wallet/src/services/addresses.ts @@ -2,8 +2,7 @@ import { AddressPrefix } from '@nervosnetwork/ckb-sdk-utils' import { AccountExtendedPublicKey } from 'models/keys/key' import Address, { AddressType } from 'models/keys/address' import LockUtils from 'models/lock-utils' -import AddressDao, { Address as AddressInterface } from 'database/address/dao' -import { AddressVersion } from 'database/address/entities/address' +import AddressDao, { Address as AddressInterface, AddressVersion } from 'database/address/address-dao' import AddressCreatedSubject from 'models/subjects/address-created-subject' import NodeService from './node' import ChainInfo from 'models/chain-info' @@ -95,16 +94,13 @@ export default class AddressService { ) } - public static updateTxCountAndBalances = async ( - addresses: string[], - url: string = NodeService.getInstance().core.rpc.node.url - ) => { - let addrs: Address[] = [] + public static updateTxCountAndBalances = async (addresses: string[], url: string = NodeService.getInstance().core.rpc.node.url) => { + let result: Address[] = [] for (const address of addresses) { - const ads = await AddressDao.updateTxCountAndBalance(address, url) - addrs = addrs.concat(ads) + const updatedAddress = await AddressDao.updateTxCountAndBalance(address, url) + result = result.concat(updatedAddress) } - return addrs + return result } // Generate both receiving and change addresses. diff --git a/packages/neuron-wallet/src/services/wallets.ts b/packages/neuron-wallet/src/services/wallets.ts index 490cc3550e..f3a24f4c11 100644 --- a/packages/neuron-wallet/src/services/wallets.ts +++ b/packages/neuron-wallet/src/services/wallets.ts @@ -7,7 +7,7 @@ import LockUtils from 'models/lock-utils' import { TransactionWithoutHash, Input, OutPoint, WitnessArgs } from 'types/cell-types' import ConvertTo from 'types/convert-to' import { WalletNotFound, IsRequired, UsedName } from 'exceptions' -import { Address as AddressInterface } from 'database/address/dao' +import { Address as AddressInterface } from 'database/address/address-dao' import Keychain from 'models/keys/keychain' import AddressDbChangedSubject from 'models/subjects/address-db-changed-subject' import AddressesUsedSubject from 'models/subjects/addresses-used-subject' diff --git a/packages/neuron-wallet/src/startup/sync-block-task/indexer.ts b/packages/neuron-wallet/src/startup/sync-block-task/indexer.ts index cb1331ba7c..3300e261ab 100644 --- a/packages/neuron-wallet/src/startup/sync-block-task/indexer.ts +++ b/packages/neuron-wallet/src/startup/sync-block-task/indexer.ts @@ -2,7 +2,7 @@ import { remote } from 'electron' import AddressService from 'services/addresses' import LockUtils from 'models/lock-utils' import IndexerQueue, { LockHashInfo } from 'services/indexer/queue' -import { Address } from 'database/address/dao' +import { Address } from 'database/address/address-dao' import initConnection from 'database/chain/ormconfig' import ChainInfo from 'models/chain-info' diff --git a/packages/neuron-wallet/src/startup/sync-block-task/sync.ts b/packages/neuron-wallet/src/startup/sync-block-task/sync.ts index decb81948f..3c35053760 100644 --- a/packages/neuron-wallet/src/startup/sync-block-task/sync.ts +++ b/packages/neuron-wallet/src/startup/sync-block-task/sync.ts @@ -2,7 +2,7 @@ import { remote } from 'electron' import AddressService from 'services/addresses' import LockUtils from 'models/lock-utils' import BlockListener from 'services/sync/block-listener' -import { Address } from 'database/address/dao' +import { Address } from 'database/address/address-dao' import initConnection from 'database/chain/ormconfig' import ChainInfo from 'models/chain-info' diff --git a/packages/neuron-wallet/src/startup/sync-block-task/task.ts b/packages/neuron-wallet/src/startup/sync-block-task/task.ts index 9b7d4abc98..31c0226e0f 100644 --- a/packages/neuron-wallet/src/startup/sync-block-task/task.ts +++ b/packages/neuron-wallet/src/startup/sync-block-task/task.ts @@ -1,5 +1,4 @@ import { remote } from 'electron' -import { initConnection as initAddressConnection } from 'database/address/ormconfig' import AddressesUsedSubject from 'models/subjects/addresses-used-subject' import { register as registerTxStatusListener } from 'listeners/tx-status' import { register as registerAddressListener } from 'listeners/address' @@ -31,7 +30,6 @@ export const testIndexer = async (url: string): Promise => { } export const run = async () => { - await initAddressConnection() databaseInitSubject.subscribe(async (params: DatabaseInitParams) => { const { network, genesisBlockHash, chain } = params if (network && genesisBlockHash.startsWith('0x')) { diff --git a/packages/neuron-wallet/tests/database/address/balance.test.ts b/packages/neuron-wallet/tests/database/address/balance.test.ts index 52156d804e..c45ef8fd66 100644 --- a/packages/neuron-wallet/tests/database/address/balance.test.ts +++ b/packages/neuron-wallet/tests/database/address/balance.test.ts @@ -1,6 +1,5 @@ -import { AddressVersion } from '../../../src/database/address/entities/address' import { AddressType } from '../../../src/models/keys/address' -import AddressDao, { Address } from '../../../src/database/address/dao' +import AddressDao, { Address, AddressVersion } from '../../../src/database/address/address-dao' describe('balance', () => { beforeEach(async () => { diff --git a/packages/neuron-wallet/tests/database/address/dao.test.ts b/packages/neuron-wallet/tests/database/address/dao.test.ts index 208271f11b..ae9b459c2a 100644 --- a/packages/neuron-wallet/tests/database/address/dao.test.ts +++ b/packages/neuron-wallet/tests/database/address/dao.test.ts @@ -1,6 +1,5 @@ -import { AddressVersion } from '../../../src/database/address/entities/address' import { AddressType } from '../../../src/models/keys/address' -import AddressDao, { Address } from '../../../src/database/address/dao' +import AddressDao, { Address, AddressVersion } from '../../../src/database/address/address-dao' describe('Address Dao tests', () => { const address: Address = { diff --git a/packages/neuron-wallet/tests/services/address.test.ts b/packages/neuron-wallet/tests/services/address.test.ts index 1d8196bbc8..1746b4d7f1 100644 --- a/packages/neuron-wallet/tests/services/address.test.ts +++ b/packages/neuron-wallet/tests/services/address.test.ts @@ -1,6 +1,5 @@ import AddressService from '../../src/services/addresses' -import { AddressVersion } from '../../src/database/address/entities/address' -import AddressDao, { Address } from '../../src/database/address/dao' +import AddressDao, { Address, AddressVersion } from '../../src/database/address/address-dao' import { AddressType } from '../../src/models/keys/address' import { AccountExtendedPublicKey } from '../../src/models/keys/key' From 9988a13e08db498429d3ef3ed9b15000bd33cc11 Mon Sep 17 00:00:00 2001 From: James Chen Date: Wed, 13 Nov 2019 22:06:18 +0800 Subject: [PATCH 04/12] feat: Regenerate addresses if necessary on launch --- .../src/controllers/app/index.ts | 3 ++ .../neuron-wallet/src/controllers/wallets.ts | 38 +++++++++---------- .../src/database/address/address-dao.ts | 9 +++-- .../neuron-wallet/src/services/addresses.ts | 6 +-- .../neuron-wallet/src/services/wallets.ts | 12 +++++- 5 files changed, 39 insertions(+), 29 deletions(-) diff --git a/packages/neuron-wallet/src/controllers/app/index.ts b/packages/neuron-wallet/src/controllers/app/index.ts index e5e404d159..6a0ed85bd5 100644 --- a/packages/neuron-wallet/src/controllers/app/index.ts +++ b/packages/neuron-wallet/src/controllers/app/index.ts @@ -6,6 +6,7 @@ import env from 'env' import { updateApplicationMenu } from './menu' import logger from 'utils/logger' import { subscribe } from './subscribe' +import WalletService from 'services/wallets' const app = electronApp || (remote && remote.app) @@ -65,6 +66,8 @@ export default class AppController { this.mainWindow.show() this.mainWindow.focus() logger.info('The main window is ready to show') + + WalletService.getInstance().generateAddressesIfNecessary() } else { logger.error('The main window is not initialized on ready to show') } diff --git a/packages/neuron-wallet/src/controllers/wallets.ts b/packages/neuron-wallet/src/controllers/wallets.ts index a8aa816d5b..cf4400795a 100644 --- a/packages/neuron-wallet/src/controllers/wallets.ts +++ b/packages/neuron-wallet/src/controllers/wallets.ts @@ -294,26 +294,24 @@ export default class WalletsController { } public static async getAllAddresses(id: string) { - const addresses = await AddressService.allAddressesByWalletId(id).then(addrs => - addrs.map( - ({ - address, - blake160: identifier, - addressType: type, - txCount, - balance, - description = '', - addressIndex: index = '', - }) => ({ - address, - identifier, - type, - txCount, - description, - balance, - index, - }) - ) + const addresses = AddressService.allAddressesByWalletId(id).map( + ({ + address, + blake160: identifier, + addressType: type, + txCount, + balance, + description = '', + addressIndex: index = '', + }) => ({ + address, + identifier, + type, + txCount, + description, + balance, + index, + }) ) return { status: ResponseCode.Success, diff --git a/packages/neuron-wallet/src/database/address/address-dao.ts b/packages/neuron-wallet/src/database/address/address-dao.ts index 76b6b28b5e..f252311fc3 100644 --- a/packages/neuron-wallet/src/database/address/address-dao.ts +++ b/packages/neuron-wallet/src/database/address/address-dao.ts @@ -120,10 +120,11 @@ export default class AddressDao { } public static allAddressesByWalletId(walletId: string, version: AddressVersion): Address[] { - const all = AddressStore.getAll() - return all.filter(value => { - return value.walletId === walletId && value.version === version - }) + return AddressStore.getAll() + .filter(value => value.walletId === walletId && value.version === version) + .sort((lhs, rhs) => { + return lhs.addressType - rhs.addressType || lhs.addressIndex - rhs.addressIndex + }) } public static usedAddressesByWalletId(walletId: string, version: AddressVersion):Address[] { diff --git a/packages/neuron-wallet/src/services/addresses.ts b/packages/neuron-wallet/src/services/addresses.ts index d3e080ca53..b81b36175a 100644 --- a/packages/neuron-wallet/src/services/addresses.ts +++ b/packages/neuron-wallet/src/services/addresses.ts @@ -22,7 +22,7 @@ export default class AddressService { return !!addressEntity } - public static generateAndSave = async ( + public static generateAndSave = ( walletId: string, extendedKey: AccountExtendedPublicKey, isImporting: boolean | undefined, @@ -63,7 +63,7 @@ export default class AddressService { AddressCreatedSubject.getSubject().next(addrs) } - public static checkAndGenerateSave = async ( + public static checkAndGenerateSave = ( walletId: string, extendedKey: AccountExtendedPublicKey, isImporting: boolean | undefined, @@ -216,7 +216,7 @@ export default class AddressService { return AddressDao.allAddresses(version) } - public static allAddressesByWalletId = async (walletId: string): Promise => { + public static allAddressesByWalletId = (walletId: string): AddressInterface[] => { const version = AddressService.getAddressVersion() return AddressDao.allAddressesByWalletId(walletId, version) } diff --git a/packages/neuron-wallet/src/services/wallets.ts b/packages/neuron-wallet/src/services/wallets.ts index f3a24f4c11..056c00beca 100644 --- a/packages/neuron-wallet/src/services/wallets.ts +++ b/packages/neuron-wallet/src/services/wallets.ts @@ -173,7 +173,15 @@ export default class WalletService { return FileKeystoreWallet.fromJSON(wallet) } - public generateAddressesById = async ( + public generateAddressesIfNecessary = () => { + for (const wallet of this.getAll()) { + if (AddressService.allAddressesByWalletId(wallet.id).length === 0) { + this.generateAddressesById(wallet.id, false) + } + } + } + + public generateAddressesById = ( id: string, isImporting: boolean, receivingAddressCount: number = 20, @@ -181,7 +189,7 @@ export default class WalletService { ) => { const wallet: Wallet = this.get(id) const accountExtendedPublicKey: AccountExtendedPublicKey = wallet.accountExtendedPublicKey() - await AddressService.checkAndGenerateSave( + AddressService.checkAndGenerateSave( id, accountExtendedPublicKey, isImporting, From 0eafab291daa14baf8535fd70d7fc387bd4aaab5 Mon Sep 17 00:00:00 2001 From: James Chen Date: Thu, 14 Nov 2019 10:02:49 +0800 Subject: [PATCH 05/12] refactor: Remove unnecessary async/await call on address modules --- .../neuron-wallet/src/controllers/wallets.ts | 2 +- .../src/database/address/address-dao.ts | 2 +- .../neuron-wallet/src/listeners/address.ts | 14 +++--- .../neuron-wallet/src/services/addresses.ts | 16 +++--- .../neuron-wallet/src/services/wallets.ts | 38 +++++--------- .../src/startup/sync-block-task/create.ts | 2 +- .../src/startup/sync-block-task/indexer.ts | 2 +- .../src/startup/sync-block-task/sync.ts | 2 +- .../tests/services/address.test.ts | 50 +++++++++---------- 9 files changed, 56 insertions(+), 72 deletions(-) diff --git a/packages/neuron-wallet/src/controllers/wallets.ts b/packages/neuron-wallet/src/controllers/wallets.ts index cf4400795a..bf895fc921 100644 --- a/packages/neuron-wallet/src/controllers/wallets.ts +++ b/packages/neuron-wallet/src/controllers/wallets.ts @@ -499,7 +499,7 @@ export default class WalletsController { const walletService = WalletsService.getInstance() const wallet = walletService.get(walletID) - await AddressService.updateDescription(wallet.id, address, description) + AddressService.updateDescription(wallet.id, address, description) return { status: ResponseCode.Success, diff --git a/packages/neuron-wallet/src/database/address/address-dao.ts b/packages/neuron-wallet/src/database/address/address-dao.ts index f252311fc3..c2b48409e6 100644 --- a/packages/neuron-wallet/src/database/address/address-dao.ts +++ b/packages/neuron-wallet/src/database/address/address-dao.ts @@ -127,7 +127,7 @@ export default class AddressDao { }) } - public static usedAddressesByWalletId(walletId: string, version: AddressVersion):Address[] { + public static usedAddressesByWalletId(walletId: string, version: AddressVersion): Address[] { const all = AddressStore.getAll() return all.filter(value => { return value.walletId === walletId diff --git a/packages/neuron-wallet/src/listeners/address.ts b/packages/neuron-wallet/src/listeners/address.ts index 26af7af070..845105fd7f 100644 --- a/packages/neuron-wallet/src/listeners/address.ts +++ b/packages/neuron-wallet/src/listeners/address.ts @@ -29,14 +29,12 @@ export const register = () => { const uniqueAddresses = [...new Set(addresses)] const addrs = await AddressService.updateTxCountAndBalances(uniqueAddresses, url) const walletIds: string[] = addrs.map(addr => (addr as Address).walletId).filter((value, idx, a) => a.indexOf(value) === idx) - await Promise.all( - walletIds.map(async id => { - const wallet = WalletService.getInstance().get(id) - const accountExtendedPublicKey: AccountExtendedPublicKey = wallet.accountExtendedPublicKey() - // set isImporting to undefined means unknown - await AddressService.checkAndGenerateSave(id, accountExtendedPublicKey, undefined, 20, 10) - }) - ) + for (const id of walletIds) { + const wallet = WalletService.getInstance().get(id) + const accountExtendedPublicKey: AccountExtendedPublicKey = wallet.accountExtendedPublicKey() + // set isImporting to undefined means unknown + AddressService.checkAndGenerateSave(id, accountExtendedPublicKey, undefined, 20, 10) + } }) } diff --git a/packages/neuron-wallet/src/services/addresses.ts b/packages/neuron-wallet/src/services/addresses.ts index b81b36175a..5c479c4df3 100644 --- a/packages/neuron-wallet/src/services/addresses.ts +++ b/packages/neuron-wallet/src/services/addresses.ts @@ -17,7 +17,7 @@ export interface AddressMetaInfo { } export default class AddressService { - public static isAddressUsed = async (address: string, walletId: string): Promise => { + public static isAddressUsed = (address: string, walletId: string): boolean => { const addressEntity = AddressDao.findByAddress(address, walletId) return !!addressEntity } @@ -190,7 +190,7 @@ export default class AddressService { return [testnetAddressInfo, mainnetAddressInfo] } - public static nextUnusedAddress = async (walletId: string): Promise => { + public static nextUnusedAddress = (walletId: string): AddressInterface | undefined => { const version = AddressService.getAddressVersion() const addressEntity = AddressDao.nextUnusedAddress(walletId, version) @@ -200,7 +200,7 @@ export default class AddressService { return addressEntity } - public static nextUnusedChangeAddress = async (walletId: string): Promise => { + public static nextUnusedChangeAddress = (walletId: string): AddressInterface | undefined => { const version = AddressService.getAddressVersion() const addressEntity = AddressDao.nextUnusedChangeAddress(walletId, version) @@ -210,7 +210,7 @@ export default class AddressService { return addressEntity } - public static allAddresses = async (): Promise => { + public static allAddresses = (): AddressInterface[] => { const version = AddressService.getAddressVersion() return AddressDao.allAddresses(version) @@ -221,20 +221,20 @@ export default class AddressService { return AddressDao.allAddressesByWalletId(walletId, version) } - public static usedAddresses = async (walletId: string): Promise => { + public static usedAddresses = (walletId: string): AddressInterface[] => { const version = AddressService.getAddressVersion() return AddressDao.usedAddressesByWalletId(walletId, version) } - public static updateDescription = async (walletId: string, address: string, description: string) => { + public static updateDescription = (walletId: string, address: string, description: string): AddressInterface | undefined => { return AddressDao.updateDescription(walletId, address, description) } - public static deleteByWalletId = async (walletId: string) => { + public static deleteByWalletId = (walletId: string): AddressInterface[] => { return AddressDao.deleteByWalletId(walletId) } - public static findByAddresses = async (addresses: string[]) => { + public static findByAddresses = (addresses: string[]): AddressInterface[] => { return AddressDao.findByAddresses(addresses) } diff --git a/packages/neuron-wallet/src/services/wallets.ts b/packages/neuron-wallet/src/services/wallets.ts index 056c00beca..653b84f250 100644 --- a/packages/neuron-wallet/src/services/wallets.ts +++ b/packages/neuron-wallet/src/services/wallets.ts @@ -187,8 +187,7 @@ export default class WalletService { receivingAddressCount: number = 20, changeAddressCount: number = 10 ) => { - const wallet: Wallet = this.get(id) - const accountExtendedPublicKey: AccountExtendedPublicKey = wallet.accountExtendedPublicKey() + const accountExtendedPublicKey: AccountExtendedPublicKey = this.get(id).accountExtendedPublicKey() AddressService.checkAndGenerateSave( id, accountExtendedPublicKey, @@ -198,18 +197,6 @@ export default class WalletService { ) } - public generateCurrentWalletAddresses = async ( - isImporting: boolean, - receivingAddressCount: number = 20, - changeAddressCount: number = 10 - ) => { - const wallet: Wallet | undefined = this.getCurrent() - if (!wallet) { - return undefined - } - return this.generateAddressesById(wallet.id, isImporting, receivingAddressCount, changeAddressCount) - } - public create = (props: WalletProperties) => { if (!props) { throw new IsRequired('wallet property') @@ -277,7 +264,7 @@ export default class WalletService { this.listStore.writeSync(this.walletsKey, newWallets) wallet.deleteKeystore() - const addressInterfaces = await AddressService.deleteByWalletId(id) + const addressInterfaces = AddressService.deleteByWalletId(id) this.deindexAddresses(addressInterfaces.map(addr => addr.address)) } @@ -288,7 +275,7 @@ export default class WalletService { if (addressesWithEnvPrefix.length === 0) { return } - const addrs: string[] = (await AddressService.findByAddresses(addressesWithEnvPrefix)).map(addr => addr.address) + const addrs: string[] = AddressService.findByAddresses(addressesWithEnvPrefix).map(addr => addr.address) const deindexAddresses: string[] = addresses.filter(item => addrs.indexOf(item) < 0); // only deindex if no same wallet if (deindexAddresses.length !== 0) { @@ -472,7 +459,7 @@ export default class WalletService { throw new WalletNotFound(walletID) } - const addressInfos = await this.getAddressInfos(walletID) + const addressInfos = this.getAddressInfos(walletID) const addresses: string[] = addressInfos.map(info => info.address) @@ -483,7 +470,7 @@ export default class WalletService { capacity: BigInt(item.capacity).toString(), })) - const changeAddress: string = await this.getChangeAddress() + const changeAddress: string = this.getChangeAddress() const tx: TransactionWithoutHash = await TransactionGenerator.generateTx( lockHashes, @@ -502,20 +489,20 @@ export default class WalletService { fee: string = '0', feeRate: string = '0', ): Promise => { - const wallet = await this.get(walletID) + const wallet = this.get(walletID) if (!wallet) { throw new WalletNotFound(walletID) } - const addressInfos = await this.getAddressInfos(walletID) + const addressInfos = this.getAddressInfos(walletID) const addresses: string[] = addressInfos.map(info => info.address) const lockHashes: string[] = new LockUtils(await LockUtils.systemScript()).addressesToAllLockHashes(addresses) - const address = await AddressesService.nextUnusedAddress(walletID) + const address = AddressesService.nextUnusedAddress(walletID) - const changeAddress: string = await this.getChangeAddress() + const changeAddress: string = this.getChangeAddress() const tx = await TransactionGenerator.generateDepositTx( lockHashes, @@ -798,7 +785,7 @@ export default class WalletService { } // path is a BIP44 full path such as "m/44'/309'/0'/0/0" - public getAddressInfos = async (walletID: string): Promise => { + public getAddressInfos = (walletID: string): AddressInterface[] => { const wallet = this.get(walletID) if (!wallet) { throw new WalletNotFound(walletID) @@ -806,10 +793,9 @@ export default class WalletService { return AddressService.allAddressesByWalletId(walletID) } - public getChangeAddress = async (): Promise => { + public getChangeAddress = (): string => { const walletId = this.getCurrent()!.id - const addr = await AddressService.nextUnusedChangeAddress(walletId) - return addr!.address + return AddressService.nextUnusedChangeAddress(walletId)!.address } public signWitness = ( diff --git a/packages/neuron-wallet/src/startup/sync-block-task/create.ts b/packages/neuron-wallet/src/startup/sync-block-task/create.ts index a3220e1a12..1c856cbe84 100644 --- a/packages/neuron-wallet/src/startup/sync-block-task/create.ts +++ b/packages/neuron-wallet/src/startup/sync-block-task/create.ts @@ -12,7 +12,7 @@ import DataUpdateSubject from 'models/subjects/data-update' export { genesisBlockHash } const updateAllAddressesTxCount = async (url: string) => { - const addresses = (await AddressService.allAddresses()).map(addr => addr.address) + const addresses = AddressService.allAddresses().map(addr => addr.address) await AddressService.updateTxCountAndBalances(addresses, url) } diff --git a/packages/neuron-wallet/src/startup/sync-block-task/indexer.ts b/packages/neuron-wallet/src/startup/sync-block-task/indexer.ts index 3300e261ab..87f4b91b62 100644 --- a/packages/neuron-wallet/src/startup/sync-block-task/indexer.ts +++ b/packages/neuron-wallet/src/startup/sync-block-task/indexer.ts @@ -12,7 +12,7 @@ const { nodeService, addressCreatedSubject, walletCreatedSubject } = remote.requ // maybe should call this every time when new address generated // load all addresses and convert to lockHashes export const loadAddressesAndConvert = async (nodeURL: string): Promise => { - const addresses: string[] = (await AddressService.allAddresses()).map(addr => addr.address) + const addresses: string[] = AddressService.allAddresses().map(addr => addr.address) const lockUtils = new LockUtils(await LockUtils.loadSystemScript(nodeURL)) return lockUtils.addressesToAllLockHashes(addresses) } diff --git a/packages/neuron-wallet/src/startup/sync-block-task/sync.ts b/packages/neuron-wallet/src/startup/sync-block-task/sync.ts index 3c35053760..fdac5e0682 100644 --- a/packages/neuron-wallet/src/startup/sync-block-task/sync.ts +++ b/packages/neuron-wallet/src/startup/sync-block-task/sync.ts @@ -21,7 +21,7 @@ export interface LockHashInfo { // load all addresses and convert to lockHashes export const loadAddressesAndConvert = async (nodeURL: string): Promise => { const lockUtils = new LockUtils(await LockUtils.systemScript(nodeURL)) - const addresses = (await AddressService.allAddresses()).map(addr => addr.address) + const addresses = AddressService.allAddresses().map(addr => addr.address) return lockUtils.addressesToAllLockHashes(addresses) } diff --git a/packages/neuron-wallet/tests/services/address.test.ts b/packages/neuron-wallet/tests/services/address.test.ts index 1746b4d7f1..665fbc1da2 100644 --- a/packages/neuron-wallet/tests/services/address.test.ts +++ b/packages/neuron-wallet/tests/services/address.test.ts @@ -90,16 +90,16 @@ describe('Key tests with db', () => { AddressDao.deleteAll() }) - const generate = async (id: string = walletId) => { - await AddressService.generateAndSave(id, extendedKey, undefined, 0, 0, 2, 1) + const generate = (id: string = walletId) => { + AddressService.generateAndSave(id, extendedKey, undefined, 0, 0, 2, 1) } - const checkAndGenerate = async (id: string = walletId) => { - await AddressService.checkAndGenerateSave(id, extendedKey, undefined, 2, 1) + const checkAndGenerate = (id: string = walletId) => { + AddressService.checkAndGenerateSave(id, extendedKey, undefined, 2, 1) } it('generateAndSave', async () => { - await generate() + generate() const all = AddressDao.getAll() @@ -130,54 +130,54 @@ describe('Key tests with db', () => { expect(final.length).toEqual((2 + 1) * 2 * 2) }) - it('generateAndSave with two wallet', async () => { - await generate() - await generate('2') + it('generateAndSave with two wallet', () => { + generate() + generate('2') const all = AddressDao.getAll() expect(all.length).toEqual((2 + 1) * 2 * 2) }) - it('isAddressUsed', async () => { + it('isAddressUsed', () => { AddressDao.create([address, usedAddress]) - const used = await AddressService.isAddressUsed(address.address, walletId) + const used = AddressService.isAddressUsed(address.address, walletId) expect(used).toBe(true) }) - it('nextUnusedAddress', async () => { + it('nextUnusedAddress', () => { AddressDao.create([address, usedAddress, changeAddress]) - const addr = await AddressService.nextUnusedAddress(walletId) + const addr = AddressService.nextUnusedAddress(walletId) const addrDao = AddressDao.nextUnusedAddress(walletId, AddressVersion.Testnet) expect(addr).toEqual(addrDao) }) - it('nextUnusedChangeAddress', async () => { + it('nextUnusedChangeAddress', () => { AddressDao.create([address, usedAddress, changeAddress]) - const addr = await AddressService.nextUnusedChangeAddress(walletId) + const addr = AddressService.nextUnusedChangeAddress(walletId) const addrDao = AddressDao.nextUnusedChangeAddress(walletId, AddressVersion.Testnet) expect(addr).toEqual(addrDao) }) - it('allAddresses', async () => { - await generate() - await generate('2') - const all = await AddressService.allAddresses() + it('allAddresses', () => { + generate() + generate('2') + const all = AddressService.allAddresses() expect(all.length).toEqual(6) }) - it('allAddressesByWalletId', async () => { - await generate() - await generate('2') - const all = await AddressService.allAddressesByWalletId(walletId) + it('allAddressesByWalletId', () => { + generate() + generate('2') + const all = AddressService.allAddressesByWalletId(walletId) expect(all.length).toEqual(3) }) - it('usedAddress', async () => { + it('usedAddress', () => { AddressDao.create([address, usedAddress]) - const addr = await AddressService.usedAddresses(walletId) + const addr = AddressService.usedAddresses(walletId) expect(addr).toEqual([]) - const addr2 = await AddressService.usedAddresses('2') + const addr2 = AddressService.usedAddresses('2') expect(addr2).not.toEqual([]) }) }) From af9bf3c77f27d4dd7f14b72933d5fe46c272ebc5 Mon Sep 17 00:00:00 2001 From: James Chen Date: Thu, 14 Nov 2019 10:52:35 +0800 Subject: [PATCH 06/12] refactor: Remove more await call --- packages/neuron-wallet/src/controllers/wallets.ts | 2 +- packages/neuron-wallet/src/services/wallets.ts | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/neuron-wallet/src/controllers/wallets.ts b/packages/neuron-wallet/src/controllers/wallets.ts index bf895fc921..0491f7952d 100644 --- a/packages/neuron-wallet/src/controllers/wallets.ts +++ b/packages/neuron-wallet/src/controllers/wallets.ts @@ -134,7 +134,7 @@ export default class WalletsController { keystore, }) - await walletsService.generateAddressesById(wallet.id, isImporting) + walletsService.generateAddressesById(wallet.id, isImporting) return { status: ResponseCode.Success, diff --git a/packages/neuron-wallet/src/services/wallets.ts b/packages/neuron-wallet/src/services/wallets.ts index 653b84f250..9bfea2d62a 100644 --- a/packages/neuron-wallet/src/services/wallets.ts +++ b/packages/neuron-wallet/src/services/wallets.ts @@ -357,7 +357,7 @@ export default class WalletService { const txHash = core.utils.rawTransactionToHash(ConvertTo.toSdkTxWithoutHash(tx)) - const addressInfos = await this.getAddressInfos(walletID) + const addressInfos = this.getAddressInfos(walletID) const paths = addressInfos.map(info => info.path) const pathAndPrivateKeys = this.getPrivateKeys(wallet, paths, password) const findPrivateKey = (blake160: string) => { @@ -454,7 +454,7 @@ export default class WalletService { fee: string = '0', feeRate: string = '0', ): Promise => { - const wallet = await this.get(walletID) + const wallet = this.get(walletID) if (!wallet) { throw new WalletNotFound(walletID) } @@ -522,7 +522,7 @@ export default class WalletService { fee: string = '0', feeRate: string = '0' ): Promise => { - const wallet = await this.get(walletID) + const wallet = this.get(walletID) if (!wallet) { throw new WalletNotFound(walletID) } @@ -538,7 +538,7 @@ export default class WalletService { throw new TransactionIsNotCommittedYet() } - const addressInfos = await this.getAddressInfos(walletID) + const addressInfos = this.getAddressInfos(walletID) const addresses: string[] = addressInfos.map(info => info.address) @@ -767,12 +767,12 @@ export default class WalletService { } public computeCycles = async (walletID: string = '', capacities: string): Promise => { - const wallet = await this.get(walletID) + const wallet = this.get(walletID) if (!wallet) { throw new WalletNotFound(walletID) } - const addressInfos = await this.getAddressInfos(walletID) + const addressInfos = this.getAddressInfos(walletID) const addresses: string[] = addressInfos.map(info => info.address) From e03ec8087bf1b2ff8c9585caca361075c9558866 Mon Sep 17 00:00:00 2001 From: James Chen Date: Thu, 14 Nov 2019 11:14:27 +0800 Subject: [PATCH 07/12] test: Remove async/await when testing address dao --- packages/neuron-wallet/tests/database/address/balance.test.ts | 2 +- packages/neuron-wallet/tests/database/address/dao.test.ts | 2 +- packages/neuron-wallet/tests/services/address.test.ts | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/neuron-wallet/tests/database/address/balance.test.ts b/packages/neuron-wallet/tests/database/address/balance.test.ts index c45ef8fd66..15811932de 100644 --- a/packages/neuron-wallet/tests/database/address/balance.test.ts +++ b/packages/neuron-wallet/tests/database/address/balance.test.ts @@ -2,7 +2,7 @@ import { AddressType } from '../../../src/models/keys/address' import AddressDao, { Address, AddressVersion } from '../../../src/database/address/address-dao' describe('balance', () => { - beforeEach(async () => { + beforeEach(() => { AddressDao.deleteAll() }) diff --git a/packages/neuron-wallet/tests/database/address/dao.test.ts b/packages/neuron-wallet/tests/database/address/dao.test.ts index ae9b459c2a..f24416621e 100644 --- a/packages/neuron-wallet/tests/database/address/dao.test.ts +++ b/packages/neuron-wallet/tests/database/address/dao.test.ts @@ -47,7 +47,7 @@ describe('Address Dao tests', () => { version: AddressVersion.Testnet, } - beforeEach(async () => { + beforeEach(() => { AddressDao.deleteAll() }) diff --git a/packages/neuron-wallet/tests/services/address.test.ts b/packages/neuron-wallet/tests/services/address.test.ts index 665fbc1da2..f28e4cb4c9 100644 --- a/packages/neuron-wallet/tests/services/address.test.ts +++ b/packages/neuron-wallet/tests/services/address.test.ts @@ -86,7 +86,7 @@ describe('Key tests with db', () => { version: AddressVersion.Testnet, } - beforeEach(async () => { + beforeEach(() => { AddressDao.deleteAll() }) @@ -107,7 +107,7 @@ describe('Key tests with db', () => { }) it('checkAndGenerateSave', async () => { - await generate() + generate() const all = AddressDao.getAll() From f3b6b27f94114e622b497f53b010bd6b2f248534 Mon Sep 17 00:00:00 2001 From: James Chen Date: Thu, 14 Nov 2019 11:40:46 +0800 Subject: [PATCH 08/12] test: Do not run address tests as async --- .../tests/database/address/dao.test.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/neuron-wallet/tests/database/address/dao.test.ts b/packages/neuron-wallet/tests/database/address/dao.test.ts index f24416621e..5044459f74 100644 --- a/packages/neuron-wallet/tests/database/address/dao.test.ts +++ b/packages/neuron-wallet/tests/database/address/dao.test.ts @@ -51,7 +51,7 @@ describe('Address Dao tests', () => { AddressDao.deleteAll() }) - it('create', async () => { + it('create', () => { AddressDao.create([address]) const all = AddressDao.getAll() @@ -74,7 +74,7 @@ describe('Address Dao tests', () => { // expect(dao.txCount).toEqual(getCountByAddress) // }) - it('nextUnusedAddress', async () => { + it('nextUnusedAddress', () => { AddressDao.create([address, usedAddress]) const addr = AddressDao.nextUnusedAddress('1', AddressVersion.Testnet) @@ -87,7 +87,7 @@ describe('Address Dao tests', () => { expect(mainnetAddr).toBe(undefined) }) - it('nextUnusedChangeAddress', async () => { + it('nextUnusedChangeAddress', () => { AddressDao.create([address, usedAddress, changeAddress]) const addr = AddressDao.nextUnusedChangeAddress('1', AddressVersion.Testnet) @@ -100,7 +100,7 @@ describe('Address Dao tests', () => { expect(mainnetAddr).toBe(undefined) }) - it('allAddresses', async () => { + it('allAddresses', () => { AddressDao.create([address, usedAddress]) const all = AddressDao.allAddresses(AddressVersion.Testnet) @@ -111,14 +111,14 @@ describe('Address Dao tests', () => { expect(allMainnet.length).toEqual(0) }) - it('allAddressesByWalletId', async () => { + it('allAddressesByWalletId', () => { AddressDao.create([address, usedAddress]) const all = AddressDao.allAddressesByWalletId('1', AddressVersion.Testnet) expect(all.length).toEqual(1) }) - it('usedAddressByWalletId', async () => { + it('usedAddressByWalletId', () => { AddressDao.create([address, usedAddress]) const walletOne = AddressDao.usedAddressesByWalletId('1', AddressVersion.Testnet) @@ -128,7 +128,7 @@ describe('Address Dao tests', () => { expect(walletTwo.length).toEqual(1) }) - it('findByAddress', async () => { + it('findByAddress', () => { AddressDao.create([address, usedAddress]) const one = AddressDao.findByAddress(address.address, address.walletId) From 60571388a3225bd16c6c8402bc6c2018d74069a8 Mon Sep 17 00:00:00 2001 From: James Chen Date: Thu, 14 Nov 2019 12:00:47 +0800 Subject: [PATCH 09/12] test: Do not run address tests as async --- packages/neuron-wallet/tests/services/address.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/neuron-wallet/tests/services/address.test.ts b/packages/neuron-wallet/tests/services/address.test.ts index f28e4cb4c9..a06ff9be13 100644 --- a/packages/neuron-wallet/tests/services/address.test.ts +++ b/packages/neuron-wallet/tests/services/address.test.ts @@ -98,7 +98,7 @@ describe('Key tests with db', () => { AddressService.checkAndGenerateSave(id, extendedKey, undefined, 2, 1) } - it('generateAndSave', async () => { + it('generateAndSave', () => { generate() const all = AddressDao.getAll() @@ -106,7 +106,7 @@ describe('Key tests with db', () => { expect(all.length).toEqual((2 + 1) * 2) }) - it('checkAndGenerateSave', async () => { + it('checkAndGenerateSave', () => { generate() const all = AddressDao.getAll() @@ -123,7 +123,7 @@ describe('Key tests with db', () => { }) AddressDao.updateAll(usedAll) - await checkAndGenerate() + checkAndGenerate() const final = AddressDao.getAll() From 50fb9b4889bc7e1e18698a83067baec6d7fcb9e7 Mon Sep 17 00:00:00 2001 From: James Chen Date: Thu, 14 Nov 2019 12:38:28 +0800 Subject: [PATCH 10/12] chore: Test mode should not log all kinds of typeorm levels --- packages/neuron-wallet/src/database/chain/ormconfig.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/neuron-wallet/src/database/chain/ormconfig.ts b/packages/neuron-wallet/src/database/chain/ormconfig.ts index 030e4eed5e..c5730b278f 100644 --- a/packages/neuron-wallet/src/database/chain/ormconfig.ts +++ b/packages/neuron-wallet/src/database/chain/ormconfig.ts @@ -32,7 +32,7 @@ const connectOptions = async (genesisBlockHash: string): Promise Date: Thu, 14 Nov 2019 12:58:52 +0800 Subject: [PATCH 11/12] test: Delete mockDeleteAddressByWalletId --- packages/neuron-wallet/tests/services/wallets.test.ts | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/packages/neuron-wallet/tests/services/wallets.test.ts b/packages/neuron-wallet/tests/services/wallets.test.ts index 81c01a53a5..0478b44101 100644 --- a/packages/neuron-wallet/tests/services/wallets.test.ts +++ b/packages/neuron-wallet/tests/services/wallets.test.ts @@ -3,13 +3,6 @@ import Keystore from '../../src/models/keys/keystore' import Keychain from '../../src/models/keys/keychain' import { mnemonicToSeedSync } from '../../src/models/keys/mnemonic' import { ExtendedPrivateKey, AccountExtendedPublicKey } from '../../src/models/keys/key' -import AddressService from '../../src/services/addresses' - -const mockDeleteAddressByWalletId = () => { - const mockDeleteAddress = jest.fn() - mockDeleteAddress.mockReturnValue(undefined) - AddressService.deleteByWalletId = mockDeleteAddress.bind(AddressService) -} describe('wallet service', () => { let walletService: WalletService @@ -121,7 +114,6 @@ describe('wallet service', () => { }) it('delete wallet', () => { - mockDeleteAddressByWalletId() const w1 = walletService.create(wallet1) walletService.create(wallet2) expect(walletService.getAll().length).toBe(2) @@ -154,7 +146,6 @@ describe('wallet service', () => { }) it('delete current wallet', () => { - mockDeleteAddressByWalletId() const w1 = walletService.create(wallet1) const w2 = walletService.create(wallet2) walletService.delete(w1.id) @@ -164,7 +155,6 @@ describe('wallet service', () => { }) it('delete none current wallet', () => { - mockDeleteAddressByWalletId() const w1 = walletService.create(wallet1) const w2 = walletService.create(wallet2) walletService.delete(w2.id) From 13e6ebe46e4a66ed1ab824690301bc4f852e0dbc Mon Sep 17 00:00:00 2001 From: James Chen Date: Thu, 14 Nov 2019 13:26:12 +0800 Subject: [PATCH 12/12] chore(ci): Run wallet CI with runInBand option --- packages/neuron-wallet/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/neuron-wallet/package.json b/packages/neuron-wallet/package.json index 1530c36f10..f490580768 100644 --- a/packages/neuron-wallet/package.json +++ b/packages/neuron-wallet/package.json @@ -21,7 +21,7 @@ "start:dev": "yarn run build && electron .", "build": "ttsc && ncp ./src/startup/sync-block-task/index.html ./dist/startup/sync-block-task/index.html", "clean": "rimraf dist/*", - "test": "jest --color", + "test": "jest --color --runInBand", "test:e2e": "jest --config jest.e2e.config.js --color", "lint": "eslint --fix --ext .ts,.js src", "precommit": "lint-staged",