Skip to content

Commit be5a014

Browse files
committed
fix: not sync after switch network
1 parent 9de23cc commit be5a014

18 files changed

Lines changed: 253 additions & 95 deletions

File tree

packages/neuron-wallet/src/database/address/dao.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { TransactionStatus } from 'types/cell-types'
77
import { OutputStatus } from 'services/tx/params'
88
import AddressEntity, { AddressVersion } from './entities/address'
99
import { getConnection } from './ormconfig'
10+
import NodeService from 'services/node'
1011

1112
export interface Address {
1213
walletId: string
@@ -54,7 +55,10 @@ export default class AddressDao {
5455
// so the final balance is (liveBalance + sentBalance - pendingBalance)
5556
// balance is the balance of the cells those who don't hold data or type script
5657
// totalBalance means balance of all cells, including those who hold data and type script
57-
public static updateTxCountAndBalance = async (address: string): Promise<AddressEntity[]> => {
58+
public static updateTxCountAndBalance = async (
59+
address: string,
60+
url: string = NodeService.getInstance().core.rpc.node.url
61+
): Promise<AddressEntity[]> => {
5862
const addressEntities = await getConnection()
5963
.getRepository(AddressEntity)
6064
.find({
@@ -64,12 +68,12 @@ export default class AddressDao {
6468
const txCount: number = await TransactionsService.getCountByAddressAndStatus(address, [
6569
TransactionStatus.Pending,
6670
TransactionStatus.Success,
67-
])
71+
], url)
6872
const entities = await Promise.all(
6973
addressEntities.map(async entity => {
7074
const addressEntity = entity
7175
addressEntity.txCount = txCount
72-
const lockHashes: string[] = await LockUtils.addressToAllLockHashes(addressEntity.address)
76+
const lockHashes: string[] = await LockUtils.addressToAllLockHashes(addressEntity.address, url)
7377
addressEntity.liveBalance = await CellsService.getBalance(lockHashes, OutputStatus.Live, true)
7478
addressEntity.sentBalance = await CellsService.getBalance(lockHashes, OutputStatus.Sent, true)
7579
addressEntity.pendingBalance = await CellsService.getBalance(lockHashes, OutputStatus.Pending, true)

packages/neuron-wallet/src/listeners/address.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { remote } from 'electron'
22
import { ReplaySubject } from 'rxjs'
33
import { bufferTime } from 'rxjs/operators'
4-
import AddressesUsedSubject from 'models/subjects/addresses-used-subject'
4+
import AddressesUsedSubject, { AddressesWithURL } from 'models/subjects/addresses-used-subject'
55
import AddressService from 'services/addresses'
66
import WalletService from 'services/wallets'
77
import { AccountExtendedPublicKey } from 'models/keys/key'
@@ -12,17 +12,21 @@ const addressesUsedSubject = isRenderer
1212
: AddressesUsedSubject.getSubject()
1313

1414
// pipe not working directly
15-
const bridge = new ReplaySubject<string[]>(1000)
16-
addressesUsedSubject.subscribe((addresses: string[]) => {
17-
bridge.next(addresses)
15+
const bridge = new ReplaySubject<AddressesWithURL>(1000)
16+
addressesUsedSubject.subscribe((params: AddressesWithURL) => {
17+
bridge.next(params)
1818
})
1919

2020
// update txCount when addresses used
2121
export const register = () => {
22-
bridge.pipe(bufferTime(1000)).subscribe(async (addressesList: string[][]) => {
23-
const addresses = addressesList.reduce((acc, val) => acc.concat(val), [])
22+
bridge.pipe(bufferTime(1000)).subscribe(async (addressesList: AddressesWithURL[]) => {
23+
if (addressesList.length === 0) {
24+
return
25+
}
26+
const addresses = addressesList.map(list => list.addresses).reduce((acc, val) => acc.concat(val), [])
27+
const url: string = addressesList[addressesList.length - 1].url
2428
const uniqueAddresses = [...new Set(addresses)]
25-
const addrs = await AddressService.updateTxCountAndBalances(uniqueAddresses)
29+
const addrs = await AddressService.updateTxCountAndBalances(uniqueAddresses, url)
2630
const walletIds: string[] = addrs.map(addr => addr.walletId).filter((value, idx, a) => a.indexOf(value) === idx)
2731
await Promise.all(
2832
walletIds.map(async id => {

packages/neuron-wallet/src/listeners/tx-status.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,11 @@ const trackingStatus = async () => {
6161
if (failedTxs.length) {
6262
const blake160s = await FailedTransaction.updateFailedTxs(failedTxs.map(tx => tx.hash))
6363
const usedAddresses = blake160s.map(blake160 => LockUtils.blake160ToAddress(blake160))
64-
AddressesUsedSubject.getSubject().next(usedAddresses)
64+
const { core } = nodeService
65+
AddressesUsedSubject.getSubject().next({
66+
addresses: usedAddresses,
67+
url: core.rpc.node.url,
68+
})
6569
}
6670

6771
if (successTxs.length > 0) {

packages/neuron-wallet/src/models/lock-utils.ts

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
1-
import { scriptToHash } from '@nervosnetwork/ckb-sdk-utils'
1+
import {
2+
scriptToHash,
3+
AddressPrefix,
4+
bech32Address,
5+
AddressType,
6+
parseAddress
7+
} from '@nervosnetwork/ckb-sdk-utils'
28
import NodeService from 'services/node'
39
import { OutPoint, Script, ScriptHashType } from 'types/cell-types'
410
import env from 'env'
511
import ConvertTo from 'types/convert-to'
612
import { SystemScriptSubject } from 'models/subjects/system-script'
7-
8-
const { core } = NodeService.getInstance()
13+
import Core from '@nervosnetwork/ckb-sdk-core'
914

1015
export interface SystemScript {
1116
codeHash: string
@@ -28,11 +33,15 @@ export default class LockUtils {
2833
@subscribed
2934
static systemScriptInfo: SystemScript | undefined
3035

31-
static async systemScript(): Promise<SystemScript> {
32-
if (this.systemScriptInfo) {
36+
static previousURL: string | undefined
37+
38+
static async systemScript(nodeURL: string = NodeService.getInstance().core.rpc.node.url): Promise<SystemScript> {
39+
if (this.systemScriptInfo && nodeURL === LockUtils.previousURL) {
3340
return this.systemScriptInfo
3441
}
3542

43+
const core = new Core(nodeURL)
44+
3645
const systemCell = await core.loadSecp256k1Dep()
3746
let { codeHash } = systemCell
3847
const { outPoint, hashType } = systemCell
@@ -57,6 +66,7 @@ export default class LockUtils {
5766
}
5867

5968
this.systemScriptInfo = systemScriptInfo
69+
LockUtils.previousURL = nodeURL
6070

6171
return systemScriptInfo
6272
}
@@ -80,8 +90,12 @@ export default class LockUtils {
8090
return LockUtils.computeScriptHash(lock)
8191
}
8292

83-
static async addressToLockScript(address: string, hashType: ScriptHashType = ScriptHashType.Type): Promise<Script> {
84-
const systemScript = await this.systemScript()
93+
static async addressToLockScript(
94+
address: string,
95+
hashType: ScriptHashType = ScriptHashType.Type,
96+
nodeURL: string = NodeService.getInstance().core.rpc.node.url
97+
): Promise<Script> {
98+
const systemScript = await this.systemScript(nodeURL)
8599

86100
const lock: Script = {
87101
codeHash: systemScript.codeHash,
@@ -91,22 +105,32 @@ export default class LockUtils {
91105
return lock
92106
}
93107

94-
static async addressToLockHash(address: string, hashType: ScriptHashType = ScriptHashType.Type): Promise<string> {
95-
const lock: Script = await this.addressToLockScript(address, hashType)
108+
static async addressToLockHash(
109+
address: string,
110+
hashType: ScriptHashType = ScriptHashType.Type,
111+
nodeURL: string = NodeService.getInstance().core.rpc.node.url
112+
): Promise<string> {
113+
const lock: Script = await this.addressToLockScript(address, hashType, nodeURL)
96114
const lockHash: string = this.lockScriptToHash(lock)
97115

98116
return lockHash
99117
}
100118

101-
static async addressToAllLockHashes(address: string): Promise<string[]> {
102-
const dataLockHash = await LockUtils.addressToLockHash(address)
119+
static async addressToAllLockHashes(
120+
address: string,
121+
nodeURL: string = NodeService.getInstance().core.rpc.node.url
122+
): Promise<string[]> {
123+
const dataLockHash = await LockUtils.addressToLockHash(address, ScriptHashType.Type, nodeURL)
103124
return [dataLockHash]
104125
}
105126

106-
static async addressesToAllLockHashes(addresses: string[]): Promise<string[]> {
127+
static async addressesToAllLockHashes(
128+
addresses: string[],
129+
nodeURL: string = NodeService.getInstance().core.rpc.node.url
130+
): Promise<string[]> {
107131
const lockHashes: string[] = (await Promise.all(
108132
addresses.map(async addr => {
109-
return LockUtils.addressToAllLockHashes(addr)
133+
return LockUtils.addressToAllLockHashes(addr, nodeURL)
110134
})
111135
)).reduce((acc, val) => acc.concat(val), [])
112136
return lockHashes
@@ -118,16 +142,16 @@ export default class LockUtils {
118142
}
119143

120144
static blake160ToAddress(blake160: string): string {
121-
const prefix = env.testnet ? core.utils.AddressPrefix.Testnet : core.utils.AddressPrefix.Mainnet
122-
return core.utils.bech32Address(blake160, {
145+
const prefix = env.testnet ? AddressPrefix.Testnet : AddressPrefix.Mainnet
146+
return bech32Address(blake160, {
123147
prefix,
124-
type: core.utils.AddressType.HashIdx,
148+
type: AddressType.HashIdx,
125149
codeHashIndex: '0x00',
126150
})
127151
}
128152

129153
static addressToBlake160(address: string): string {
130-
const result: string = core.utils.parseAddress(address, 'hex') as string
154+
const result: string = parseAddress(address, 'hex') as string
131155
const hrp: string = `0100`
132156
let blake160: string = result.slice(hrp.length + 2, result.length)
133157
if (!blake160.startsWith('0x')) {

packages/neuron-wallet/src/models/subjects/addresses-used-subject.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
11
import { ReplaySubject } from 'rxjs'
22

3+
export interface AddressesWithURL {
4+
addresses: string[]
5+
url: string
6+
}
7+
38
// subscribe this Subject to monitor which addresses are used
49
export class AddressesUsedSubject {
5-
static subject = new ReplaySubject<string[]>(100)
10+
static subject = new ReplaySubject<AddressesWithURL>(100)
611

712
static getSubject() {
813
return this.subject
914
}
1015

11-
static setSubject(subject: ReplaySubject<string[]>) {
16+
static setSubject(subject: ReplaySubject<AddressesWithURL>) {
1217
this.subject = subject
1318
}
1419
}

packages/neuron-wallet/src/services/addresses.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import AddressDao, { Address as AddressInterface } from 'database/address/dao'
66
import env from 'env'
77
import AddressEntity, { AddressVersion } from 'database/address/entities/address'
88
import AddressCreatedSubject from 'models/subjects/address-created-subject'
9+
import NodeService from './node'
910

1011
const MAX_ADDRESS_COUNT = 30
1112

@@ -96,10 +97,13 @@ export default class AddressService {
9697

9798
/* eslint no-await-in-loop: "off" */
9899
/* eslint no-restricted-syntax: "off" */
99-
public static updateTxCountAndBalances = async (addresses: string[]) => {
100+
public static updateTxCountAndBalances = async (
101+
addresses: string[],
102+
url: string = NodeService.getInstance().core.rpc.node.url
103+
) => {
100104
let addrs: AddressEntity[] = []
101105
for (const address of addresses) {
102-
const ads = await AddressDao.updateTxCountAndBalance(address)
106+
const ads = await AddressDao.updateTxCountAndBalance(address, url)
103107
addrs = addrs.concat(ads)
104108
}
105109
return addrs

packages/neuron-wallet/src/services/indexer/queue.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,12 @@ export default class IndexerQueue {
4545

4646
private latestCreatedBy: TxUniqueFlagCache = new TxUniqueFlagCache(100)
4747

48+
private url: string
49+
4850
constructor(url: string, lockHashInfos: LockHashInfo[], tipNumberSubject: Subject<string | undefined>) {
4951
// this.lockHashes = lockHashes
5052
this.lockHashInfos = lockHashInfos
53+
this.url = url
5154
this.indexerRPC = new IndexerRPC(url)
5255
this.getBlocksService = new GetBlocks(url)
5356
this.blockNumberService = new BlockNumber()
@@ -190,7 +193,10 @@ export default class IndexerQueue {
190193
}
191194
if (type === TxPointType.CreatedBy && this.latestCreatedBy.includes(txUniqueFlag)) {
192195
const address = LockUtils.lockScriptToAddress(transaction.outputs![parseInt(txPoint.index, 16)].lock)
193-
AddressesUsedSubject.getSubject().next([address])
196+
AddressesUsedSubject.getSubject().next({
197+
addresses: [address],
198+
url: this.url,
199+
})
194200
return
195201
}
196202

@@ -229,7 +235,10 @@ export default class IndexerQueue {
229235
}
230236
}
231237
if (address) {
232-
AddressesUsedSubject.getSubject().next([address])
238+
AddressesUsedSubject.getSubject().next({
239+
addresses: [address],
240+
url: this.url,
241+
})
233242
}
234243
}
235244
}

packages/neuron-wallet/src/services/sync/check-and-save/index.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,19 @@ import CheckTx from './tx'
44
export default class CheckAndSave {
55
private block: Block
66
private lockHashes: string[]
7+
private url: string
78

8-
constructor(block: Block, lockHashes: string[]) {
9+
constructor(block: Block, lockHashes: string[], url: string) {
910
this.block = block
1011
this.lockHashes = lockHashes
12+
this.url = url
1113
}
1214

1315
public process = async (): Promise<boolean[]> => {
1416
const txs = this.block.transactions
1517
let result: boolean[] = []
1618
for (const tx of txs) {
17-
const checkTx = new CheckTx(tx)
19+
const checkTx = new CheckTx(tx, this.url)
1820
const checkResult = await checkTx.checkAndSave(this.lockHashes)
1921
result.push(checkResult)
2022
}

packages/neuron-wallet/src/services/sync/check-and-save/tx.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,22 @@ import { TransactionPersistor } from 'services/tx'
66
import LockUtils from 'models/lock-utils'
77
import CheckOutput from './output'
88
import { addressesUsedSubject as addressesUsedSubjectParam } from '../renderer-params'
9+
import { AddressesWithURL } from 'models/subjects/addresses-used-subject'
910

1011
export default class CheckTx {
1112
private tx: Transaction
12-
private addressesUsedSubject: Subject<string[]>
13+
private addressesUsedSubject: Subject<AddressesWithURL>
14+
private url: string
1315

14-
constructor(tx: Transaction, addressesUsedSubject: Subject<string[]> = addressesUsedSubjectParam) {
16+
constructor(
17+
tx: Transaction,
18+
url: string,
19+
addressesUsedSubject: Subject<AddressesWithURL> = addressesUsedSubjectParam,
20+
) {
1521
this.tx = tx
1622
this.addressesUsedSubject = addressesUsedSubject
23+
24+
this.url = url
1725
}
1826

1927
public check = async (lockHashes: string[]): Promise<string[]> => {
@@ -33,7 +41,10 @@ export default class CheckTx {
3341
const addresses = await this.check(lockHashes)
3442
if (addresses.length > 0) {
3543
await TransactionPersistor.saveFetchTx(this.tx)
36-
this.addressesUsedSubject.next(addresses)
44+
this.addressesUsedSubject.next({
45+
addresses,
46+
url: this.url,
47+
})
3748
return true
3849
}
3950
return false

packages/neuron-wallet/src/services/sync/get-blocks.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,12 @@ export default class GetBlocks {
1414
private retryTime: number
1515
private retryInterval: number
1616
private core: Core
17+
private url: string
1718

1819
constructor(url: string, retryTime: number = 3, retryInterval: number = 100) {
1920
this.retryTime = retryTime
2021
this.retryInterval = retryInterval
22+
this.url = url
2123
this.core = generateCore(url)
2224
}
2325

@@ -39,7 +41,7 @@ export default class GetBlocks {
3941
public checkAndSave = async (blocks: Block[], lockHashes: string[]): Promise<void> => {
4042
for (const block of blocks) {
4143
for (const tx of block.transactions) {
42-
const checkTx = new CheckTx(tx)
44+
const checkTx = new CheckTx(tx, this.url)
4345
const addresses = await checkTx.check(lockHashes)
4446
if (addresses.length > 0) {
4547
for (const input of tx.inputs!) {
@@ -51,7 +53,10 @@ export default class GetBlocks {
5153
input.capacity = previousOutput.capacity
5254
}
5355
await TransactionPersistor.saveFetchTx(tx)
54-
addressesUsedSubject.next(addresses)
56+
addressesUsedSubject.next({
57+
addresses,
58+
url: this.url,
59+
})
5560
}
5661
}
5762
}

0 commit comments

Comments
 (0)