import type { DBStore } from "./datastore/db"; import { AccountType } from "../utils/enums"; import type { AccountDTO, AccountEntity, AddressDTO, AddressEntity, AssetEntity, AssetTransactionEntity, NftEntity, SessionEntity, TokenEntity, TransactionEntity, VaultDTO, VaultEntity } from "../types/db.types"; import type { AssetType } from "../types/wallet.types"; import { currentTimestamp } from "../utils/common"; export type DBEvent = | { type: 'tx_refresh'; } | { type: 'nft_refresh'; } | { type: 'token_refresh'; } export type DBUpdateCallback = (event: DBEvent) => void; export class WalletDB { private readonly store: DBStore; private updateCallback?: DBUpdateCallback; constructor(store: DBStore) { this.store = store; } public onUpdate(callback: DBUpdateCallback): void { this.updateCallback = callback; } private notify(event: DBEvent): void { this.updateCallback?.(event); } public async initSchema(): Promise { return this.store.initSchema(); } public async clearData(): Promise { return this.store.clearData(); } public async addLocalTransaction(tx: TransactionEntity): Promise { try { await this.store.upsertTransaction(tx); this.notify({ type: 'tx_refresh' }); } catch (error) { console.error(error); } } public async addAssetTransaction(assetTx: AssetTransactionEntity): Promise { return this.store.upsertAssetTransaction(assetTx); } public async getLocalTransactions(account: number, tokenId?: string): Promise { return this.store.getTransactions(account, tokenId); } public async getPageLocalTransactions(account: number, pageNum: number, pageSize: number, tokenId?: string): Promise { return this.store.getPageTransactions(account, pageNum, pageSize, tokenId); } public async countLocalTransactions(account: number, tokenId?: string): Promise { return this.store.countTransactions(account, tokenId); } public async clearLocalTransactions(account: number): Promise { await this.store.clearTransactions(account); this.notify({ type: 'tx_refresh' }); } public async saveToken(account: number, token: TokenEntity): Promise { const asset: AssetEntity = { accountId: account, tokenIdHex: token.tokenIdHex, type: "token", addedTime: currentTimestamp() } await this.store.upsertToken(token); await this.saveAsset(asset); this.notify({ type: 'token_refresh' }); } public async getLocalTokens(account: number, pageNum: number, pageSize: number): Promise { return this.store.getTokens(account, pageNum, pageSize); } public async getToken(id: string): Promise { return this.store.getToken(id); } public async deleteToken(account: number, tokenId: string): Promise { await this.removeAsset(account, tokenId); const count = await this.store.countAssetsById(tokenId); if (count == 0) { await this.store.deleteToken(tokenId); } this.notify({ type: 'token_refresh' }); } public async saveNft(account: number, nft: NftEntity, time: number): Promise { const asset: AssetEntity = { accountId: account, tokenIdHex: nft.tokenIdHex, type: "nft", addedTime: time } await this.store.upsertNft(nft); await this.saveAsset(asset); this.notify({ type: 'nft_refresh' }); } public async getLocalNfts(account: number, pageNum: number, pageSize: number): Promise { return this.store.getNfts(account, pageNum, pageSize); } public async getLocalNft(id: string): Promise { return this.store.getNft(id); } public async deleteNft(account: number, tokenId: string): Promise { await this.removeAsset(account, tokenId); const count = await this.store.countAssetsById(tokenId); if (count == 0) { await this.store.deleteNft(tokenId); } this.notify({ type: 'nft_refresh' }); } public async countLocalNfts(account: number): Promise { return this.store.countNfts(account); } public async getAssets(account: number, type: AssetType): Promise { return this.store.getAssets(account, type); } public async saveAsset(asset: AssetEntity): Promise { await this.store.upsertAsset(asset); } public async removeAsset(account: number, id: string): Promise { return this.store.deleteAsset(account, id); } public async saveAccount(account: AccountDTO): Promise { const accountEntity: AccountEntity = { id: account.id, address: account.address, name: account.name, height: account.height, hidden: account.hidden, statusHash: account.statusHash, balance: JSON.stringify(account.balance), tokensBalance: JSON.stringify(account.tokensBalance) } return this.store.upsertAccount(accountEntity); } public async getAccounts(): Promise { const accs = await this.store.getAccounts(); return accs.map(a => ({ ...a, type: AccountType.DAPP, balance: JSON.parse(a.balance), tokensBalance: JSON.parse(a.tokensBalance) })); } public async countAccounts(): Promise { return this.store.countAccounts(); } public async updateAccountName(account: number, name: string): Promise { return this.store.updateAccountName(account, name); } public async saveSession(session: SessionEntity): Promise { return this.store.upsertSession(session); } public async getAccountSessions(accountId: number): Promise { return this.store.getSessionsByAccount(accountId); } public async removeSession(sessionId: string): Promise { return this.store.deleteSession(sessionId); } public async saveAddress(address: AddressDTO): Promise { const addressEntity: AddressEntity = { address: address.address, idx: address.idx, space: address.space, height: address.height, statusHash: address.statusHash, used: address.used, balance: JSON.stringify(address.balance), tokensBalance: JSON.stringify(address.tokensBalance) } return this.store.upsertAddress(addressEntity); } public async getReceiveAddresses(): Promise { const addrs = await this.store.getReceiveAddresses(); return addrs.map(a => ({ ...a, type: AccountType.MAIN, balance: JSON.parse(a.balance), tokensBalance: JSON.parse(a.tokensBalance) })); } public async getChangeAddresses(): Promise { const addrs = await this.store.getChangeAddresses(); return addrs.map(a => ({ ...a, type: AccountType.MAIN, balance: JSON.parse(a.balance), tokensBalance: JSON.parse(a.tokensBalance) })); } public async countAddresses(): Promise { return this.store.countAddresses(); } public async getVaults(): Promise { const vaults = await this.store.getVaults(); return vaults.map(v => ({ ...v, type: AccountType.VAULT, balance: JSON.parse(v.balance), tokensBalance: JSON.parse(v.tokensBalance) })); } public async saveVault(vault: VaultDTO): Promise { const vaultEntity: VaultEntity = { address: vault.address, idx: vault.idx, block: vault.block, height: vault.height, statusHash: vault.statusHash, balance: JSON.stringify(vault.balance), tokensBalance: JSON.stringify(vault.tokensBalance) }; return this.store.upsertVault(vaultEntity); } }