Skip to content

Commit

Permalink
Finish up balance subscription and balance refresh logic
Browse files Browse the repository at this point in the history
  • Loading branch information
rileystephens28 committed Oct 25, 2024
1 parent f6b25d0 commit 9bbd67d
Show file tree
Hide file tree
Showing 7 changed files with 119 additions and 157 deletions.
13 changes: 13 additions & 0 deletions background/accounts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,19 @@ export type QiWalletBalance = {
dataSource: "local"
}

export type QiLedgerLastFullScan = {
chainID: string
retrievedAt: number
}

export type QiCoinbaseAddressBalance = {
address: string
balance: bigint
retrievedAt: number
chainID: string
dataSource: "local"
}

/**
* An address on a particular network. That's it. That's the comment.
*/
Expand Down
57 changes: 0 additions & 57 deletions background/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -490,63 +490,6 @@ export default class Main extends BaseService<never> {
await this.store.dispatch(setNewNetworkConnectError(chainIdWithError))
}

async startQiMiningAddressBalanceChecker(): Promise<void> {
const interval = setInterval(async () => {
const qiWalletBalance = await this.updateQiMiningAddressBalance()
if (qiWalletBalance !== null) {
this.store.dispatch(
updateUtxoAccountsBalances({ balances: [qiWalletBalance] })
)
}
}, 60000)
}

/**
* Returns the balance of the mining address or null if there is no balance
*/
async updateQiMiningAddressBalance(): Promise<QiWalletBalance | null> {
const qiMiningAddresses =
await this.indexingService.getQiCoinbaseAddresses()
const allOutpoints = (
await Promise.all(
qiMiningAddresses.map(async (qiAddress) => {
const outpoints = await this.chainService.getOutpointsForQiAddress(
qiAddress.address
)
return outpoints.map((outpoint) => ({
outpoint,
address: qiAddress.address,
account: qiAddress.account,
zone: Zone.Cyprus1,
}))
})
)
).flat()
if (allOutpoints.length === 0) return null
const qiWallet = await this.keyringService.getQiHDWallet()
qiWallet.importOutpoints(allOutpoints)
const serializedQiHDWallet = qiWallet.serialize()
await this.keyringService.vaultManager.add(
{ qiHDWallet: serializedQiHDWallet },
{}
)
const qiWalletBalance: QiWalletBalance = {
paymentCode: qiWallet.getPaymentCode(0),
network: this.chainService.selectedNetwork,
assetAmount: {
asset: QI,
amount: qiWallet.getBalanceForZone(Zone.Cyprus1),
},
dataSource: "local",
retrievedAt: Date.now(),
}
console.log(
"updateQiMiningAddressBalance: after qiWalletBalance",
qiWalletBalance
)
return qiWalletBalance
}

