Skip to content

Commit 34d3ce7

Browse files
authored
Merge pull request #12 from ava-labs/balance_update
Automatic balance update
2 parents cdacf5c + 81e7cbe commit 34d3ce7

File tree

3 files changed

+95
-62
lines changed

3 files changed

+95
-62
lines changed

src/AppViewModel.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export default class {
2323
}
2424

2525
onLogout(): void {
26+
this.wallet?.destroy()
2627
this.wallet = null
2728
this.setSelectedView(SelectedView.Onboard)
2829
}

src/mainView/MainView.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ class MainView extends Component<MainViewProps, MainViewState> {
9090
}
9191

9292
componentWillUnmount(): void {
93+
this.viewModel.onComponentUnMount()
9394
}
9495

9596
private onSendX(addressX: string, amount: string): void {

src/mainView/MainViewViewModel.ts

Lines changed: 93 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,32 @@
1-
import {asyncScheduler, BehaviorSubject, Observable, of, zip} from "rxjs"
1+
import {BN} from 'avalanche';
2+
import {asyncScheduler, BehaviorSubject, from, Observable, of, zip} from "rxjs"
23
import {MnemonicWallet, Utils} from "../../wallet_sdk"
34
import WalletSDK from "../WalletSDK"
4-
import {concatMap, filter, map, subscribeOn, take} from "rxjs/operators"
5-
import {AssetBalanceP, AssetBalanceX} from "../../wallet_sdk/Wallet/types"
5+
import {concatMap, delay, filter, map, retryWhen, subscribeOn, take, tap} from "rxjs/operators"
6+
import {AssetBalanceP, iWalletAddressChanged, WalletBalanceX} from "../../wallet_sdk/Wallet/types"
7+
8+
enum WalletEvents {
9+
AddressChanged = "addressChanged",
10+
BalanceChangedX = "balanceChangedX",
11+
BalanceChangedP = "balanceChangedP",
12+
BalanceChangedC = "balanceChangedC",
13+
}
614

715
export default class {
8-
hdIndicesSet: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false)
916
avaxPrice: BehaviorSubject<number> = new BehaviorSubject(0)
10-
wallet!: BehaviorSubject<MnemonicWallet>
11-
walletCAddress!: Observable<string>
12-
walletEvmAddrBech!: Observable<string>
13-
addressX!: Observable<string>
14-
addressP!: Observable<string>
15-
addressC!: Observable<string>
16-
availableC!: Observable<string>
17-
stakingAmount!: Observable<string>
18-
private avaxBalanceX!: Observable<AssetBalanceX>
19-
private avaxBalanceP!: Observable<AssetBalanceP>
20-
availableX!: Observable<string>
21-
availableP!: Observable<string>
17+
wallet: BehaviorSubject<MnemonicWallet>
18+
walletCAddress: Observable<string>
19+
walletEvmAddrBech: Observable<string>
20+
addressX: BehaviorSubject<string> = new BehaviorSubject<string>("")
21+
addressP: BehaviorSubject<string> = new BehaviorSubject<string>("")
22+
addressC: Observable<string>
23+
stakingAmount: Observable<string>
24+
availableX: Observable<string>
25+
availableP: Observable<string>
26+
availableC: Observable<string>
27+
newBalanceX: BehaviorSubject<WalletBalanceX | null> = new BehaviorSubject<WalletBalanceX | null>(null)
28+
newBalanceP: BehaviorSubject<AssetBalanceP | null> = new BehaviorSubject<AssetBalanceP | null>(null)
29+
newBalanceC: BehaviorSubject<BN | null> = new BehaviorSubject<BN | null>(null)
2230

2331
constructor(wallet: MnemonicWallet) {
2432
this.wallet = new BehaviorSubject<MnemonicWallet>(wallet)
@@ -31,26 +39,10 @@ export default class {
3139
map(wallet => wallet.getEvmAddressBech()),
3240
)
3341

34-
this.addressX = this.wallet.pipe(
35-
map(wallet => wallet.getAddressX()),
36-
)
37-
38-
this.addressP = this.wallet.pipe(
39-
map(wallet => wallet.getAddressP()),
40-
)
41-
4242
this.addressC = this.wallet.pipe(
4343
map(wallet => wallet.getAddressC()),
4444
)
4545

46-
this.availableC = this.wallet.pipe(
47-
concatMap(wallet => wallet.evmWallet.updateBalance()),
48-
map(balance => {
49-
const symbol = 'AVAX'
50-
return Utils.bnToAvaxC(balance) + ' ' + symbol
51-
})
52-
)
53-
5446
this.stakingAmount = this.wallet.pipe(
5547
concatMap(wallet => wallet.getStake()),
5648
map(stake => {
@@ -59,62 +51,60 @@ export default class {
5951
})
6052
)
6153

62-
this.avaxBalanceX = this.hdIndicesSet.pipe(
63-
filter(hdIndicesSet => hdIndicesSet === true),
64-
map(
65-
() => this.wallet.value.getAvaxBalanceX(),
66-
),
67-
)
68-
69-
this.avaxBalanceP = this.hdIndicesSet.pipe(
70-
filter(hdIndicesSet => hdIndicesSet === true),
71-
map(
72-
() => this.wallet.value.getAvaxBalanceP(),
73-
),
54+
this.availableX = this.newBalanceX.pipe(
55+
filter(value => value !== null),
56+
map(assetBalance => assetBalance!['U8iRqJoiJm8xZHAacmvYyZVwqQx6uDNtQeP3CQ6fcgQk3JqnK'].unlocked), //fixme should not be hardcoded?
57+
map(balance => {
58+
const symbol = 'AVAX'
59+
return Utils.bnToAvaxX(balance) + ' ' + symbol
60+
})
7461
)
7562

76-
this.availableX = this.avaxBalanceX.pipe(
77-
filter(assetBalance => assetBalance !== undefined),
78-
map(assetBalance => {
79-
return Utils.bnToAvaxX(assetBalance.unlocked) + ' ' + assetBalance.meta.symbol
63+
this.availableP = this.newBalanceP.pipe(
64+
filter(value => value !== null),
65+
map(assetBalance => assetBalance!.unlocked),
66+
map(balance => {
67+
const symbol = 'AVAX'
68+
return Utils.bnToAvaxP(balance) + ' ' + symbol
8069
})
8170
)
8271

83-
this.availableP = this.avaxBalanceP.pipe(
84-
filter(assetBalance => assetBalance !== undefined),
85-
map(assetBalance => {
72+
this.availableC = this.newBalanceC.pipe(
73+
filter(value => value !== null),
74+
map(balance => {
8675
const symbol = 'AVAX'
87-
return Utils.bnToAvaxP(assetBalance.unlocked) + ' ' + symbol
76+
return Utils.bnToAvaxC(<BN>balance) + ' ' + symbol
8877
})
8978
)
9079
}
9180

92-
onComponentMount(): void {
93-
WalletSDK.getAvaxPrice()
94-
.then(value => {
95-
this.avaxPrice.next(value)
96-
})
97-
.catch(reason => console.log(reason))
81+
onComponentMount = (): void => {
82+
this.fetchAvaxPriceWithRetryOnError()
83+
this.addBalanceListeners(this.wallet.value)
84+
this.wallet.value.on(WalletEvents.AddressChanged, this.onAddressChanged)
9885
}
9986

87+
onComponentUnMount = (): void => {
88+
this.removeBalanceListeners(this.wallet.value)
89+
this.wallet.value.off(WalletEvents.AddressChanged, this.onAddressChanged)
90+
}
10091

101-
onResetHdIndices(): Observable<boolean> {
92+
onResetHdIndices = (): Observable<boolean> => {
10293
return this.wallet
10394
.pipe(
10495
take(1),
10596
concatMap(wallet => wallet.resetHdIndices()),
10697
concatMap(() => this.wallet.value.getUtxosX()),
10798
concatMap(() => this.wallet.value.getUtxosP()),
10899
map(() => {
109-
this.hdIndicesSet.next(true)
110100
this.wallet.next(this.wallet.value)
111101
return true
112102
}),
113103
subscribeOn(asyncScheduler),
114104
)
115105
}
116106

117-
onSendAvaxX(addressX: string, amount: string, memo?: string): Observable<string> {
107+
onSendAvaxX = (addressX: string, amount: string, memo?: string): Observable<string> => {
118108
return zip(
119109
this.wallet,
120110
of(amount),
@@ -130,7 +120,7 @@ export default class {
130120
)
131121
}
132122

133-
onSendAvaxC(addressC: string, amount: string): Observable<string> {
123+
onSendAvaxC = (addressC: string, amount: string): Observable<string> => {
134124
return zip(
135125
this.wallet,
136126
of(amount),
@@ -147,4 +137,45 @@ export default class {
147137
subscribeOn(asyncScheduler),
148138
)
149139
}
140+
141+
private onBalanceChangedX = (balance: WalletBalanceX): void => {
142+
this.newBalanceX.next(balance)
143+
}
144+
145+
private onBalanceChangedP = (balance: AssetBalanceP): void => {
146+
this.newBalanceP.next(balance)
147+
}
148+
149+
private onBalanceChangedC = (balance: BN): void => {
150+
this.newBalanceC.next(balance)
151+
}
152+
153+
private onAddressChanged = (params: iWalletAddressChanged): void => {
154+
this.addressX.next(params.X)
155+
this.addressP.next(params.P)
156+
}
157+
158+
private addBalanceListeners = (wallet: MnemonicWallet): void => {
159+
wallet.on(WalletEvents.BalanceChangedX, this.onBalanceChangedX)
160+
wallet.on(WalletEvents.BalanceChangedP, this.onBalanceChangedP)
161+
wallet.on(WalletEvents.BalanceChangedC, this.onBalanceChangedC)
162+
}
163+
164+
private removeBalanceListeners = (wallet: MnemonicWallet): void => {
165+
wallet.off(WalletEvents.BalanceChangedX, this.onBalanceChangedX)
166+
wallet.off(WalletEvents.BalanceChangedP, this.onBalanceChangedP)
167+
wallet.off(WalletEvents.BalanceChangedC, this.onBalanceChangedC)
168+
}
169+
170+
private fetchAvaxPriceWithRetryOnError = (): void => {
171+
from(WalletSDK.getAvaxPrice()).pipe(
172+
retryWhen(errors => errors.pipe(
173+
tap(err => console.warn(err)),
174+
delay(5000)
175+
)
176+
)
177+
).subscribe({
178+
next: value => this.avaxPrice.next(value)
179+
})
180+
}
150181
}

0 commit comments

Comments
 (0)