Skip to content

Commit

Permalink
feat: not start from zero in indexer when create wallet
Browse files Browse the repository at this point in the history
  • Loading branch information
classicalliu committed Aug 20, 2019
1 parent 3a40dcc commit 25ed522
Show file tree
Hide file tree
Showing 9 changed files with 103 additions and 31 deletions.
8 changes: 6 additions & 2 deletions packages/neuron-wallet/src/controllers/wallets/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ export default class WalletsController {
name,
password,
mnemonic,
isImport: true,
})

WalletCreatedSubject.getSubject().next('import')
Expand All @@ -93,6 +94,7 @@ export default class WalletsController {
name,
password,
mnemonic,
isImport: false,
})

WalletCreatedSubject.getSubject().next('create')
Expand All @@ -104,10 +106,12 @@ export default class WalletsController {
name,
password,
mnemonic,
isImport,
}: {
name: string
password: string
mnemonic: string
isImport: boolean
}): Promise<Controller.Response<Omit<WalletProperties, 'extendedKey'>>> {
if (!validateMnemonic(mnemonic)) {
throw new InvalidMnemonic()
Expand Down Expand Up @@ -138,7 +142,7 @@ export default class WalletsController {
keystore,
})

await walletsService.generateAddressesById(wallet.id)
await walletsService.generateAddressesById(wallet.id, isImport)

return {
status: ResponseCode.Success,
Expand Down Expand Up @@ -188,7 +192,7 @@ export default class WalletsController {
keystore: keystoreObject,
})

await walletsService.generateAddressesById(wallet.id)
await walletsService.generateAddressesById(wallet.id, true)
WalletCreatedSubject.getSubject().next('import')

return {
Expand Down
2 changes: 1 addition & 1 deletion packages/neuron-wallet/src/listeners/address.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export const register = () => {
walletIds.map(async id => {
const wallet = WalletService.getInstance().get(id)
const accountExtendedPublicKey: AccountExtendedPublicKey = wallet.accountExtendedPublicKey()
await AddressService.checkAndGenerateSave(id, accountExtendedPublicKey, 20, 10)
await AddressService.checkAndGenerateSave(id, accountExtendedPublicKey, true, 20, 10)
})
)
})
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { ReplaySubject } from 'rxjs'
import { AddressWithWay } from 'services/addresses'

export default class AddressCreatedSubject {
static subject = new ReplaySubject<AddressWithWay[]>(100)

static getSubject() {
return this.subject
}
}
27 changes: 26 additions & 1 deletion packages/neuron-wallet/src/services/addresses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,15 @@ import LockUtils from 'models/lock-utils'
import AddressDao, { Address as AddressInterface } from 'database/address/dao'
import env from 'env'
import AddressEntity, { AddressVersion } from 'database/address/entities/address'
import AddressCreatedSubject from 'models/subjects/address-created-subject'

const MAX_ADDRESS_COUNT = 30

export interface AddressWithWay {
address: AddressInterface
isImport: boolean | undefined
}