async startBalanceChecker(): Promise<void> {
const interval = setInterval(async () => {
if (!walletOpen) return
Expand Down
11 changes: 1 addition & 10 deletions background/redux-slices/accounts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -608,17 +608,8 @@ export const triggerManualBalanceUpdate = createBackgroundAsyncThunk(
const uiState = state.ui
const isUtxoSelected = uiState.isUtxoSelected
if (isUtxoSelected) {
// const qiCoinbaseAddressBalances =
// await main.indexingService.getQiCoinbaseAddressBalances()

// await main.indexingService.persistQiCoinbaseAddressBalance(
// qiCoinbaseAddressBalances
// )
// await main.updateQiMiningAddressBalance()
await main.chainService.syncQiWallet()
console.log("triggerManualBalanceUpdate: after syncQiWallet")
await main.chainService.syncQiWallet(true)
} else {
console.log("triggerManualBalanceUpdate: !isUtxoSelected")
await main.manuallyCheckBalances()
}
}
Expand Down
3 changes: 1 addition & 2 deletions background/redux-slices/selectors/uiSelectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,8 @@ export const selectQiBalanceForCurrentUtxoAccountCyprus1 = createSelector(
(state: RootState) => state.ui.selectedUtxoAccount?.balances,
(balances) => {
const amount = balances?.[Zone.Cyprus1]?.assetAmount?.amount

return amount !== undefined && amount !== null && !isNaN(Number(amount))
? Number(formatQi(amount)).toFixed(3)
? formatQi(amount)
: null
}
)
56 changes: 42 additions & 14 deletions background/services/chain/db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { UNIXTime } from "../../types"
import {
AccountBalance,
AddressOnNetwork,
QiCoinbaseAddressBalance,
QiLedgerLastFullScan,
QiWalletBalance,
} from "../../accounts"
import { NetworkBaseAsset } from "../../networks"
Expand Down Expand Up @@ -53,13 +55,12 @@ export class ChainDatabase extends Dexie {
private baseAssets!: Dexie.Table<NetworkBaseAsset, string>

private qiCoinbaseAddressBalances!: Dexie.Table<
{
address: string
balance: string
},
QiCoinbaseAddressBalance,
number
>

private qiLedgerLastFullScan!: Dexie.Table<QiLedgerLastFullScan, string>

constructor(options?: DexieOptions) {
super("pelagus/chain", options)
this.version(1).stores({
Expand All @@ -81,7 +82,9 @@ export class ChainDatabase extends Dexie {
})

this.version(3).stores({
qiCoinbaseAddressBalance: "++id,balance",
qiCoinbaseAddressBalances:
"&[address+chainID],address,chainID,balance,retrievedAt,dataSource",
// qiLedgerLastFullScan: "&chainID,retrievedAt",
})
}

Expand Down Expand Up @@ -266,26 +269,51 @@ export class ChainDatabase extends Dexie {

async setQiCoinbaseAddressBalance(balance: {
address: string
balance: string
balance: bigint
chainID: string
}): Promise<void> {
await this.qiCoinbaseAddressBalances.put(balance)
await this.qiCoinbaseAddressBalances.put({
...balance,
retrievedAt: Date.now(),
dataSource: "local",
})
}

async getQiCoinbaseAddressBalance(address: string): Promise<bigint> {
async getQiCoinbaseAddressBalance(
address: string,
chainID: string
): Promise<bigint> {
return BigInt(
(
await this.qiCoinbaseAddressBalances
.where("address")
.equals(address)
.where("[address+chainID]")
.equals([address, chainID])
.toArray()
)[0]?.balance ?? "0"
)
}

async getQiCoinbaseAddressBalances(): Promise<
{ address: string; balance: string }[]
> {
return this.qiCoinbaseAddressBalances.toArray()
async getQiCoinbaseAddressBalances(
chainID: string
): Promise<QiCoinbaseAddressBalance[]> {
const balances = await this.qiCoinbaseAddressBalances
.where("chainID")
.equals(chainID)
.toArray()
return balances
}

async setQiLedgerLastFullScan(chainID: string): Promise<void> {
await this.qiLedgerLastFullScan.put({
chainID,
retrievedAt: Date.now(),
})
}

async getQiLedgerLastFullScan(
chainID: string
): Promise<QiLedgerLastFullScan | undefined> {
return this.qiLedgerLastFullScan.get(chainID)
}
}

Expand Down
111 changes: 55 additions & 56 deletions background/services/chain/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ import KeyringService from "../keyring"
import type { ValidatedAddEthereumChainParameter } from "../provider-bridge/utils"
import { MAILBOX_INTERFACE } from "../../contracts/payment-channel-mailbox"
import { OutpointInfo } from "quais/lib/commonjs/wallet/qi-hdwallet"
import NotificationsManager from "../notifications"
import { bigIntToDecimal } from "../../redux-slices/utils/asset-utils"

// The number of blocks to query at a time for historic asset transfers.
// Unfortunately there's no "right" answer here that works well across different
Expand Down Expand Up @@ -199,7 +201,7 @@ export default class ChainService extends BaseService<Events> {
},
qiWalletSync: {
schedule: {
periodInMinutes: 1,
periodInMinutes: 5,
},
handler: () => this.syncQiWallet(),
},
Expand Down Expand Up @@ -304,7 +306,7 @@ export default class ChainService extends BaseService<Events> {
{ type: "balance", address },
async (balance: bigint) => {
if (isQiAddress(address)) {
await this.handleQiMiningAddressBalanceUpdate(network)
await this.handleQiMiningAddressBalanceUpdate(network, address)
} else {
await this.handleQuaiAddressBalanceUpdate(network, address, balance)
}
Expand All @@ -329,6 +331,35 @@ export default class ChainService extends BaseService<Events> {
dataSource: "local",
retrievedAt: Date.now(),
}

//get current selected account balance and compare to get amount of incoming assets
const selectedAccount = await this.preferenceService.getSelectedAccount()
const currentAccountState =
globalThis.main.store.getState().account.accountsData.evm[
selectedAccount.network.chainID
]?.[selectedAccount.address]
const currentNetworkChainID = selectedAccount.network.chainID

if (currentAccountState === "loading") return

const currentBalanceAmount =
currentAccountState?.balances["QUAI"].assetAmount.amount

// show this is the current network is selected
if (
currentBalanceAmount &&
balance > currentBalanceAmount &&
currentNetworkChainID === network.chainID &&
!this.keyringService.isLocked()
) {
const parsedAmount = bigIntToDecimal(balance - currentBalanceAmount)
NotificationsManager.createIncomingAssetsNotification(
parsedAmount,
asset.symbol,
address
)
}

this.emitter.emit("accountsWithBalances", {
balances: [accountBalance],
addressOnNetwork: {
Expand All @@ -340,31 +371,22 @@ export default class ChainService extends BaseService<Events> {
}

async handleQiMiningAddressBalanceUpdate(
network: NetworkInterface
network: NetworkInterface,
address: string
): Promise<void> {
const qiMiningAddresses =
await globalThis.main.indexingService.getQiCoinbaseAddresses()
const allOutpoints = (
await Promise.all(
qiMiningAddresses.map(async (qiAddress) => {
const outpoints = await this.getOutpointsForQiAddress(
qiAddress.address
)
return outpoints.map((outpoint) => ({
outpoint,
address: qiAddress.address,
account: qiAddress.account,
zone: Zone.Cyprus1,
}))
})
)
).flat()
const outpointReqs = await this.getOutpointsForQiAddress(address)
const outpoints = outpointReqs.map((outpoint) => ({
outpoint,
address,
account: 0,
zone: Zone.Cyprus1,
}))

if (allOutpoints.length === 0) return
if (outpoints.length === 0) return

const qiWallet = await this.keyringService.getQiHDWallet()
const paymentCode = qiWallet.getPaymentCode(0)
qiWallet.importOutpoints(allOutpoints)
qiWallet.importOutpoints(outpoints)

const serializedQiHDWallet = qiWallet.serialize()
await this.keyringService.vaultManager.update({
Expand Down Expand Up @@ -479,7 +501,7 @@ export default class ChainService extends BaseService<Events> {
return await this.jsonRpcProvider.getOutpointsByAddress(address)
}

async syncQiWallet(recheckAddresses: string[] = []): Promise<void> {
async syncQiWallet(forceFullScan = false): Promise<void> {
try {
const network = this.selectedNetwork
const qiWallet = await this.keyringService.getQiHDWallet()
Expand All @@ -505,38 +527,14 @@ export default class ChainService extends BaseService<Events> {
qiWallet.openChannel(paymentCode)
})

let allOutpoints: OutpointInfo[] = []
if (recheckAddresses.length > 0) {
allOutpoints = (
await Promise.all(
recheckAddresses.map(async (address) => {
const outpoints = await this.getOutpointsForQiAddress(address)
return outpoints.map((outpoint) => ({
outpoint,
address,
account: 0,
zone: Zone.Cyprus1,
}))
})
)
).flat()

if (allOutpoints.length > 0) {
qiWallet.importOutpoints(allOutpoints)
}
if (forceFullScan) {
await qiWallet.scan(Zone.Cyprus1)
} else {
await qiWallet.sync(Zone.Cyprus1)
}

await qiWallet.sync(Zone.Cyprus1)

const balance = qiWallet.getBalanceForZone(Zone.Cyprus1)

await this.keyringService.vaultManager.add(
{
qiHDWallet: qiWallet.serialize(),
},
{}
)

const qiWalletBalance: QiWalletBalance = {
paymentCode,
network,
Expand All @@ -558,11 +556,12 @@ export default class ChainService extends BaseService<Events> {

await this.db.addQiLedgerBalance(qiWalletBalance)

// this.db.getQiCoinbaseAddressBalance(paymentCode).then((balance) => {
// if (balance) {
// this.emitter.emit("qiCoinbaseAddressBalance", balance)
// }
// })
await this.keyringService.vaultManager.add(
{
qiHDWallet: qiWallet.serialize(),
},
{}
)
} catch (error) {
logger.error("Error getting qi wallet balance for address", error)
}
Expand Down
Loading

0 comments on commit 9bbd67d

Please sign in to comment.