export interface AddressMetaInfo {
walletId: string
addressType: AddressType
Expand All @@ -24,6 +30,7 @@ export default class AddressService {
public static generateAndSave = async (
walletId: string,
extendedKey: AccountExtendedPublicKey,
isImport: boolean | undefined,
receivingStartIndex: number,
changeStartIndex: number,
receivingAddressCount: number = 20,
Expand All @@ -37,18 +44,35 @@ export default class AddressService {
receivingAddressCount,
changeAddressCount
)
const allAddresses = [
const allAddresses: AddressInterface[] = [
...addresses.testnetReceiving,
...addresses.mainnetReceiving,
...addresses.testnetChange,
...addresses.mainnetChange,
]
await AddressDao.create(allAddresses)

// TODO: notify address created and pass addressWay
AddressService.notifyAddressCreated(allAddresses, isImport)
}

private static notifyAddressCreated = (addresses: AddressInterface[], isImport: boolean | undefined) => {
const version = AddressService.getAddressVersion()
const addressesWithWay: AddressWithWay[] = addresses
.filter(addr => addr.version === version)
.map(addr => {
return {
address: addr,
isImport,
}
})
AddressCreatedSubject.getSubject().next(addressesWithWay)
}

public static checkAndGenerateSave = async (
walletId: string,
extendedKey: AccountExtendedPublicKey,
isImport: boolean | undefined,
receivingAddressCount: number = 20,
changeAddressCount: number = 10
) => {
Expand All @@ -68,6 +92,7 @@ export default class AddressService {
return AddressService.generateAndSave(
walletId,
extendedKey,
isImport,
nextReceivingIndex,
nextChangeIndex,
receivingAddressCount,
Expand Down
2 changes: 1 addition & 1 deletion packages/neuron-wallet/src/services/indexer/indexer-rpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export default class IndexerRPC {
return this.core.rpc.deindexLockHash(lockHash)
}

public indexLockHash = async (lockHash: string, indexFrom = '0') => {
public indexLockHash = async (lockHash: string, indexFrom?: string | undefined) => {
return this.core.rpc.indexLockHash(lockHash, indexFrom)
}

Expand Down
32 changes: 21 additions & 11 deletions packages/neuron-wallet/src/services/indexer/queue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,19 @@ import IndexerTransaction from 'services/tx/indexer-transaction'

import IndexerRPC from './indexer-rpc'

export interface LockHashInfo {
lockHash: string
isImport: boolean | undefined
}

enum TxPointType {
CreatedBy = 'createdBy',
ConsumedBy = 'consumedBy',
}

export default class IndexerQueue {
private lockHashes: string[]
// private lockHashes: string[]
private lockHashInfos: LockHashInfo[]
private indexerRPC: IndexerRPC
private getBlocksService: GetBlocks
private per = 50
Expand All @@ -34,8 +40,9 @@ export default class IndexerQueue {

private resetFlag = false

constructor(url: string, lockHashes: string[], tipNumberSubject: Subject<string | undefined>) {
this.lockHashes = lockHashes
constructor(url: string, lockHashInfos: LockHashInfo[], tipNumberSubject: Subject<string | undefined>) {
// this.lockHashes = lockHashes
this.lockHashInfos = lockHashInfos
this.indexerRPC = new IndexerRPC(url)
this.getBlocksService = new GetBlocks()
this.blockNumberService = new BlockNumber()
Expand All @@ -46,8 +53,9 @@ export default class IndexerQueue {
})
}

public setLockHashes = (lockHashes: string[]): void => {
this.lockHashes = lockHashes
public setLockHashInfos = (lockHashInfos: LockHashInfo[]): void => {
// this.lockHashes = lockHashes
this.lockHashInfos = lockHashInfos
this.indexed = false
}

Expand All @@ -65,13 +73,14 @@ export default class IndexerQueue {
await this.blockNumberService.updateCurrent(BigInt(0))
this.resetFlag = false
}
const { lockHashes } = this
const { lockHashInfos } = this
const currentBlockNumber: bigint = await this.blockNumberService.getCurrent()
if (!this.indexed || currentBlockNumber !== this.tipBlockNumber) {
if (!this.indexed) {
await this.indexLockHashes(lockHashes)
await this.indexLockHashes(lockHashInfos)
this.indexed = true
}
const lockHashes: string[] = lockHashInfos.map(info => info.lockHash)
const minBlockNumber = await this.getCurrentBlockNumber(lockHashes)
for (const lockHash of lockHashes) {
await this.pipeline(lockHash, TxPointType.CreatedBy, currentBlockNumber)
Expand Down Expand Up @@ -130,13 +139,14 @@ export default class IndexerQueue {
return minBlockNumber
}

public indexLockHashes = async (lockHashes: string[]) => {
public indexLockHashes = async (lockHashInfos: LockHashInfo[]) => {
const lockHashIndexStates = await this.indexerRPC.getLockHashIndexStates()
const indexedLockHashes: string[] = lockHashIndexStates.map(state => state.lockHash)
const nonIndexedLockHashes = lockHashes.filter(i => !indexedLockHashes.includes(i))
const nonIndexedLockHashInfos = lockHashInfos.filter(i => !indexedLockHashes.includes(i.lockHash))

await Utils.mapSeries(nonIndexedLockHashes, async (lockHash: string) => {
await this.indexerRPC.indexLockHash(lockHash)
await Utils.mapSeries(nonIndexedLockHashInfos, async (info: LockHashInfo) => {
const indexFrom: string | undefined = info.isImport ? '0' : undefined
await this.indexerRPC.indexLockHash(info.lockHash, indexFrom)
})
}

Expand Down
12 changes: 10 additions & 2 deletions packages/neuron-wallet/src/services/wallets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,23 +169,31 @@ export default class WalletService {

public generateAddressesById = async (
id: string,
isImport: boolean,
receivingAddressCount: number = 20,
changeAddressCount: number = 10
) => {
const wallet: Wallet = this.get(id)
const accountExtendedPublicKey: AccountExtendedPublicKey = wallet.accountExtendedPublicKey()
await AddressService.checkAndGenerateSave(id, accountExtendedPublicKey, receivingAddressCount, changeAddressCount)
await AddressService.checkAndGenerateSave(
id,
accountExtendedPublicKey,
isImport,
receivingAddressCount,
changeAddressCount
)
}

public generateCurrentWalletAddresses = async (
isImport: boolean,
receivingAddressCount: number = 20,
changeAddressCount: number = 10
) => {
const wallet: Wallet | undefined = this.getCurrent()
if (!wallet) {
return undefined
}
return this.generateAddressesById(wallet.id, receivingAddressCount, changeAddressCount)
return this.generateAddressesById(wallet.id, isImport, receivingAddressCount, changeAddressCount)
}

public create = (props: WalletProperties) => {
Expand Down
39 changes: 26 additions & 13 deletions packages/neuron-wallet/src/startup/sync-block-task/indexer.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import { remote } from 'electron'
import AddressService from 'services/addresses'
import AddressService, { AddressWithWay } from 'services/addresses'
import LockUtils from 'models/lock-utils'
import IndexerQueue from 'services/indexer/queue'
import IndexerQueue, { LockHashInfo } from 'services/indexer/queue'
// import { Address } from 'database/address/dao'

import { initDatabase } from './init-database'

const { nodeService, addressDbChangedSubject, walletCreatedSubject } = remote.require(
'./startup/sync-block-task/params'
)
const { nodeService, addressCreatedSubject, walletCreatedSubject } = remote.require('./startup/sync-block-task/params')

// maybe should call this every time when new address generated
// load all addresses and convert to lockHashes
Expand All @@ -29,16 +28,30 @@ export const switchNetwork = async (nodeURL: string) => {
await initDatabase()
// load lockHashes
const lockHashes: string[] = await loadAddressesAndConvert()
const lockHashInfos: LockHashInfo[] = lockHashes.map(lockHash => {
return {
lockHash,
isImport: true,
}
})
// start sync blocks service
indexerQueue = new IndexerQueue(nodeURL, lockHashes, nodeService.tipNumberSubject)
indexerQueue = new IndexerQueue(nodeURL, lockHashInfos, nodeService.tipNumberSubject)

addressDbChangedSubject.subscribe(async (event: string) => {
// ignore update and remove
if (event === 'AfterInsert') {
const hashes: string[] = await loadAddressesAndConvert()
if (indexerQueue) {
indexerQueue.setLockHashes(hashes)
}
// listen to address created
addressCreatedSubject.subscribe(async (addressWithWay: AddressWithWay[]) => {
if (indexerQueue) {
const infos: LockHashInfo[] = (await Promise.all(
addressWithWay.map(async aw => {
const hashes: string[] = await LockUtils.addressToAllLockHashes(aw.address.address)
return hashes.map(h => {
return {
lockHash: h,
isImport: aw.isImport,
}
})
})
)).reduce((acc, val) => acc.concat(val), [])
indexerQueue.setLockHashInfos(infos)
}
})

Expand Down
2 changes: 2 additions & 0 deletions packages/neuron-wallet/src/startup/sync-block-task/params.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import NodeService from 'services/node'
import { AddressesUsedSubject } from 'models/subjects/addresses-used-subject'
import AddressDbChangedSubject from 'models/subjects/address-db-changed-subject'
import WalletCreatedSubject from 'models/subjects/wallet-created-subject'
import AddressCreatedSubject from 'models/subjects/address-created-subject'

export { networkSwitchSubject } from 'services/networks'

Expand All @@ -12,3 +13,4 @@ export const nodeService = NodeService.getInstance()
export const addressesUsedSubject = AddressesUsedSubject.getSubject()
export const addressDbChangedSubject = AddressDbChangedSubject.getSubject()
export const walletCreatedSubject = WalletCreatedSubject.getSubject()
export const addressCreatedSubject = AddressCreatedSubject.getSubject()

0 comments on commit 25ed522

Please sign in to comment.