@otoplo/wallet-common 0.1.5 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -964,8 +964,9 @@ function Lt(a = 12) {
964
964
  function qe(a) {
965
965
  return Pe(a, ue);
966
966
  }
967
- function pe(a, e) {
968
- return De(a, e, { t: 2, m: 19456, p: 1, dkLen: 32 });
967
+ async function pe(a, e) {
968
+ const t = performance.now(), s = await De(a, e, { t: 2, m: 19456, p: 1, dkLen: 32 });
969
+ return console.log(performance.now() - t), s;
969
970
  }
970
971
  async function Ft(a, e) {
971
972
  const t = y.getRandomBuffer(16), s = y.getRandomBuffer(12), n = y.utf8ToBuffer(a), i = await pe(e, t), o = de(i, s).encrypt(n), r = y.concat([t, s, o]);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/utils/common.ts","../src/persistence/datastore/kv.ts","../src/utils/enums.ts","../src/persistence/wallet-db.ts","../src/services/cache.ts","../src/services/rostrum.ts","../src/utils/keypath.ts","../src/services/key.ts","../src/utils/asset.ts","../src/services/asset.ts","../src/services/transaction.ts","../src/utils/seed.ts","../src/utils/price.ts","../src/utils/vault.ts","../src/services/session.ts","../src/services/tx-transformer.ts","../src/services/discovery.ts","../src/services/wallet.ts","../src/state/slices/auth.ts","../src/state/slices/dapp.ts","../src/state/slices/loader.ts","../src/state/slices/notifications.ts","../src/state/slices/status.ts","../src/state/slices/wallet.ts","../src/state/store.ts","../src/state/hooks.ts"],"sourcesContent":["import { Address, AddressType, BufferUtils, CommonUtils, Networks } from \"libnexa-ts\";\r\nimport type { Balance } from \"../types/wallet.types\";\r\n\r\nexport const MAIN_WALLET_ID = -1;\r\nexport const MAX_INT64 = 9223372036854775807n;\r\nexport const VAULT_FIRST_BLOCK = 274710;\r\nexport const VAULT_SCRIPT_PREFIX = \"0014461ad25081cb0119d034385ff154c8d3ad6bdd76\";\r\n\r\nexport function isTestnet(): boolean {\r\n return Networks.defaultNetwork == Networks.testnet;\r\n}\r\n\r\nexport function isGenesisHashValid(hash: string): boolean {\r\n if(isTestnet()) {\r\n return hash == \"508c843a4b98fb25f57cf9ebafb245a5c16468f06519cdd467059a91e7b79d52\";\r\n }\r\n return hash == \"edc7144fe1ba4edd0edf35d7eea90f6cb1dba42314aa85da8207e97c5339c801\";\r\n}\r\n\r\nexport function isValidNexaAddress(address: string, type = AddressType.PayToScriptTemplate): boolean {\r\n return Address.isValid(address, Networks.defaultNetwork, type);\r\n}\r\n\r\nexport function getExplorerUrl(): string {\r\n return `https://${(isTestnet() ? 'testnet-' : '')}explorer.nexa.org`;\r\n}\r\n\r\nexport function currentTimestamp(): number {\r\n return Math.floor(Date.now() / 1000);\r\n}\r\n\r\nexport function estimateDateByFutureBlock(current: number, future: number): string {\r\n const estimateMins = (future - current) * 2;\r\n const time = new Date();\r\n time.setMinutes(time.getMinutes() + estimateMins);\r\n return time.toLocaleDateString();\r\n}\r\n\r\nexport function isNullOrEmpty(arg?: string | any[] | null): arg is undefined | [] | null | '' {\r\n return !arg || arg.length === 0;\r\n}\r\n\r\nexport function truncateStringMiddle(str?: string, maxLength = 0): string {\r\n if (!str || str.length <= maxLength) {\r\n return str || '';\r\n }\r\n\r\n const ellipsis = '...';\r\n const halfLength = Math.floor((maxLength - ellipsis.length) / 2);\r\n const firstHalf = str.slice(0, halfLength);\r\n const secondHalf = str.slice(str.length - halfLength);\r\n\r\n return firstHalf + ellipsis + secondHalf;\r\n};\r\n\r\nexport function capitalizeFirstLetter(str: string): string {\r\n if (str.length === 0) {\r\n return \"\";\r\n }\r\n return str.charAt(0).toUpperCase() + str.substring(1);\r\n}\r\n\r\nexport function getAddressBuffer(address: string): Uint8Array {\r\n if (CommonUtils.isHexa(address)) {\r\n return BufferUtils.hexToBuffer(address) ;\r\n }\r\n return Address.fromString(address).data;\r\n}\r\n\r\nexport function tokenIdToHex(token: string): string {\r\n if (CommonUtils.isHexa(token)) {\r\n return token;\r\n }\r\n return BufferUtils.bufferToHex(getAddressBuffer(token));\r\n}\r\n\r\nexport function tokenHexToAddr(token: string): string {\r\n if (!CommonUtils.isHexa(token)) {\r\n return token;\r\n }\r\n return new Address(getAddressBuffer(token), Networks.defaultNetwork, AddressType.GroupIdAddress).toString();\r\n}\r\n\r\nexport function tokenAmountToAssetAmount(amount?: string | number | bigint): string {\r\n if (amount == null || amount === \"\") {\r\n return \"\";\r\n }\r\n if (BigInt(amount) <= 0n) {\r\n return \"0\";\r\n }\r\n return amount.toString();\r\n}\r\n\r\nexport function sumBalance(balances: Balance[]): Balance {\r\n let confirmed = BigInt(0), unconfirmed = BigInt(0);\r\n balances.forEach(b => {\r\n confirmed += BigInt(b.confirmed);\r\n unconfirmed += BigInt(b.unconfirmed);\r\n });\r\n return {confirmed: confirmed.toString(), unconfirmed: unconfirmed.toString()};\r\n}\r\n\r\nexport function sumTokensBalance(balances: Record<string, Balance>[]): Record<string, Balance> {\r\n const tokensBalance: Record<string, Balance> = {};\r\n balances.forEach(b => {\r\n for (const key in b) {\r\n if (tokensBalance[key]) {\r\n tokensBalance[key].confirmed = (BigInt(tokensBalance[key].confirmed) + BigInt(b[key].confirmed)).toString();\r\n tokensBalance[key].unconfirmed = (BigInt(tokensBalance[key].unconfirmed) + BigInt(b[key].unconfirmed)).toString();\r\n } else {\r\n tokensBalance[key] = { confirmed: BigInt(b[key].confirmed).toString(), unconfirmed: BigInt(b[key].unconfirmed).toString() };\r\n }\r\n }\r\n });\r\n \r\n return tokensBalance;\r\n}\r\n\r\nconst FILE_EXTENSION_TO_TYPE = {\r\n // Images\r\n //'.svg': { media: 'image', mime: 'image/svg+xml' },\r\n '.gif': { media: 'image', mime: 'image/gif' },\r\n '.png': { media: 'image', mime: 'image/png' },\r\n '.apng': { media: 'image', mime: 'image/apng' },\r\n '.jpg': { media: 'image', mime: 'image/jpeg' },\r\n '.jpeg': { media: 'image', mime: 'image/jpeg' },\r\n '.avif': { media: 'image', mime: 'image/avif' },\r\n '.webp': { media: 'image', mime: 'image/webp' },\r\n '.bmp': { media: 'image', mime: 'image/bmp' },\r\n \r\n // Videos\r\n '.mp4': { media: 'video', mime: 'video/mp4' },\r\n '.mpeg': { media: 'video', mime: 'video/mpeg' },\r\n '.mpg': { media: 'video', mime: 'video/mpeg' },\r\n '.webm': { media: 'video', mime: 'video/webm' },\r\n '.mov': { media: 'video', mime: 'video/quicktime' },\r\n \r\n // Audio\r\n '.mp3': { media: 'audio', mime: 'audio/mpeg' },\r\n '.ogg': { media: 'audio', mime: 'audio/ogg' },\r\n '.wav': { media: 'audio', mime: 'audio/wav' },\r\n '.m4a': { media: 'audio', mime: 'audio/mp4' },\r\n} as const;\r\n\r\nexport function getFileMediaType(filename: string): 'video' | 'audio' | 'image' | 'unknown' {\r\n const lastDotIndex = filename.lastIndexOf('.');\r\n if (lastDotIndex === -1) return 'unknown';\r\n \r\n const extension = filename.slice(lastDotIndex).toLowerCase();\r\n return FILE_EXTENSION_TO_TYPE[extension as keyof typeof FILE_EXTENSION_TO_TYPE]?.media ?? 'unknown';\r\n}\r\n\r\nexport function getFileMimeType(filename: string): string {\r\n const lastDotIndex = filename.lastIndexOf('.');\r\n if (lastDotIndex === -1) return 'application/octet-stream';\r\n \r\n const extension = filename.slice(lastDotIndex).toLowerCase();\r\n return FILE_EXTENSION_TO_TYPE[extension as keyof typeof FILE_EXTENSION_TO_TYPE]?.mime ?? 'application/octet-stream';\r\n}","import type { RostrumParams } from \"../../types/rostrum.types\";\r\nimport { isNullOrEmpty, isTestnet } from \"../../utils/common\";\r\n\r\nexport abstract class KVStore {\r\n \r\n public abstract getValue(key: string): Promise<string | null>;\r\n public abstract setValue(key: string, value: string): Promise<void>;\r\n public abstract removeValue(key: string): Promise<void>;\r\n public abstract clearData(): Promise<void>;\r\n\r\n protected getPrefix(): string {\r\n return isTestnet() ? 'testnet-' : '';\r\n }\r\n\r\n public async getEncryptedSeed(): Promise<string | null> {\r\n return this.getValue(\"seed\");\r\n }\r\n\r\n public async saveEncryptedSeed(seed: string): Promise<void> {\r\n return this.setValue('seed', seed);\r\n }\r\n\r\n public async getVersionCode(): Promise<string | null> {\r\n return this.getValue(\"version-code\");\r\n }\r\n\r\n public async setVersionCode(code: string): Promise<void> {\r\n return this.setValue('version-code', code);\r\n }\r\n\r\n public async getReleaseNumber(): Promise<string | null> {\r\n return this.getValue(\"release-number\");\r\n }\r\n\r\n public async setReleaseNumber(release: string): Promise<void> {\r\n return this.setValue('release-number', release);\r\n }\r\n\r\n public async getRostrumParams(): Promise<RostrumParams | undefined> {\r\n const params = await this.getValue(this.getPrefix() + \"rostrum-params\");\r\n if (params) {\r\n return JSON.parse(params);\r\n }\r\n }\r\n\r\n public async saveRostrumParams(params: RostrumParams): Promise<void> {\r\n return this.setValue(this.getPrefix() + \"rostrum-params\", JSON.stringify(params));\r\n }\r\n\r\n public async removeRostrumParams(): Promise<void> {\r\n return this.removeValue(this.getPrefix() + \"rostrum-params\");\r\n }\r\n\r\n public async setHideZeroTokenConfig(hide: boolean): Promise<void> {\r\n return this.setValue(\"zero-tokens\", JSON.stringify(hide));\r\n }\r\n\r\n public async getHideZeroTokenConfig(): Promise<boolean> {\r\n const hide = await this.getValue(\"zero-tokens\");\r\n return hide === \"true\";\r\n }\r\n\r\n public async setHideZeroVaultsConfig(hide: boolean): Promise<void> {\r\n return this.setValue(\"zero-vaults\", JSON.stringify(hide));\r\n }\r\n\r\n public async getHideZeroVaultsConfig(): Promise<boolean> {\r\n const hide = await this.getValue(\"zero-vaults\");\r\n return hide === \"true\";\r\n }\r\n\r\n public async getSelectedCurrency(): Promise<string> {\r\n const value = await this.getValue('selectedCurrency');\r\n return value || 'usd';\r\n }\r\n\r\n public async setSelectedCurrency(currency: string): Promise<void> {\r\n return this.setValue('selectedCurrency', currency);\r\n }\r\n\r\n public async getUseBiometric(): Promise<boolean> {\r\n const value = await this.getValue('biometrics');\r\n return value === \"true\";\r\n }\r\n\r\n public async setUseBiometric(useBiometric: boolean): Promise<void> {\r\n return this.setValue('biometrics', JSON.stringify(useBiometric));\r\n }\r\n\r\n public async getRequireAuth(): Promise<boolean> {\r\n const value = await this.getValue('auth');\r\n return isNullOrEmpty(value) || value === \"true\";\r\n }\r\n\r\n public async setRequireAuth(requireAuth: boolean): Promise<void> {\r\n await this.setValue('auth', JSON.stringify(requireAuth));\r\n }\r\n\r\n public async getReleaseNotesTime(): Promise<number | undefined> {\r\n const value = await this.getValue('show-notes');\r\n return value ? Number(value) : undefined;\r\n }\r\n\r\n public async setReleaseNotesTime(time: string): Promise<void> {\r\n if (isNullOrEmpty(time)) {\r\n await this.removeValue('show-notes');\r\n } else {\r\n await this.setValue('show-notes', time);\r\n }\r\n }\r\n\r\n public async getIsTestnet(): Promise<boolean> {\r\n const value = await this.getValue('testnet');\r\n return value === \"1\";\r\n }\r\n\r\n public async setIsTestnet(isTestnet: boolean): Promise<void> {\r\n await this.setValue('testnet', isTestnet ? \"1\" : \"0\");\r\n }\r\n\r\n public async getAutoLockSeconds(): Promise<number> {\r\n const value = await this.getValue('auto-lock');\r\n return value ? parseInt(value) : 60;\r\n }\r\n\r\n public async setAutoLockSeconds(autoLock: number): Promise<void> {\r\n await this.setValue('auto-lock', `${autoLock}`);\r\n }\r\n}","export enum AccountType {\r\n MAIN = 0,\r\n VAULT = 1,\r\n DAPP = 2\r\n}\r\n\r\nexport enum KeySpace {\r\n RECEIVE = 0,\r\n CHANGE = 1\r\n}\r\n\r\nexport enum SessionRequestType {\r\n SignMessage = 'signMessage',\r\n AddToken = 'addToken',\r\n SignTransaction = 'signTransaction',\r\n SendTransaction = 'sendTransaction',\r\n}\r\n\r\nexport enum AssetType {\r\n TOKEN = 'token',\r\n NFT = 'nft'\r\n}","import type { DBStore } from \"./datastore/db\";\r\nimport { AccountType, AssetType } from \"../utils/enums\";\r\nimport type { AccountDTO, AccountEntity, AddressDTO, AddressEntity, AssetEntity, AssetTransactionEntity, NftEntity, SessionEntity, TokenEntity, TransactionEntity, VaultDTO, VaultEntity } from \"../types/db.types\";\r\nimport { currentTimestamp } from \"../utils/common\";\r\n\r\nexport type DBEvent =\r\n | { type: 'tx_refresh'; }\r\n | { type: 'nft_refresh'; }\r\n | { type: 'token_added'; accountId: number; token: AssetEntity; }\r\n | { type: 'token_removed'; accountId: number; tokenId: string; }\r\n | { type: 'nft_deleted'; id: string; }\r\n\r\nexport type DBUpdateCallback = (event: DBEvent) => void;\r\n\r\nexport class WalletDB {\r\n\r\n private readonly store: DBStore;\r\n private updateCallback?: DBUpdateCallback;\r\n\r\n constructor(store: DBStore) {\r\n this.store = store;\r\n }\r\n\r\n public onUpdate(callback: DBUpdateCallback): void {\r\n this.updateCallback = callback;\r\n }\r\n\r\n private notify(event: DBEvent): void {\r\n this.updateCallback?.(event);\r\n }\r\n\r\n public async initSchema(): Promise<boolean> {\r\n return this.store.initSchema();\r\n }\r\n\r\n public async clearData(): Promise<void> {\r\n return this.store.clearData();\r\n }\r\n\r\n public async addLocalTransaction(tx: TransactionEntity): Promise<void> {\r\n try {\r\n await this.store.upsertTransaction(tx);\r\n this.notify({ type: 'tx_refresh' });\r\n } catch (error) {\r\n console.error(error);\r\n }\r\n }\r\n\r\n public async addAssetTransaction(assetTx: AssetTransactionEntity): Promise<void> {\r\n return this.store.upsertAssetTransaction(assetTx);\r\n }\r\n\r\n public async getLocalTransactions(account: number, tokenId?: string): Promise<TransactionEntity[] | undefined> {\r\n return this.store.getTransactions(account, tokenId);\r\n }\r\n\r\n public async getPageLocalTransactions(account: number, pageNum: number, pageSize: number, tokenId?: string): Promise<TransactionEntity[] | undefined> {\r\n return this.store.getPageTransactions(account, pageNum, pageSize, tokenId);\r\n }\r\n\r\n public async countLocalTransactions(account: number, tokenId?: string): Promise<number> {\r\n return this.store.countTransactions(account, tokenId);\r\n }\r\n\r\n public async clearLocalTransactions(account: number): Promise<void> {\r\n await this.store.clearTransactions(account);\r\n this.notify({ type: 'tx_refresh' });\r\n }\r\n\r\n public async saveToken(account: number, token: TokenEntity): Promise<void> {\r\n const asset: AssetEntity = {\r\n accountId: account,\r\n tokenIdHex: token.tokenIdHex,\r\n type: AssetType.TOKEN,\r\n addedTime: currentTimestamp()\r\n }\r\n await this.store.upsertAsset(asset);\r\n await this.store.upsertToken(token);\r\n this.notify({ type: 'token_added', accountId: account, token: asset });\r\n }\r\n\r\n public async getLocalTokens(account: number): Promise<AssetEntity[] | undefined> {\r\n return this.store.getTokens(account);\r\n }\r\n\r\n public async getToken(id: string): Promise<TokenEntity | undefined> {\r\n return this.store.getToken(id);\r\n }\r\n\r\n public async deleteToken(account: number, tokenId: string): Promise<void> {\r\n await this.removeAsset(account, tokenId);\r\n const count = await this.store.countAssetsById(tokenId);\r\n if (count == 0) {\r\n await this.store.deleteToken(tokenId);\r\n }\r\n this.notify({ type: 'token_removed', accountId: account, tokenId: tokenId });\r\n }\r\n\r\n public async saveNft(asset: AssetEntity, nft: NftEntity): Promise<void> {\r\n await this.store.upsertNft(nft);\r\n await this.saveAsset(asset, true);\r\n }\r\n\r\n public async getLocalNfts(account: number, pageNum: number, pageSize: number): Promise<AssetEntity[] | undefined> {\r\n return this.store.getNfts(account, pageNum, pageSize);\r\n }\r\n\r\n public async getLocalNft(id: string): Promise<NftEntity | undefined> {\r\n return this.store.getNft(id);\r\n }\r\n\r\n public async deleteNft(account: number, tokenId: string, notify = false): Promise<void> {\r\n await this.removeAsset(account, tokenId);\r\n const count = await this.store.countAssetsById(tokenId);\r\n if (count == 0) {\r\n await this.store.deleteNft(tokenId);\r\n this.notify({ type: 'nft_deleted', id: tokenId });\r\n }\r\n if (notify) {\r\n this.notify({ type: 'nft_refresh' });\r\n }\r\n }\r\n\r\n public async countLocalNfts(account: number): Promise<number> {\r\n return this.store.countNfts(account);\r\n }\r\n\r\n public async isNftExist(id: string): Promise<boolean> {\r\n return this.store.isNftExist(id);\r\n }\r\n\r\n public async saveAsset(asset: AssetEntity, notifyNft = false): Promise<void> {\r\n await this.store.upsertAsset(asset);\r\n if (notifyNft) {\r\n this.notify({ type: 'nft_refresh' });\r\n }\r\n }\r\n\r\n public async removeAsset(account: number, id: string): Promise<void> {\r\n return this.store.deleteAsset(account, id);\r\n }\r\n\r\n public async isAssetExistForAccount(account: number, id: string): Promise<boolean> {\r\n return this.store.isAssetExistForAccount(account, id);\r\n }\r\n\r\n public async saveAccount(account: AccountDTO): Promise<void> {\r\n const accountEntity: AccountEntity = {\r\n id: account.id,\r\n address: account.address,\r\n name: account.name,\r\n height: account.height,\r\n hidden: account.hidden,\r\n statusHash: account.statusHash,\r\n balance: JSON.stringify(account.balance),\r\n tokensBalance: JSON.stringify(account.tokensBalance)\r\n }\r\n return this.store.upsertAccount(accountEntity);\r\n }\r\n\r\n public async getAccounts(): Promise<AccountDTO[]> {\r\n const accs = await this.store.getAccounts();\r\n return accs.map(a => ({\r\n ...a,\r\n type: AccountType.DAPP,\r\n balance: JSON.parse(a.balance),\r\n tokensBalance: JSON.parse(a.tokensBalance)\r\n }));\r\n }\r\n\r\n public async countAccounts(): Promise<number> {\r\n return this.store.countAccounts();\r\n }\r\n\r\n public async updateAccountName(account: number, name: string): Promise<void> {\r\n return this.store.updateAccountName(account, name);\r\n }\r\n\r\n public async saveSession(session: SessionEntity): Promise<void> {\r\n return this.store.upsertSession(session);\r\n }\r\n\r\n public async getAccountSessions(accountId: number): Promise<SessionEntity[]> {\r\n return this.store.getSessionsByAccount(accountId);\r\n }\r\n\r\n public async removeSession(sessionId: string): Promise<void> {\r\n return this.store.deleteSession(sessionId);\r\n }\r\n\r\n public async saveAddress(address: AddressDTO): Promise<void> {\r\n const addressEntity: AddressEntity = {\r\n address: address.address,\r\n idx: address.idx,\r\n space: address.space,\r\n height: address.height,\r\n statusHash: address.statusHash,\r\n used: address.used,\r\n balance: JSON.stringify(address.balance),\r\n tokensBalance: JSON.stringify(address.tokensBalance)\r\n }\r\n return this.store.upsertAddress(addressEntity);\r\n }\r\n\r\n public async getReceiveAddresses(): Promise<AddressDTO[]> {\r\n const addrs = await this.store.getReceiveAddresses();\r\n return addrs.map(a => ({\r\n ...a,\r\n type: AccountType.MAIN,\r\n balance: JSON.parse(a.balance),\r\n tokensBalance: JSON.parse(a.tokensBalance)\r\n }));\r\n }\r\n\r\n public async getChangeAddresses(): Promise<AddressDTO[]> {\r\n const addrs = await this.store.getChangeAddresses();\r\n return addrs.map(a => ({\r\n ...a,\r\n type: AccountType.MAIN,\r\n balance: JSON.parse(a.balance),\r\n tokensBalance: JSON.parse(a.tokensBalance)\r\n }));\r\n }\r\n\r\n public async countAddresses(): Promise<number> {\r\n return this.store.countAddresses();\r\n }\r\n\r\n public async getVaults(): Promise<VaultDTO[]> {\r\n const vaults = await this.store.getVaults();\r\n return vaults.map(v => ({\r\n ...v,\r\n type: AccountType.VAULT,\r\n balance: JSON.parse(v.balance),\r\n tokensBalance: JSON.parse(v.tokensBalance)\r\n }));\r\n }\r\n\r\n public async saveVault(vault: VaultDTO): Promise<void> {\r\n const vaultEntity: VaultEntity = {\r\n address: vault.address,\r\n idx: vault.idx,\r\n block: vault.block,\r\n height: vault.height,\r\n statusHash: vault.statusHash,\r\n balance: JSON.stringify(vault.balance),\r\n tokensBalance: JSON.stringify(vault.tokensBalance)\r\n };\r\n return this.store.upsertVault(vaultEntity);\r\n }\r\n}\r\n","import type { NftEntity, TokenEntity } from \"../types/db.types\";\r\nimport { tokenIdToHex } from \"../utils/common\";\r\nimport type { WalletDB } from \"../persistence/wallet-db\";\r\n\r\nexport class WalletCache {\r\n\r\n private readonly walletDb: WalletDB;\r\n\r\n private readonly tokens = new Map<string, TokenEntity>();\r\n private readonly nfts = new Map<string, NftEntity>();\r\n\r\n public constructor(walletDb: WalletDB) {\r\n this.walletDb = walletDb;\r\n }\r\n\r\n public clear(): void {\r\n this.tokens.clear();\r\n this.nfts.clear();\r\n }\r\n\r\n public async getTokenById(id: string): Promise<TokenEntity | undefined> {\r\n id = tokenIdToHex(id);\r\n if (this.tokens.has(id)) {\r\n return this.tokens.get(id)!;\r\n }\r\n\r\n const token = await this.walletDb.getToken(id);\r\n if (token) {\r\n this.tokens.set(id, token);\r\n }\r\n return token;\r\n }\r\n\r\n public async getNftById(id: string): Promise<NftEntity | undefined> {\r\n id = tokenIdToHex(id);\r\n if (this.nfts.has(id)) {\r\n return this.nfts.get(id)!;\r\n }\r\n\r\n const nft = await this.walletDb.getLocalNft(id);\r\n if (nft) {\r\n this.nfts.set(id, nft);\r\n }\r\n return nft;\r\n }\r\n\r\n public removeToken(id: string): void {\r\n this.tokens.delete(tokenIdToHex(id));\r\n }\r\n\r\n public removeNft(id: string): void {\r\n this.nfts.delete(tokenIdToHex(id));\r\n }\r\n}","import type { RequestResponse} from \"@otoplo/electrum-client\";\r\nimport { ConnectionStatus, ElectrumClient, TransportScheme } from \"@otoplo/electrum-client\";\r\nimport type { BlockTip, IFirstUse, IListUnspentRecord, ITokenGenesis, ITokenListUnspent, ITokensBalance, ITokenUtxo, ITransaction, ITXHistory, IUtxo, RostrumParams, ServerFeatures } from \"../types/rostrum.types\";\r\nimport type { Balance } from \"../types/wallet.types\";\r\nimport { isTestnet } from \"../utils/common\";\r\nimport type { KVStore } from \"../persistence/datastore/kv\";\r\n\r\ntype RPCParameter = object | string | number | boolean | null;\r\n\r\nexport class RostrumService {\r\n\r\n private readonly kvStore: KVStore;\r\n\r\n private client?: ElectrumClient;\r\n\r\n public constructor(kvStore: KVStore) {\r\n this.kvStore = kvStore;\r\n }\r\n \r\n public getFeatures(): Promise<ServerFeatures> {\r\n return this.execute<ServerFeatures>('server.features');\r\n }\r\n\r\n public getBlockTip(): Promise<BlockTip> {\r\n return this.execute<BlockTip>('blockchain.headers.tip');\r\n }\r\n\r\n public getBalance(address: string): Promise<Balance> {\r\n return this.execute<Balance>('blockchain.address.get_balance', address, 'exclude_tokens');\r\n }\r\n\r\n public getTransactionsHistory(address: string, fromHeight = 0): Promise<ITXHistory[]> {\r\n return this.execute<ITXHistory[]>('blockchain.address.get_history', address, { from_height: fromHeight });\r\n }\r\n\r\n public getFirstUse(address: string): Promise<IFirstUse> {\r\n return this.execute<IFirstUse>('blockchain.address.get_first_use', address);\r\n }\r\n\r\n public async isAddressUsed(address: string): Promise<boolean> {\r\n try {\r\n const firstUse = await this.getFirstUse(address);\r\n return !!(firstUse.tx_hash && firstUse.tx_hash !== \"\");\r\n } catch (e) {\r\n if (e instanceof Error && e.message.includes(\"not found\")) {\r\n return false;\r\n }\r\n throw e;\r\n }\r\n }\r\n \r\n public getTransaction(id: string, verbose = true): Promise<ITransaction> {\r\n return this.execute<ITransaction>('blockchain.transaction.get', id, verbose);\r\n }\r\n\r\n public getUtxo(outpoint: string): Promise<IUtxo> {\r\n return this.execute<IUtxo>('blockchain.utxo.get', outpoint);\r\n }\r\n\r\n public getNexaUtxos(address: string): Promise<IListUnspentRecord[]> {\r\n return this.execute<IListUnspentRecord[]>('blockchain.address.listunspent', address, 'exclude_tokens');\r\n }\r\n \r\n public async getTokenUtxos(address: string, token: string): Promise<ITokenUtxo[]> {\r\n const listunspent = await this.execute<ITokenListUnspent>('token.address.listunspent', address, null, token);\r\n return listunspent.unspent;\r\n }\r\n\r\n public async getTokensBalance(address: string): Promise<Record<string, Balance>> {\r\n const tokensBalance = await this.execute<ITokensBalance>('token.address.get_balance', address);\r\n const balance: Record<string, Balance> = {};\r\n \r\n for (const cToken in tokensBalance.confirmed) {\r\n if (tokensBalance.confirmed[cToken] != 0) {\r\n balance[cToken] = { confirmed: BigInt(tokensBalance.confirmed[cToken]).toString(), unconfirmed: \"0\" }\r\n }\r\n }\r\n \r\n for (const uToken in tokensBalance.unconfirmed) {\r\n if (tokensBalance.unconfirmed[uToken] != 0) {\r\n if (balance[uToken]) {\r\n balance[uToken].unconfirmed = BigInt(tokensBalance.unconfirmed[uToken]).toString();\r\n } else {\r\n balance[uToken] = { confirmed: \"0\", unconfirmed: BigInt(tokensBalance.unconfirmed[uToken]).toString() }\r\n }\r\n }\r\n }\r\n \r\n return balance;\r\n }\r\n \r\n public getTokenGenesis(token: string): Promise<ITokenGenesis> {\r\n return this.execute<ITokenGenesis>('token.genesis.info', token);\r\n }\r\n\r\n public broadcast(txHex: string): Promise<string> {\r\n return this.execute<string>('blockchain.transaction.broadcast', txHex);\r\n }\r\n\r\n public subscribeHeaders(handler: (block: number) => void): Promise<Error | RequestResponse> {\r\n return this.client!.subscribe((response: any) => {\r\n const data = Array.isArray(response) ? response[0] : response;\r\n const height = typeof data?.height === 'number' ? data.height : 0;\r\n handler(height);\r\n }, 'blockchain.headers.subscribe');\r\n }\r\n\r\n public subscribeAddress(address: string, handler: (data: unknown) => void): Promise<Error | RequestResponse> {\r\n return this.client!.subscribe(handler, 'blockchain.address.subscribe', address);\r\n }\r\n \r\n public async getLatency(): Promise<number> {\r\n try {\r\n const start = Date.now();\r\n const res = await this.getBlockTip();\r\n if (res) {\r\n return Date.now() - start;\r\n }\r\n return 0;\r\n } catch {\r\n return 0;\r\n }\r\n }\r\n \r\n public async connect(params?: RostrumParams): Promise<void> {\r\n try {\r\n if (!params) {\r\n params = await this.getCurrentInstance();\r\n }\r\n\r\n this.client = new ElectrumClient(\"com.otoplo.wallet\", \"1.4.3\", params.host, params.port, params.scheme, 45*1000, 10*1000);\r\n await this.client.connect();\r\n } catch (e) {\r\n if (e instanceof Error) {\r\n console.info(e.message);\r\n } else {\r\n console.error(e);\r\n }\r\n throw e;\r\n }\r\n }\r\n \r\n public async disconnect(force?: boolean): Promise<boolean> {\r\n try {\r\n return await this.client?.disconnect(force) ?? false;\r\n } catch (e) {\r\n console.error(e)\r\n return false;\r\n }\r\n }\r\n \r\n private async execute<T>(method: string, ...parameters: RPCParameter[]): Promise<T> {\r\n await this.waitForConnection();\r\n const res = await this.client!.request(method, ...parameters);\r\n if (res instanceof Error) {\r\n throw res;\r\n }\r\n return res as T;\r\n }\r\n\r\n private waitForConnection(timeout = 5000): Promise<void> {\r\n const start = Date.now();\r\n\r\n return new Promise((resolve, reject) => {\r\n const check = (): void => {\r\n if (this.client?.connectionStatus == ConnectionStatus.CONNECTED) {\r\n return resolve();\r\n }\r\n if (Date.now() - start > timeout) {\r\n return reject(new Error(\"Rostrum Connection timeout\"));\r\n }\r\n setTimeout(check, 250);\r\n };\r\n\r\n check();\r\n });\r\n }\r\n\r\n public async getCurrentInstance(): Promise<RostrumParams> {\r\n const params = await this.kvStore.getRostrumParams();\r\n if (params) {\r\n return params;\r\n }\r\n return RostrumService.getPredefinedInstances()[0];\r\n }\r\n\r\n public static getPredefinedInstances(): RostrumParams[] { \r\n if (isTestnet()) {\r\n return [\r\n {\r\n scheme: TransportScheme.WSS,\r\n host: 'testnet-electrum.nexa.org',\r\n port: 30004,\r\n label: 'NexaOrg'\r\n }\r\n ];\r\n } else {\r\n return [\r\n {\r\n scheme: TransportScheme.WSS,\r\n host: 'rostrum.otoplo.com',\r\n port: 443,\r\n label: 'Otoplo'\r\n },\r\n {\r\n scheme: TransportScheme.WSS,\r\n host: 'electrum.nexa.org',\r\n port: 20004,\r\n label: 'NexaOrg'\r\n }\r\n ];\r\n }\r\n }\r\n}","import type { KeyPath } from \"../types\";\r\nimport type { AccountType, KeySpace } from \"./enums\";\r\n\r\nexport function keyPathToString(account: AccountType, type: KeySpace, index: number): string {\r\n return `${account}'/${type}/${index}`;\r\n}\r\n\r\nexport function stringToKeyPath(path: string): KeyPath {\r\n const parts = path.split('/');\r\n return {\r\n account: parseInt(parts[0].replace(\"'\", \"\")) as AccountType,\r\n type: parseInt(parts[1]) as KeySpace,\r\n index: parseInt(parts[2])\r\n };\r\n}","import { mnemonicToSeedSync } from \"@scure/bip39\";\r\nimport { HDPrivateKey } from \"libnexa-ts\";\r\nimport type { AccountType } from \"../utils/enums\";\r\nimport type { KeyPath } from \"../types/wallet.types\";\r\nimport { keyPathToString, stringToKeyPath } from \"../utils/keypath\";\r\n\r\nexport class KeyManager {\r\n\r\n private seed!: Uint8Array;\r\n private masterKey!: HDPrivateKey;\r\n private accountKeys = new Map<number, HDPrivateKey>();\r\n private walletKeys = new Map<string, HDPrivateKey>();\r\n\r\n public init(mnemonic: string | Uint8Array): void {\r\n this.seed = typeof mnemonic === \"string\" ? mnemonicToSeedSync(mnemonic) : mnemonic;\r\n this.masterKey = HDPrivateKey.fromSeed(this.seed).deriveChild(44, true).deriveChild(29223, true);\r\n }\r\n\r\n public reset(): void {\r\n if (!this.seed) {\r\n throw new Error(\"KeysManager not initialized\");\r\n }\r\n this.masterKey = HDPrivateKey.fromSeed(this.seed).deriveChild(44, true).deriveChild(29223, true);\r\n this.accountKeys.clear();\r\n this.walletKeys.clear();\r\n }\r\n\r\n private getAccountKey(account: AccountType): HDPrivateKey {\r\n let key = this.accountKeys.get(account);\r\n if (!key) {\r\n key = this.masterKey.deriveChild(account, true);\r\n this.accountKeys.set(account, key);\r\n }\r\n\r\n return key;\r\n }\r\n\r\n public getKey(keyPath: string | KeyPath): HDPrivateKey {\r\n const path = typeof keyPath === 'string'\r\n ? keyPath\r\n : keyPathToString(keyPath.account, keyPath.type, keyPath.index);\r\n\r\n let key = this.walletKeys.get(path);\r\n if (!key) {\r\n const { account, type, index } = typeof keyPath === 'string'\r\n ? stringToKeyPath(keyPath)\r\n : keyPath;\r\n const accountKey = this.getAccountKey(account);\r\n key = accountKey.deriveChild(type, false).deriveChild(index, false);\r\n this.walletKeys.set(path, key);\r\n }\r\n\r\n return key;\r\n }\r\n}","import { BufferUtils, GroupToken } from \"libnexa-ts\";\r\nimport type { TokenEntity } from \"../types/db.types\";\r\nimport { getAddressBuffer, isTestnet } from \"./common\";\r\n\r\nexport function getNiftyToken(): TokenEntity {\r\n return {\r\n name: 'NiftyArt',\r\n ticker: 'NIFTY',\r\n iconUrl: 'https://niftyart.cash/td/niftyicon.svg',\r\n parentGroup: '',\r\n token: isTestnet()\r\n ? 'nexatest:tq8r37lcjlqazz7vuvug84q2ev50573hesrnxkv9y6hvhhl5k5qqqnmyf79mx'\r\n : 'nexa:tr9v70v4s9s6jfwz32ts60zqmmkp50lqv7t0ux620d50xa7dhyqqqcg6kdm6f',\r\n tokenIdHex: isTestnet()\r\n ? '0e38fbf897c1d10bcce33883d40acb28fa7a37cc0733598526aecbdff4b50000'\r\n : 'cacf3d958161a925c28a970d3c40deec1a3fe06796fe1b4a7b68f377cdb90000',\r\n decimals: 0\r\n };\r\n}\r\n\r\nexport function fetchNiftyNFT(id: string): Promise<Uint8Array> {\r\n return performGet(getNiftyEndpoint() + id, 'raw');\r\n}\r\n\r\nexport function isNiftySubgroup(group: string): boolean {\r\n try {\r\n const addrBuf = getAddressBuffer(group);\r\n if (!GroupToken.isSubgroup(addrBuf)) {\r\n return false;\r\n }\r\n\r\n return BufferUtils.bufferToHex(addrBuf.subarray(0, 32)) === getNiftyToken().tokenIdHex;\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\nexport function fetchAssetDoc(url: string): Promise<any> {\r\n // it is possible that legacy token description is stored on IPFS, check for this\r\n // example: ipfs://bafkvmicdm2vdjgieqvk3s5ykqlddtzd42yuy7voum4cifpknjvhv3uarwu\r\n url = translateIfIpfsUrl(url);\r\n return performGet(url, 'json');\r\n}\r\n\r\nexport function fetchAssetBlob(url: string): Promise<Uint8Array> {\r\n // it is possible that NRC (Token / NFT) description is stored on IPFS, check for this\r\n // example: ipfs://bafkvmicdm2vdjgieqvk3s5ykqlddtzd42yuy7voum4cifpknjvhv3uarwu\r\n url = translateIfIpfsUrl(url);\r\n return performGet(url, 'raw');\r\n}\r\n\r\nexport function transformTokenIconUrl(icon: string, documentUrl: string): string {\r\n if (icon && typeof icon === 'string') {\r\n if (icon.startsWith('http')) {\r\n return icon.replace('http://', 'https://');\r\n }\r\n if (icon.startsWith('ipfs://')) {\r\n return icon;\r\n }\r\n const url = new URL(documentUrl);\r\n return `${url.origin}${icon}`;\r\n }\r\n return \"\";\r\n}\r\n\r\nexport function parseTokenDataUrl(data?: string): string | null {\r\n if (!data) {\r\n return null;\r\n }\r\n return translateIfIpfsUrl(data);\r\n}\r\n\r\nfunction translateIfIpfsUrl(url: string, gateway = \"https://ipfs.nebula.markets/\"): string {\r\n // if ipfs gateway is implemented properly, you will be able to trim\r\n // the ipfs:// from the url and append the url to the gateway path\r\n // see https://docs.ipfs.tech/concepts/ipfs-gateway/#path for more info\r\n if (url?.startsWith(\"ipfs://\")) {\r\n return gateway + url.substring(7);\r\n }\r\n return url;\r\n}\r\n\r\nfunction getNiftyEndpoint(): string {\r\n return `https://${isTestnet() ? 'testnet.' : ''}niftyart.cash/_public/`;\r\n}\r\n\r\nasync function performGet(url: string, responseType?: 'json' | 'raw'): Promise<any> {\r\n try {\r\n const response = await fetch(url);\r\n if (!response.ok) {\r\n throw new Error(`Failed to perform GET. status: ${response.status}`);\r\n }\r\n \r\n if (responseType === 'raw') {\r\n const arrayBuffer = await response.arrayBuffer();\r\n return new Uint8Array(arrayBuffer);\r\n } else {\r\n return await response.json();\r\n }\r\n } catch (e) {\r\n throw new Error(`Unexpected Error: ${e}`);\r\n }\r\n}\r\n","import { Address, AddressType, BufferUtils, GroupIdType, GroupToken, Networks } from \"libnexa-ts\";\r\nimport type { AssetEntity, NftEntity, TokenEntity } from \"../types/db.types\";\r\nimport { fetchAssetBlob, fetchAssetDoc, getNiftyToken, isNiftySubgroup, transformTokenIconUrl } from \"../utils/asset\";\r\nimport { currentTimestamp, getAddressBuffer, tokenHexToAddr, tokenIdToHex } from \"../utils/common\";\r\nimport { AssetType } from \"../utils/enums\";\r\nimport type { WalletDB } from \"../persistence/wallet-db\";\r\nimport type { RostrumService } from \"./rostrum\";\r\nimport type { WalletCache } from \"./cache\";\r\nimport JSZip from \"jszip\";\r\nimport type { AssetInfo, Balance } from \"../types/wallet.types\";\r\n\r\nexport class AssetService {\r\n\r\n private readonly walletDb: WalletDB;\r\n private readonly rostrumService: RostrumService;\r\n private readonly walletCache: WalletCache;\r\n\r\n constructor(walletDb: WalletDB, rostrumService: RostrumService, walletCache: WalletCache) {\r\n this.walletDb = walletDb;\r\n this.rostrumService = rostrumService;\r\n this.walletCache = walletCache;\r\n }\r\n\r\n public async getTokenInfo(token: string, checkCache = true): Promise<TokenEntity | undefined> {\r\n try {\r\n if (checkCache) {\r\n const cachedToken = await this.walletCache.getTokenById(token);\r\n if (cachedToken) {\r\n return cachedToken;\r\n }\r\n }\r\n\r\n const genesis = await this.rostrumService.getTokenGenesis(token);\r\n const groupId = BufferUtils.hexToBuffer(genesis.token_id_hex);\r\n let parent = \"\";\r\n let iconUrl = \"\";\r\n \r\n if (genesis.op_return_id == GroupIdType.NRC2 || genesis.op_return_id == GroupIdType.NRC3 || isNiftySubgroup(token)) {\r\n return undefined;\r\n }\r\n \r\n if (GroupToken.isSubgroup(groupId)) {\r\n parent = new Address(GroupToken.getParentGroupId(groupId), Networks.defaultNetwork, AddressType.GroupIdAddress).toString();\r\n }\r\n \r\n if (genesis.document_url) {\r\n try {\r\n if (genesis.op_return_id == GroupIdType.NRC1) {\r\n const token_zip = await fetchAssetBlob(genesis.document_url);\r\n const zip = await JSZip.loadAsync(token_zip);\r\n const info = zip.file('info.json');\r\n if (info) {\r\n const infoData = await info.async('string');\r\n const infoJson = JSON.parse(infoData);\r\n iconUrl = transformTokenIconUrl(infoJson[0]?.icon, genesis.document_url);\r\n }\r\n } else {\r\n const infoJson = await fetchAssetDoc(genesis.document_url);\r\n iconUrl = transformTokenIconUrl(infoJson[0]?.icon, genesis.document_url);\r\n }\r\n } catch (e) {\r\n console.error(\"Failed to load metadata\", e)\r\n }\r\n }\r\n \r\n const tokenEntity: TokenEntity = {\r\n token: genesis.group,\r\n tokenIdHex: genesis.token_id_hex,\r\n decimals: genesis.decimal_places ?? 0,\r\n parentGroup: parent,\r\n name: genesis.name ?? \"\",\r\n ticker: genesis.ticker ?? \"\",\r\n iconUrl: iconUrl\r\n };\r\n \r\n return tokenEntity;\r\n } catch (e) {\r\n console.error(e)\r\n return undefined;\r\n }\r\n }\r\n\r\n public async isNftToken(token: string): Promise<boolean> {\r\n try {\r\n if (isNiftySubgroup(token)) {\r\n return true;\r\n }\r\n\r\n const cachedToken = await this.walletCache.getNftById(token);\r\n if (cachedToken) {\r\n return true;\r\n }\r\n\r\n const genesis = await this.rostrumService.getTokenGenesis(token);\r\n if (genesis.op_return_id == GroupIdType.NRC3) {\r\n return true;\r\n }\r\n } catch (e) {\r\n console.error(e)\r\n }\r\n\r\n return false;\r\n }\r\n\r\n public async getAssetInfo(token: string): Promise<AssetInfo | undefined> {\r\n let asset: AssetInfo | undefined = await this.getTokenInfo(token);\r\n if (!asset) {\r\n const isNft = await this.isNftToken(token);\r\n if (isNft) {\r\n asset = {\r\n token: tokenHexToAddr(token),\r\n tokenIdHex: tokenIdToHex(token),\r\n decimals: 0,\r\n };\r\n }\r\n }\r\n return asset;\r\n }\r\n\r\n public async handleNftReceive(accountId: number, tokenIdHex: string, time: number): Promise<void> {\r\n const exist = await this.walletDb.isNftExist(tokenIdHex);\r\n if (exist) {\r\n const asset: AssetEntity = {\r\n accountId: accountId,\r\n tokenIdHex: tokenIdHex,\r\n type: AssetType.NFT,\r\n addedTime: time\r\n }\r\n await this.walletDb.saveAsset(asset, true);\r\n return;\r\n }\r\n\r\n const genesis = await this.rostrumService.getTokenGenesis(tokenIdHex);\r\n if (genesis.op_return_id == GroupIdType.NRC3) {\r\n const groupId = getAddressBuffer(tokenIdHex);\r\n if (GroupToken.isSubgroup(groupId)) {\r\n const parentGroupId = new Address(groupId.subarray(0, 32), Networks.defaultNetwork, AddressType.GroupIdAddress).toString();\r\n const parentGenesis = await this.rostrumService.getTokenGenesis(parentGroupId);\r\n if (parentGenesis?.op_return_id == GroupIdType.NRC2) {\r\n // parent is an NRC-2 collection, this is an NRC-3 NFT. The name of the collection and NRC-3 NFT belongs\r\n // to is the name of the NRC-2 collection.\r\n await this.saveNft(accountId, tokenIdHex, genesis.document_url ?? '', parentGroupId, time, parentGenesis?.name ?? \"\");\r\n }\r\n }\r\n } else if (isNiftySubgroup(tokenIdHex)) {\r\n // NiftyArt does not have collections, pass \"\" for the collection\r\n await this.saveNft(accountId, tokenIdHex, 'nifty', getNiftyToken().token, time, \"\");\r\n }\r\n }\r\n\r\n private async saveNft(account: number, hexId: string, source: string, parent: string, time: number, collection: string): Promise<void> {\r\n if (!source) {\r\n return;\r\n }\r\n\r\n try {\r\n const asset: AssetEntity = {\r\n accountId: account,\r\n tokenIdHex: hexId,\r\n type: AssetType.NFT,\r\n addedTime: time\r\n }\r\n const nftEntity: NftEntity = {\r\n parentGroup: parent,\r\n token: tokenHexToAddr(hexId),\r\n tokenIdHex: hexId,\r\n source: source,\r\n collection: collection\r\n }\r\n\r\n await this.walletDb.saveNft(asset, nftEntity);\r\n } catch (e) {\r\n console.error('failed to save NFT', e);\r\n }\r\n }\r\n\r\n public async fetchAndSaveTokens(accountId: number, tokenBalances: Record<string, Balance>): Promise<void> {\r\n for (const tokenId in tokenBalances) {\r\n const token = await this.getTokenInfo(tokenId);\r\n if (token) {\r\n await this.walletDb.saveToken(accountId, token);\r\n }\r\n }\r\n }\r\n\r\n public async syncNfts(accountId: number, tokensBalance: Record<string, Balance>): Promise<void> {\r\n const currentAssets = Object.keys(tokensBalance);\r\n const internalAssets = await this.walletDb.getLocalNfts(accountId, 1, 1000);\r\n\r\n const handleNftDelete = async (tokenId: string): Promise<void> => {\r\n await this.walletDb.deleteNft(accountId, tokenId, true);\r\n this.walletCache.removeNft(tokenId);\r\n }\r\n\r\n const staleAssets = internalAssets?.filter(a => !currentAssets.includes(a.tokenIdHex)) ?? [];\r\n for (const asset of staleAssets) {\r\n await handleNftDelete(asset.tokenIdHex);\r\n }\r\n\r\n for (const [token, balance] of Object.entries(tokensBalance)) {\r\n const tokenId = tokenIdToHex(token);\r\n const hasBalance = balance && BigInt(balance.confirmed) + BigInt(balance.unconfirmed) > 0n;\r\n const isAssetExist = internalAssets?.some(a => a.tokenIdHex == tokenId);\r\n if ((!hasBalance && !isAssetExist) || (hasBalance && isAssetExist)) {\r\n continue;\r\n }\r\n\r\n const isNft = await this.isNftToken(tokenId);\r\n if (!isNft) {\r\n continue;\r\n }\r\n \r\n if (!hasBalance && isAssetExist) {\r\n await handleNftDelete(tokenId);\r\n } else {\r\n await this.handleNftReceive(accountId, tokenId, currentTimestamp());\r\n }\r\n }\r\n }\r\n}","import type { PrivateKey, PublicKey, Script, UTXO } from \"libnexa-ts\";\r\nimport { Address, AddressType, Transaction, TransactionBuilder, UnitUtils } from \"libnexa-ts\";\r\nimport type { KeyManager } from \"./key\";\r\nimport type { RostrumService } from \"./rostrum\";\r\nimport type { AssetMovement, TransactionDTO, TransactionEntity, TransactionType } from \"../types/db.types\";\r\nimport { currentTimestamp, isNullOrEmpty, isValidNexaAddress, MAX_INT64, tokenAmountToAssetAmount, tokenIdToHex, VAULT_FIRST_BLOCK } from \"../utils/common\";\r\nimport type { WalletDB } from \"../persistence/wallet-db\";\r\nimport type { ITXHistory } from \"../types/rostrum.types\";\r\nimport type { AddressKey } from \"../types/wallet.types\";\r\n\r\nexport interface TxTemplateData {\r\n templateScript: Script;\r\n constraintScript: Script;\r\n visibleArgs: any[];\r\n publicKey: PublicKey;\r\n}\r\n\r\nexport interface TxOptions {\r\n isConsolidate?: boolean;\r\n templateData?: TxTemplateData;\r\n feeFromAmount?: boolean;\r\n}\r\n\r\nexport class TransactionService {\r\n\r\n private readonly rostrumService: RostrumService;\r\n private readonly keyManager: KeyManager;\r\n private readonly walletDb: WalletDB;\r\n\r\n private readonly MAX_INPUTS_OUTPUTS = 250;\r\n\r\n public constructor(rostrumService: RostrumService, keysManager: KeyManager, walletDb: WalletDB) {\r\n this.rostrumService = rostrumService;\r\n this.keyManager = keysManager;\r\n this.walletDb = walletDb;\r\n }\r\n\r\n public async broadcastTransaction(txHex: string): Promise<string> {\r\n return this.rostrumService.broadcast(txHex);\r\n }\r\n\r\n public async fetchTransactionsHistory(address: string, fromHeight: number): Promise<{txs: ITXHistory[], lastHeight: number}> {\r\n let maxHeight = fromHeight;\r\n \r\n const fromHeightFilter = fromHeight > 0 ? fromHeight + 1 : 0;\r\n const txHistory = await this.rostrumService.getTransactionsHistory(address, fromHeightFilter);\r\n \r\n for (const tx of txHistory) {\r\n maxHeight = Math.max(maxHeight, tx.height);\r\n }\r\n \r\n return {txs: txHistory, lastHeight: maxHeight};\r\n }\r\n\r\n public async fetchVaultTransactions(address: string): Promise<TransactionDTO[]> {\r\n const txHistory = await this.rostrumService.getTransactionsHistory(address, VAULT_FIRST_BLOCK);\r\n\r\n const transactions: Promise<TransactionDTO>[] = [];\r\n for (const tx of txHistory) {\r\n const txEntry = this.classifyTransaction(tx.tx_hash, [address]);\r\n transactions.push(txEntry);\r\n }\r\n\r\n return Promise.all(transactions);\r\n }\r\n\r\n public async classifyAndSaveTransaction(accountId: number, txHash: string, myAddresses: string[]): Promise<void> {\r\n const txDto = await this.classifyTransaction(txHash, myAddresses);\r\n txDto.accountId = accountId;\r\n\r\n const txEntity: TransactionEntity = {\r\n ...txDto,\r\n othersOutputs: JSON.stringify(txDto.othersOutputs),\r\n myOutputs: JSON.stringify(txDto.myOutputs),\r\n myInputs: JSON.stringify(txDto.myInputs)\r\n };\r\n\r\n const involvedAssets = new Set<string>();\r\n txDto.myInputs.forEach(m => m.assetId && involvedAssets.add(m.assetId));\r\n txDto.myOutputs.forEach(m => m.assetId && involvedAssets.add(m.assetId));\r\n\r\n for (const assetId of involvedAssets) {\r\n await this.walletDb.addAssetTransaction({\r\n accountId: accountId,\r\n assetId: assetId,\r\n txIdem: txDto.txIdem,\r\n time: txDto.time\r\n });\r\n }\r\n await this.walletDb.addLocalTransaction(txEntity);\r\n }\r\n\r\n private async classifyTransaction(txHash: string, myAddresses: string[]): Promise<TransactionDTO> {\r\n const t = await this.rostrumService.getTransaction(txHash);\r\n\r\n const myInputs: AssetMovement[] = [];\r\n const othersInputs: AssetMovement[] = [];\r\n const myOutputs: AssetMovement[] = [];\r\n const othersOutputs: AssetMovement[] = [];\r\n\r\n for (const vin of t.vin) {\r\n const movement: AssetMovement = {\r\n address: vin.addresses[0],\r\n nexaAmount: vin.value_satoshi.toString(),\r\n assetId: vin.token_id_hex ?? \"\",\r\n assetAmount: tokenAmountToAssetAmount(vin.groupQuantity)\r\n };\r\n if (myAddresses.includes(movement.address)) {\r\n myInputs.push(movement);\r\n } else {\r\n othersInputs.push(movement);\r\n }\r\n }\r\n\r\n for (const vout of t.vout) {\r\n if (isNullOrEmpty(vout.scriptPubKey.addresses)) continue;\r\n const movement: AssetMovement = {\r\n address: vout.scriptPubKey.addresses[0],\r\n nexaAmount: vout.value_satoshi.toString(),\r\n assetId: vout.scriptPubKey.token_id_hex ?? \"\",\r\n assetAmount: tokenAmountToAssetAmount(vout.scriptPubKey.groupQuantity)\r\n };\r\n if (myAddresses.includes(movement.address)) {\r\n myOutputs.push(movement);\r\n } else {\r\n othersOutputs.push(movement);\r\n }\r\n }\r\n\r\n let type: TransactionType;\r\n if (myInputs.length === 0) {\r\n type = 'receive';\r\n } else if (myOutputs.length === 0) {\r\n type = 'send';\r\n } else if (othersInputs.length === 0 && othersOutputs.length === 0) {\r\n type = 'self';\r\n } else if (othersInputs.length === 0 && othersOutputs.length > 0) {\r\n type = 'send';\r\n } else if (othersInputs.length > 0 && othersOutputs.length === 0) {\r\n type = 'receive';\r\n } else {\r\n type = 'swap';\r\n }\r\n\r\n const isConfirmed = t.height > 0;\r\n const txDto: TransactionDTO = {\r\n accountId: 0, // Will be set in classifyAndSaveTransaction\r\n txId: t.txid,\r\n txIdem: t.txidem,\r\n time: isConfirmed ? t.time : currentTimestamp(),\r\n height: isConfirmed ? t.height : 0,\r\n type: type,\r\n fee: t.fee_satoshi.toString(),\r\n othersOutputs: type == 'send' || type == 'swap' ? othersOutputs : [],\r\n myOutputs: myOutputs,\r\n myInputs: myInputs\r\n };\r\n\r\n return txDto;\r\n }\r\n\r\n public async buildAndSignTransferTransaction(\r\n from: AddressKey[],\r\n toAddr: string,\r\n toChange: string,\r\n amount: string,\r\n feeFromAmount?: boolean,\r\n token?: string,\r\n feePerByte?: number,\r\n data?: string\r\n ): Promise<Transaction> {\r\n const txOptions: TxOptions = {\r\n feeFromAmount: feeFromAmount\r\n }\r\n \r\n const txBuilder = this.prepareTransaction(toAddr, amount, token, data);\r\n if (feePerByte) {\r\n txBuilder.feePerByte(feePerByte);\r\n }\r\n\r\n let tokenPrivKeys = new Map<string, PrivateKey>();\r\n if (token) {\r\n tokenPrivKeys = await this.populateTokenInputsAndChange(txBuilder, from, toChange, token, BigInt(amount));\r\n }\r\n const privKeys = await this.populateNexaInputsAndChange(txBuilder, from, toChange, txOptions);\r\n tokenPrivKeys.forEach((v, k) => privKeys.set(k, v));\r\n\r\n return await this.finalizeTransaction(txBuilder, Array.from(privKeys.values()));\r\n }\r\n\r\n public async buildAndSignConsolidateTransaction(from: AddressKey[], toChange: string, templateData?: TxTemplateData): Promise<Transaction> {\r\n const txOptions: TxOptions = {\r\n isConsolidate: true,\r\n templateData: templateData\r\n }\r\n \r\n const txBuilder = new TransactionBuilder();\r\n const privKeys = await this.populateNexaInputsAndChange(txBuilder, from, toChange, txOptions);\r\n \r\n return this.finalizeTransaction(txBuilder, Array.from(privKeys.values()));\r\n }\r\n\r\n private prepareTransaction(toAddr: string, amount: string, token?: string, data?: string): TransactionBuilder {\r\n if (!isValidNexaAddress(toAddr) && !isValidNexaAddress(toAddr, AddressType.PayToPublicKeyHash)) {\r\n throw new Error('Invalid Address.');\r\n }\r\n if ((token && BigInt(amount) < 1n) || (!token && parseInt(amount) < Transaction.DUST_AMOUNT)) {\r\n throw new Error(\"The amount is too low.\");\r\n }\r\n if ((token && BigInt(amount) > MAX_INT64) || (!token && parseInt(amount) > Transaction.MAX_MONEY)) {\r\n throw new Error(\"The amount is too high.\");\r\n }\r\n \r\n const builder = new TransactionBuilder();\r\n if (data) {\r\n builder.addData(data);\r\n }\r\n\r\n if (token) {\r\n if (!isValidNexaAddress(token, AddressType.GroupIdAddress)) {\r\n throw new Error('Invalid Token ID');\r\n }\r\n if (Address.getOutputType(toAddr) === 0) {\r\n throw new Error('Token must be sent to script template address');\r\n }\r\n builder.to(toAddr, Transaction.DUST_AMOUNT, token, BigInt(amount))\r\n } else {\r\n builder.to(toAddr, amount);\r\n }\r\n \r\n return builder;\r\n }\r\n\r\n private async populateNexaInputsAndChange(txBuilder: TransactionBuilder, from: AddressKey[], toChange: string, options: TxOptions): Promise<Map<string, PrivateKey>> {\r\n const allKeys = from.filter(k => BigInt(k.balance.confirmed) + BigInt(k.balance.unconfirmed) > 0n);\r\n if (isNullOrEmpty(allKeys)) {\r\n throw new Error(\"Not enough Nexa balance.\");\r\n }\r\n \r\n const usedKeys = new Map<string, PrivateKey>();\r\n const origAmount = options.isConsolidate ? 0 : Number(txBuilder.transaction.outputs.find(out => out.value > 0n)!.value);\r\n \r\n for (const key of allKeys) {\r\n const utxos = await this.rostrumService.getNexaUtxos(key.address);\r\n for (const utxo of utxos) {\r\n const input: UTXO = {\r\n outpoint: utxo.outpoint_hash,\r\n address: key.address,\r\n satoshis: utxo.value,\r\n templateData: options.templateData\r\n }\r\n txBuilder.from(input);\r\n \r\n if (!usedKeys.has(key.address)) {\r\n const hdkey = this.keyManager.getKey(key.keyPath);\r\n usedKeys.set(key.address, hdkey.privateKey);\r\n }\r\n \r\n if (options.isConsolidate) {\r\n txBuilder.change(toChange);\r\n if (txBuilder.transaction.inputs.length > this.MAX_INPUTS_OUTPUTS) {\r\n return usedKeys;\r\n }\r\n } else {\r\n const tx = txBuilder.transaction;\r\n if (tx.inputs.length > this.MAX_INPUTS_OUTPUTS) {\r\n throw new Error(\"Too many inputs. Consider consolidate transactions or reduce the send amount.\");\r\n }\r\n \r\n const unspent = tx.getUnspentValue();\r\n if (unspent < 0n) {\r\n continue;\r\n }\r\n \r\n if (unspent == 0n && options.feeFromAmount) {\r\n const txFee = tx.estimateRequiredFee();\r\n tx.updateOutputAmount(0, origAmount - txFee);\r\n return usedKeys;\r\n }\r\n \r\n txBuilder.change(toChange);\r\n if (options.feeFromAmount) {\r\n const hasChange = tx.getChangeOutput();\r\n let txFee = tx.estimateRequiredFee();\r\n tx.updateOutputAmount(0, origAmount - txFee);\r\n \r\n // edge case where change added after update\r\n if (!hasChange && tx.getChangeOutput()) {\r\n txFee = tx.estimateRequiredFee();\r\n tx.updateOutputAmount(0, origAmount - txFee);\r\n }\r\n }\r\n \r\n // check again after change output manipulation\r\n if (tx.getUnspentValue() < tx.estimateRequiredFee()) {\r\n // try to add more utxos to satisfy the minimum fee\r\n continue;\r\n }\r\n \r\n return usedKeys;\r\n }\r\n }\r\n }\r\n \r\n if (options.isConsolidate) {\r\n if (usedKeys.size > 0) {\r\n return usedKeys;\r\n }\r\n throw new Error(\"Not enough Nexa balance.\");\r\n }\r\n \r\n const err = {\r\n errorMsg: \"Not enough Nexa balance.\",\r\n amount: UnitUtils.formatNEXA(txBuilder.transaction.outputs[0].value),\r\n fee: UnitUtils.formatNEXA(txBuilder.transaction.estimateRequiredFee())\r\n }\r\n \r\n throw new Error(JSON.stringify(err));\r\n }\r\n\r\n private async populateTokenInputsAndChange(txBuilder: TransactionBuilder, from: AddressKey[], toChange: string, token: string, outTokenAmount: bigint): Promise<Map<string, PrivateKey>> {\r\n const tokenHex = tokenIdToHex(token);\r\n const allKeys = from.filter(k => Object.keys(k.tokensBalance).includes(tokenHex));\r\n \r\n if (isNullOrEmpty(allKeys)) {\r\n throw new Error(\"Not enough token balance.\");\r\n }\r\n \r\n const usedKeys = new Map<string, PrivateKey>();\r\n let inTokenAmount = 0n;\r\n \r\n for (const key of allKeys) {\r\n const utxos = await this.rostrumService.getTokenUtxos(key.address, token);\r\n for (const utxo of utxos) {\r\n if (BigInt(utxo.token_amount) < 0n) {\r\n continue;\r\n }\r\n txBuilder.from({\r\n outpoint: utxo.outpoint_hash,\r\n address: key.address,\r\n satoshis: utxo.value,\r\n groupId: utxo.group,\r\n groupAmount: BigInt(utxo.token_amount),\r\n });\r\n \r\n inTokenAmount = inTokenAmount + BigInt(utxo.token_amount);\r\n if (!usedKeys.has(key.address)) {\r\n const hdkey = this.keyManager.getKey(key.keyPath);\r\n usedKeys.set(key.address, hdkey.privateKey);\r\n }\r\n \r\n if (inTokenAmount > MAX_INT64) {\r\n throw new Error(\"Token inputs exceeded max amount. Consider sending in small chunks\");\r\n }\r\n if (txBuilder.transaction.inputs.length > this.MAX_INPUTS_OUTPUTS) {\r\n throw new Error(\"Too many inputs. Consider consolidating transactions or reduce the send amount.\");\r\n }\r\n \r\n if (inTokenAmount == outTokenAmount) {\r\n return usedKeys;\r\n }\r\n if (inTokenAmount > outTokenAmount) {\r\n // change\r\n txBuilder.to(toChange, Transaction.DUST_AMOUNT, token, inTokenAmount - outTokenAmount);\r\n return usedKeys;\r\n }\r\n }\r\n }\r\n \r\n throw new Error(\"Not enough token balance\");\r\n }\r\n\r\n private async finalizeTransaction(tx: TransactionBuilder, privKeys: PrivateKey[]): Promise<Transaction> {\r\n const tip = await this.rostrumService.getBlockTip();\r\n return tx.lockUntilBlockHeight(tip.height).sign(privKeys).build();\r\n }\r\n\r\n public printTransactionJson(tx?: Transaction | null): string {\r\n if (!tx) {\r\n return \"\";\r\n }\r\n const obj = {\r\n ...tx.toObject(),\r\n hex: tx.toString(),\r\n }\r\n return JSON.stringify(obj, null, 2)\r\n }\r\n}","import { gcm } from \"@noble/ciphers/aes.js\";\r\nimport { argon2idAsync } from \"@noble/hashes/argon2.js\";\r\nimport { generateMnemonic, validateMnemonic } from \"@scure/bip39\";\r\nimport { wordlist } from \"@scure/bip39/wordlists/english.js\";\r\nimport { BufferUtils } from \"libnexa-ts\";\r\n\r\nexport function generateNewMnemonic(size: 12 | 24 = 12): string {\r\n return generateMnemonic(wordlist, size === 24 ? 256 : 128);\r\n}\r\n\r\nexport function isMnemonicValid(mnemonic: string): boolean {\r\n return validateMnemonic(mnemonic, wordlist);\r\n}\r\n\r\nfunction deriveKey(password: string, salt: Uint8Array): Promise<Uint8Array> {\r\n return argon2idAsync(password, salt, { t: 2, m: 19456, p: 1, dkLen: 32 });\r\n}\r\n\r\nexport async function encryptMnemonic(phrase: string, password: string): Promise<string> {\r\n const salt = BufferUtils.getRandomBuffer(16);\r\n const iv = BufferUtils.getRandomBuffer(12);\r\n const data = BufferUtils.utf8ToBuffer(phrase);\r\n\r\n const key = await deriveKey(password, salt);\r\n\r\n const cipher = gcm(key, iv).encrypt(data);\r\n const encBuf = BufferUtils.concat([salt, iv, cipher]);\r\n return BufferUtils.bufferToBase64(encBuf);\r\n}\r\n\r\nasync function decryptMnemonic(encSeed: string, password: string): Promise<string> {\r\n const encBuf = BufferUtils.base64ToBuffer(encSeed);\r\n\r\n const salt = encBuf.subarray(0, 16);\r\n const iv = encBuf.subarray(16, 28);\r\n const cipher = encBuf.subarray(28);\r\n\r\n const key = await deriveKey(password, salt);\r\n\r\n const data = gcm(key, iv).decrypt(cipher);\r\n return BufferUtils.bufferToUtf8(data);\r\n}\r\n\r\nexport async function validateAndDecryptMnemonic(encSeed: string, password: string): Promise<string | false> {\r\n try {\r\n if (encSeed) {\r\n const decMn = await decryptMnemonic(encSeed, password);\r\n if (decMn && isMnemonicValid(decMn)) {\r\n return decMn;\r\n }\r\n }\r\n return false;\r\n } catch {\r\n return false;\r\n }\r\n}","import type { Price } from \"../types/wallet.types\";\r\n\r\nconst currencySymbols = {\r\n usd: \"$\",\r\n eur: \"€\",\r\n gbp: \"£\",\r\n cny: \"¥\",\r\n jpy: \"¥\",\r\n aud: \"A$\",\r\n cad: \"C$\",\r\n chf: \"Fr\"\r\n} as const;\r\n\r\ntype Currency = keyof typeof currencySymbols;\r\n\r\nexport const currencies = Object.keys(currencySymbols);\r\n\r\nexport async function getNexaPrices(): Promise<Record<string, number>> {\r\n const vs_currencies = currencies.join(\",\");\r\n \r\n const res = await fetch(`https://api.coingecko.com/api/v3/simple/price?ids=nexacoin&include_24hr_change=true&vs_currencies=${vs_currencies}`);\r\n if (!res.ok) {\r\n throw new Error(\"Failed to fetch price\");\r\n }\r\n\r\n const data = await res.json();\r\n return data.nexacoin || {};\r\n}\r\n\r\nexport function getCurrencySymbol(currency: Currency): string {\r\n return currencySymbols[currency] || currency;\r\n}\r\n\r\nexport function initializePrices(): Record<string, Price> {\r\n const prices: Record<string, Price> = {};\r\n currencies.forEach(currency => {\r\n prices[currency] = { value: 0, change: 0 };\r\n });\r\n return prices;\r\n}","import type { PublicKey, ScriptElement} from \"libnexa-ts\";\nimport { Address, BNExtended, Hash, Opcode, Script, ScriptOpcode } from \"libnexa-ts\";\r\n\r\nexport function getVaultTemplate(): Script {\r\n return Script.empty()\r\n .add(Opcode.OP_FROMALTSTACK).add(Opcode.OP_DROP)\r\n .add(Opcode.OP_FROMALTSTACK).add(Opcode.OP_CHECKLOCKTIMEVERIFY).add(Opcode.OP_DROP)\r\n .add(Opcode.OP_FROMALTSTACK).add(Opcode.OP_CHECKSIGVERIFY);\r\n}\r\n\r\nexport function getVaultTemplateHash(): Uint8Array {\r\n const template = getVaultTemplate();\r\n return Hash.sha256ripemd160(template.toBuffer());\r\n}\r\n\r\nexport function generateVaultConstraint(pubKey: PublicKey): Script {\r\n return Script.empty().add(pubKey.toBuffer());\r\n}\r\n\r\nexport function getVaultConstraintHash(pubKey: PublicKey): Uint8Array {\r\n const constraint = generateVaultConstraint(pubKey);\r\n return Hash.sha256ripemd160(constraint.toBuffer());\r\n}\r\n\r\nexport function generateVaultVisibleArgs(args: number[]): ScriptElement[] {\r\n return args.map(arg => arg <= 16 ? ScriptOpcode.smallInt(arg) : BNExtended.fromNumber(arg).toScriptNumBuffer());\r\n}\r\n\r\nexport function generateVaultAddress(pubKey: PublicKey, args: number[]): string | undefined {\r\n if (args.length !== 2) {\r\n return undefined;\r\n }\r\n\r\n const templateHash = getVaultTemplateHash();\r\n const constraintHash = getVaultConstraintHash(pubKey);\r\n const visibleArgs = generateVaultVisibleArgs(args);\r\n const address = Address.fromScriptTemplate(templateHash, constraintHash, visibleArgs);\r\n return address.toString();\r\n}","import { DAppProvider } from \"wallet-comms-sdk\";\r\nimport type { SessionInfo, AccountDTO, KeyPath, AppNotification, DappRpcRequest } from \"../types\";\r\nimport type { WalletDB } from \"../persistence\";\r\nimport { AccountType, KeySpace, MAIN_WALLET_ID, SessionRequestType } from \"../utils\";\r\nimport { Networks } from \"libnexa-ts\";\r\nimport type { KeyManager } from \"./key\";\r\n\r\ntype MethodHandler = {\r\n resolve: (value: any) => void;\r\n reject: (value: any) => void;\r\n}\r\n\r\nexport type SessionEvent =\r\n | { type: 'session_added'; accountId: number; sessionInfo: SessionInfo }\r\n | { type: 'session_removed'; accountId: number; sessionId: string }\r\n | { type: 'sessions_cleared', accountId: number }\r\n | { type: 'new_notification'; notification: AppNotification }\r\n | { type: 'new_request'; request: DappRpcRequest };\r\n\r\nexport type SessionUpdateCallback = (event: SessionEvent) => void;\r\n\r\nexport class SessionManager {\r\n\r\n private readonly walletDb: WalletDB;\r\n private readonly keyManager: KeyManager;\r\n\r\n private readonly providers: Map<number, Map<string, DAppProvider>>;\r\n private readonly handlers: Map<string, MethodHandler>;\r\n\r\n private removeOnClose: boolean;\r\n\r\n private updateCallback?: SessionUpdateCallback;\r\n \r\n public constructor(walletDb: WalletDB, keyManager: KeyManager) {\r\n this.walletDb = walletDb;\r\n this.keyManager = keyManager;\r\n this.providers = new Map();\r\n this.handlers = new Map();\r\n this.removeOnClose = true;\r\n }\r\n\r\n public onUpdate(callback: SessionUpdateCallback): void {\r\n this.updateCallback = callback;\r\n }\r\n\r\n private notify(event: SessionEvent): void {\r\n this.updateCallback?.(event);\r\n }\r\n\r\n public getHandler(request: string): MethodHandler | undefined {\r\n return this.handlers.get(request);\r\n }\r\n\r\n public add(account: AccountDTO, provider: DAppProvider, sessionInfo: SessionInfo): void {\r\n if (!this.providers.has(account.id)) {\r\n this.providers.set(account.id, new Map());\r\n }\r\n\r\n const sessionId = sessionInfo.details.sessionId;\r\n const accountSessions = this.providers.get(account.id)!;\r\n\r\n this.registerHandlers(account, provider, sessionId);\r\n accountSessions.set(sessionId, provider);\r\n this.notify({ type: 'session_added', accountId: account.id, sessionInfo });\r\n }\r\n\r\n public remove(accountId: number, sessionId: string): void {\r\n const sessionMap = this.providers.get(accountId);\r\n if (sessionMap) {\r\n const provider = sessionMap.get(sessionId);\r\n if (provider) {\r\n provider.disconnect();\r\n sessionMap.delete(sessionId);\r\n }\r\n if (sessionMap.size === 0) {\r\n this.providers.delete(accountId);\r\n }\r\n }\r\n this.notify({ type: 'session_removed', accountId, sessionId });\r\n }\r\n\r\n public async reload(accounts: Map<number, AccountDTO>): Promise<void> {\r\n for (const account of accounts.values()) {\r\n if (account.id == MAIN_WALLET_ID) {\r\n continue;\r\n }\r\n const storedSessions = await this.walletDb.getAccountSessions(account.id);\r\n const currentSessions = this.providers.get(account.id);\r\n\r\n const loadedSessions = storedSessions.map(async (session) => {\r\n if (currentSessions?.has(session.sessionId)) {\r\n return;\r\n }\r\n\r\n let provider;\r\n try {\r\n provider = new DAppProvider(session.uri);\r\n const details = provider.getSessionInfo();\r\n await provider.connect(3000);\r\n const appInfo = await provider.getAppInfo(2000);\r\n await provider.joinSession(account.address, 2000);\r\n const messages = await provider.fetchPendingMessages();\r\n for (const msg of messages) {\r\n this.notify({\r\n type: 'new_notification',\r\n notification: {\r\n id: crypto.randomUUID(),\r\n createdAt: msg.createdAt,\r\n type: 'web3',\r\n title: 'Request pending approval',\r\n message: `A connected dApp (${appInfo.name}) has requested an action from your Account: ${account.name}. Review the request details before approving or rejecting.`,\r\n action: {\r\n type: 'DAPP_REQUEST',\r\n account: account.id,\r\n sessionId: details.sessionId,\r\n payload: msg.message\r\n }\r\n }\r\n });\r\n }\r\n return { account: account, provider, metadata: { details, appInfo } };\r\n } catch (error) {\r\n console.error(`Failed to reload session ${session.sessionId}`, error);\r\n provider?.disconnect();\r\n await this.walletDb.removeSession(session.sessionId);\r\n }\r\n });\r\n\r\n const results= await Promise.allSettled(loadedSessions);\r\n for (const result of results) {\r\n if (result.status === 'fulfilled' && result.value) {\r\n this.add(result.value.account, result.value.provider, result.value.metadata);\r\n }\r\n }\r\n }\r\n }\r\n \r\n public clear(): void {\r\n try {\r\n this.removeOnClose = false;\r\n for (const [accountId, sessions] of this.providers) {\r\n for (const [,provider] of sessions) {\r\n provider.disconnect();\r\n }\r\n sessions.clear();\r\n this.notify({ type: 'sessions_cleared', accountId });\r\n }\r\n this.providers.clear();\r\n } finally {\r\n this.removeOnClose = true;\r\n }\r\n }\r\n\r\n public async revoke(accountId: number, sessionId: string): Promise<void> {\r\n const sessionMap = this.providers.get(accountId);\r\n if (sessionMap) {\r\n const provider = sessionMap.get(sessionId);\r\n if (provider) {\r\n await provider.revokeSession();\r\n }\r\n }\r\n }\r\n\r\n public async replayMessage(accountId: number, sessionId: string, payload: string): Promise<void> {\r\n const sessionMap = this.providers.get(accountId);\r\n if (sessionMap) {\r\n const provider = sessionMap.get(sessionId);\r\n if (provider) {\r\n await provider.replayMessage(payload);\r\n }\r\n }\r\n }\r\n\r\n private registerHandlers(account: AccountDTO, provider: DAppProvider, sessionId: string): void {\r\n provider.onSessionDelete((): Promise<void> => {\r\n return this.walletDb.removeSession(sessionId);\r\n });\r\n\r\n provider.onClose((): void => {\r\n if (this.removeOnClose) {\r\n this.remove(account.id, sessionId);\r\n }\r\n });\r\n\r\n const handleRequest = <T>(type: SessionRequestType, request: unknown): Promise<T> => {\r\n return new Promise<T>((resolve, reject) => {\r\n this.handlers.set(type, { resolve, reject });\r\n this.notify({ type: 'new_request', request: { type, accountId: account.id, sessionId, request } });\r\n });\r\n }\r\n\r\n provider.onSignMessage(signMsgReq => {\r\n return handleRequest(SessionRequestType.SignMessage, signMsgReq);\r\n });\r\n\r\n provider.onAddToken(addTokenReq => {\r\n return handleRequest(SessionRequestType.AddToken, addTokenReq);\r\n });\r\n\r\n provider.onSendTransaction(sendTransactionReq => {\r\n return handleRequest(SessionRequestType.SendTransaction, sendTransactionReq);\r\n });\r\n\r\n provider.onSignTransaction(signTransactionReq => {\r\n return handleRequest(SessionRequestType.SignTransaction, signTransactionReq);\r\n });\r\n\r\n provider.onGetAccount(() => {\r\n const path: KeyPath = { account: AccountType.DAPP, type: KeySpace.RECEIVE, index: account.id };\r\n return {\r\n name: account.name,\r\n address: account.address,\r\n pubkey: this.keyManager.getKey(path).publicKey.toString(),\r\n blockchain: \"nexa\",\r\n network: Networks.defaultNetwork.name,\r\n capabilities: {\r\n addToken: true,\r\n sendTransaction: true,\r\n signMessage: true,\r\n signTransaction: true\r\n }\r\n }\r\n });\r\n }\r\n}","import type { Input, PrivateKey} from \"libnexa-ts\";\r\nimport { BufferUtils, Hash, Opcode, Output, OutputSighashType, Script, ScriptFactory, SighashType, Transaction, TxSigner } from \"libnexa-ts\";\r\nimport type { KeyManager } from \"./key\";\r\nimport type { RostrumService } from \"./rostrum\";\r\nimport type { AddressKey, AssetMovement, MovementDetails, TransactionDetails } from \"../types\";\r\nimport { tokenAmountToAssetAmount, tokenIdToHex } from \"../utils\";\r\nimport type { AssetService } from \"./asset\";\r\n\r\ninterface TransactionContext {\r\n address: string;\r\n privateKey: PrivateKey;\r\n txDetails: TransactionDetails;\r\n myInputs: Map<number, AssetMovement>;\r\n myOutputs: Map<number, AssetMovement>;\r\n involvedAssets: Set<string>;\r\n inputsToSign: Set<number>;\r\n coveredOutputs: Set<number>;\r\n allMyOutputsCovered: boolean;\r\n}\r\n\r\nexport class TransactionTransformer {\r\n\r\n private readonly rostrumService: RostrumService;\r\n private readonly keyManager: KeyManager;\r\n private readonly assetService: AssetService;\r\n\r\n public constructor(rostrumService: RostrumService, keyManager: KeyManager, assetService: AssetService) {\r\n this.rostrumService = rostrumService;\r\n this.keyManager = keyManager;\r\n this.assetService = assetService;\r\n }\r\n\r\n public async transformRawTransaction(hex: string, addressKey: AddressKey): Promise<TransactionDetails> {\r\n const context = this.createContext(hex, addressKey);\r\n\r\n await this.processInputs(context);\r\n this.processOutputs(context);\r\n this.signInputs(context);\r\n await this.processAssetMovements(context);\r\n\r\n return context.txDetails;\r\n }\r\n\r\n private createContext(hex: string, addressKey: AddressKey): TransactionContext {\r\n try {\r\n return {\r\n address: addressKey.address,\r\n privateKey: this.keyManager.getKey(addressKey.keyPath).privateKey,\r\n txDetails: {\r\n tx: new Transaction(hex),\r\n send: [],\r\n receive: []\r\n },\r\n myInputs: new Map<number, AssetMovement>(),\r\n myOutputs: new Map<number, AssetMovement>(),\r\n involvedAssets: new Set<string>(),\r\n inputsToSign: new Set<number>(),\r\n coveredOutputs: new Set<number>(),\r\n allMyOutputsCovered: false,\r\n };\r\n } catch {\r\n throw new Error(\"Invalid transaction format.\");\r\n }\r\n }\r\n\r\n private async processInputs(context: TransactionContext): Promise<void> {\r\n const promises = [];\r\n for (let i = 0; i < context.txDetails.tx.inputs.length; i++) {\r\n const p = this.processInput(context, i);\r\n promises.push(p);\r\n }\r\n await Promise.all(promises);\r\n }\r\n\r\n private async processInput(context: TransactionContext, index: number): Promise<void> {\r\n const input = context.txDetails.tx.inputs[index];\r\n const utxo = await this.rostrumService.getUtxo(BufferUtils.bufferToHex(input.outpoint));\r\n if (utxo.status == \"spent\") {\r\n throw new Error(\"Input UTXO is already spent.\");\r\n }\r\n\r\n input.output = new Output(utxo.amount, utxo.scriptpubkey);\r\n if (input.output.address == context.address) {\r\n const assetId = utxo.token_id_hex || \"NEXA\";\r\n context.myInputs.set(index, {\r\n address: context.address,\r\n nexaAmount: utxo.amount.toString(),\r\n assetId: assetId,\r\n assetAmount: tokenAmountToAssetAmount(utxo.group_quantity) || utxo.amount.toString()\r\n });\r\n context.involvedAssets.add(assetId);\r\n \r\n if (input.scriptSig.isEmpty()) {\r\n context.inputsToSign.add(index);\r\n }\r\n }\r\n\r\n if (input.scriptSig.findPlaceholder() > 0) {\r\n context.inputsToSign.add(index);\r\n }\r\n }\r\n\r\n private processOutputs(context: TransactionContext): void {\r\n for (let i = 0; i < context.txDetails.tx.outputs.length; i++) {\r\n const output = context.txDetails.tx.outputs[i].toObject();\r\n if (output.address !== context.address) {\r\n continue;\r\n }\r\n\r\n const assetId = output.groupId ? tokenIdToHex(output.groupId) : \"NEXA\";\r\n const movement = {\r\n address: output.address,\r\n nexaAmount: output.value.toString(),\r\n assetId: assetId,\r\n assetAmount: tokenAmountToAssetAmount(output.groupAmount) || output.value.toString()\r\n };\r\n\r\n context.involvedAssets.add(assetId);\r\n context.myOutputs.set(i, movement);\r\n }\r\n }\r\n\r\n private signInputs(context: TransactionContext): void {\r\n if (context.inputsToSign.size == 0) {\r\n throw new Error(\"No inputs to sign.\");\r\n }\r\n\r\n for (const index of context.inputsToSign) {\r\n const input = context.txDetails.tx.inputs[index];\r\n const subscript = this.validateAndGetSubscript(input);\r\n\r\n if (input.scriptSig.isEmpty()) { // only p2pkt can be empty\r\n context.allMyOutputsCovered = true;\r\n const txSig = TxSigner.sign(context.txDetails.tx, index, SighashType.ALL, subscript, context.privateKey).toTxFormat();\r\n const constraint = Script.empty().add(context.privateKey.publicKey.toBuffer());\r\n input.scriptSig = ScriptFactory.buildScriptTemplateIn(undefined, constraint, Script.empty().add(txSig))\r\n } else {\r\n const placeholderIndex = input.scriptSig.findPlaceholder();\r\n const placeholder = input.scriptSig.chunks[placeholderIndex];\r\n const sigHashBuf = placeholder.buf!.subarray(64);\r\n const sigHashType = SighashType.fromBuffer(sigHashBuf);\r\n this.processSignatureCoverage(context, sigHashType);\r\n\r\n const txSig = TxSigner.sign(context.txDetails.tx, index, sigHashType, subscript, context.privateKey).toTxFormat(sigHashBuf);\r\n input.scriptSig.replaceChunk(placeholderIndex, Script.empty().add(txSig));\r\n }\r\n }\r\n\r\n if (!context.allMyOutputsCovered) {\r\n throw new Error(\"Some of interested outputs are not covered by signatures.\");\r\n }\r\n }\r\n\r\n private validateAndGetSubscript(input: Input): Script {\r\n if (input.output!.scriptPubKey.isPublicKeyTemplateOut()) {\r\n if (input.scriptSig.isEmpty() || input.scriptSig.isPublicKeyTemplateIn()) {\r\n return Script.empty().add(Opcode.OP_FROMALTSTACK).add(Opcode.OP_CHECKSIGVERIFY);\r\n }\r\n throw new Error(\"Invalid input script type.\");\r\n }\r\n \r\n if (input.output!.scriptPubKey.isScriptTemplateOut()) {\r\n if (!input.scriptSig.isScriptTemplateIn()) {\r\n throw new Error(\"Unsupported input script type.\");\r\n }\r\n\r\n const templateHash = input.output!.scriptPubKey.getTemplateHash() as Uint8Array;\r\n const templateBuf = input.scriptSig.chunks[0].buf!;\r\n if (BufferUtils.equals(templateHash, Hash.sha256ripemd160(templateBuf)) || BufferUtils.equals(templateHash, Hash.sha256sha256(templateBuf))) {\r\n return Script.fromBuffer(templateBuf);\r\n }\r\n\r\n throw new Error(\"Invalid input script template.\");\r\n }\r\n \r\n throw new Error(\"Unsupported prevout script type.\");\r\n }\r\n\r\n private processSignatureCoverage(context: TransactionContext, sigHashType: SighashType): void {\r\n if (context.allMyOutputsCovered) {\r\n return;\r\n }\r\n\r\n if (sigHashType.outType == OutputSighashType.TWO) {\r\n context.coveredOutputs.add(sigHashType.outData[0]);\r\n context.coveredOutputs.add(sigHashType.outData[1]);\r\n this.checkSignatureCoverage(context);\r\n } else if (sigHashType.outType == OutputSighashType.FIRSTN) {\r\n const n = sigHashType.outData[0];\r\n for (let i = 0; i < n; i++) {\r\n context.coveredOutputs.add(i);\r\n }\r\n this.checkSignatureCoverage(context);\r\n } else {\r\n context.allMyOutputsCovered = true;\r\n }\r\n }\r\n\r\n private checkSignatureCoverage(context: TransactionContext): void {\r\n if (context.allMyOutputsCovered) {\r\n return;\r\n }\r\n\r\n for (const i of context.myOutputs.keys()) {\r\n if (!context.coveredOutputs.has(i)) {\r\n return;\r\n }\r\n }\r\n context.allMyOutputsCovered = true;\r\n }\r\n\r\n private async processAssetMovements(context: TransactionContext): Promise<void> {\r\n const myInputs = Array.from(context.myInputs.values());\r\n const myOutputs = Array.from(context.myOutputs.values());\r\n\r\n const promises = [];\r\n for (const assetId of context.involvedAssets) {\r\n const p = this.processAssetMovement(context, assetId, myInputs, myOutputs);\r\n promises.push(p);\r\n }\r\n await Promise.all(promises);\r\n }\r\n\r\n private async processAssetMovement(context: TransactionContext, assetId: string, myInputs: AssetMovement[], myOutputs: AssetMovement[]): Promise<void> {\r\n const sentAmount = myInputs\r\n .reduce((sum, m) => m.assetId === assetId ? sum + BigInt(m.assetAmount) : sum, 0n);\r\n\r\n const receivedAmount = myOutputs\r\n .reduce((sum, m) => m.assetId === assetId ? sum + BigInt(m.assetAmount) : sum, 0n);\r\n\r\n if (sentAmount > 0n || receivedAmount > 0n) {\r\n const movement: MovementDetails = { amount: receivedAmount - sentAmount };\r\n if (assetId !== \"NEXA\") {\r\n movement.asset = await this.assetService.getAssetInfo(assetId);\r\n }\r\n\r\n if (movement.amount > 0n) {\r\n context.txDetails.receive.push(movement);\r\n } else if (movement.amount < 0n) {\r\n context.txDetails.send.push(movement);\r\n }\r\n }\r\n }\r\n}","import { Address, BNExtended, BufferWriter, Script, ScriptOpcode } from \"libnexa-ts\";\r\nimport type { VaultDTO } from \"../types\";\r\nimport { AccountType, generateVaultAddress, KeySpace } from \"../utils\";\r\nimport type { KeyManager } from \"./key\";\r\nimport type { RostrumService } from \"./rostrum\";\r\n\r\nconst HODL_FIRST_BLOCK = 274710;\r\nconst HODL_SCRIPT_PREFIX = \"0014461ad25081cb0119d034385ff154c8d3ad6bdd76\";\r\n\r\nexport class WalletDiscoveryService {\r\n\r\n private readonly rostrumService: RostrumService;\r\n private readonly keyManager: KeyManager;\r\n\r\n public constructor(rostrumService: RostrumService, keyManager: KeyManager) {\r\n this.rostrumService = rostrumService;\r\n this.keyManager = keyManager;\r\n }\r\n\r\n public async discoverWalletIndex(type: AccountType, keySpace: KeySpace): Promise<number> {\r\n let index = 0, stop = false, addrBatch = 0;\r\n \r\n do {\r\n stop = true;\r\n for (let i = addrBatch; i < addrBatch+20; i++) {\r\n const keyPath = { account: type, type: keySpace, index: i };\r\n const rAddr = this.keyManager.getKey(keyPath).privateKey.toAddress().toString();\r\n const isUsed = await this.rostrumService.isAddressUsed(rAddr);\r\n if (isUsed) {\r\n index = i;\r\n stop = false;\r\n }\r\n }\r\n addrBatch += 20;\r\n } while (!stop);\r\n \r\n return index;\r\n }\r\n\r\n public async discoverVaults(addresses: string[]): Promise<Map<string, VaultDTO>> {\r\n const vaultsPromises: Promise<Set<string>>[] = [];\r\n for (const address of addresses) {\r\n const p = this.checkVaultsForAddress(address);\r\n vaultsPromises.push(p);\r\n }\r\n\r\n const res = await Promise.all(vaultsPromises);\r\n const vaults = new Map<string, VaultDTO>();\r\n\r\n res.forEach(set => {\r\n set.forEach(hex => {\r\n const vault = this.parseVaultDetails(hex);\r\n if (vault) {\r\n vaults.set(vault.address, vault);\r\n }\r\n });\r\n });\r\n\r\n return vaults;\r\n }\r\n\r\n private async checkVaultsForAddress(address: string): Promise<Set<string>> {\r\n const vaults = new Set<string>();\r\n\r\n const history = await this.rostrumService.getTransactionsHistory(address, HODL_FIRST_BLOCK);\r\n for (const txHistory of history) {\r\n const tx = await this.rostrumService.getTransaction(txHistory.tx_hash);\r\n const hodls = tx.vout.filter(out => out.scriptPubKey.hex.startsWith(HODL_SCRIPT_PREFIX));\r\n for (const hodl of hodls) { \r\n vaults.add(hodl.scriptPubKey.hex);\r\n }\r\n }\r\n \r\n return vaults;\r\n }\r\n\r\n private parseVaultDetails(hex: string): VaultDTO | undefined {\r\n const scirptTemplate = Script.fromHex(hex);\r\n const buf = new BufferWriter().writeVarLengthBuf(scirptTemplate.toBuffer()).toBuffer();\r\n const actualAddress = new Address(buf).toString();\r\n\r\n const args = scirptTemplate.getVisibleArgs();\r\n\r\n const block = BNExtended.fromScriptNumBuffer(args.chunks[0].buf!).toNumber();\r\n const index = ScriptOpcode.isSmallIntOp(args.chunks[1].opcodenum)\r\n ? ScriptOpcode.decodeOP_N(args.chunks[1].opcodenum)\r\n : BNExtended.fromScriptNumBuffer(args.chunks[1].buf!).toNumber();\r\n\r\n const visibleArgs = [block, index];\r\n const key = this.keyManager.getKey({ account: AccountType.VAULT, type: KeySpace.RECEIVE, index: index });\r\n const expectedAddress = generateVaultAddress(key.publicKey, visibleArgs);\r\n\r\n if (actualAddress != expectedAddress) {\r\n return undefined;\r\n }\r\n\r\n const dto: VaultDTO = {\r\n address: actualAddress,\r\n block: block,\r\n idx: index,\r\n statusHash: '',\r\n balance: { confirmed: \"0\", unconfirmed: \"0\" },\r\n tokensBalance: {},\r\n height: 0,\r\n type: AccountType.VAULT\r\n }\r\n\r\n return dto;\r\n }\r\n}","import type { KVStore, WalletDB } from \"../persistence\";\r\nimport type { Account, AccountDTO, AddressDTO, AddressKey, Balance, ITXHistory, RostrumParams, VaultDTO, VaultInfo } from \"../types\";\r\nimport { AccountType, keyPathToString, KeySpace, MAIN_WALLET_ID, sumBalance, sumTokensBalance } from \"../utils\";\r\nimport type { AssetService } from \"./asset\";\r\nimport { WalletDiscoveryService } from \"./discovery\";\r\nimport type { KeyManager } from \"./key\";\r\nimport type { RostrumService } from \"./rostrum\";\r\nimport type { SessionManager } from \"./session\";\r\nimport type { TransactionService } from \"./transaction\";\r\n\r\ntype WalletAddress = AccountDTO | AddressDTO | VaultDTO;\r\n\r\ninterface AddressHistory {\r\n address: WalletAddress;\r\n txs: ITXHistory[];\r\n}\r\n\r\ninterface UpdateInfo {\r\n address: WalletAddress;\r\n result: string\r\n}\r\n\r\nexport type WalletEvent =\r\n | { type: 'new_tip'; tip: number; }\r\n | { type: 'new_account'; account: Account; }\r\n | { type: 'new_vault'; vault: VaultInfo; }\r\n | { type: 'discover_wallet'; loading: boolean; }\r\n | { type: 'load_wallet'; loading: boolean; }\r\n | { type: 'sync_wallet'; loading: boolean; }\r\n | { type: 'account_balance_updated'; accountId: number; balance: Balance, tokensBalance: Record<string, Balance>; }\r\n | { type: 'vault_balance_updated'; address: string, balance: Balance; }\r\n | { type: 'main_address_updated'; address: string; };\r\n\r\nexport type WalletUpdateCallback = (event: WalletEvent) => void;\r\n\r\nexport class WalletManager {\r\n\r\n private static readonly GAP_LIMIT = 20;\r\n private static readonly DEBOUNCE_MS = 1000;\r\n\r\n private addressResolvers: Map<string, () => void>;\r\n\r\n public accounts: Map<number, AccountDTO>;\r\n public accountsAddressToId: Map<string, number>;\r\n\r\n public receiveAddresses: AddressDTO[];\r\n public changeAddresses: AddressDTO[];\r\n\r\n public vaults: Map<string, VaultDTO>;\r\n\r\n private pendingUpdates: Map<string, UpdateInfo>;\r\n private updateTimer?: number;\r\n\r\n private updateCallback?: WalletUpdateCallback;\r\n\r\n private readonly discoveryService: WalletDiscoveryService;\r\n\r\n public constructor(\r\n private readonly keyManager: KeyManager,\r\n private readonly kvStore: KVStore,\r\n private readonly walletDb: WalletDB,\r\n private readonly rostrumService: RostrumService,\r\n private readonly assetService: AssetService,\r\n private readonly transactionService: TransactionService,\r\n private readonly sessionManager: SessionManager,\r\n ) {\r\n this.discoveryService = new WalletDiscoveryService(this.rostrumService, this.keyManager);\r\n this.accounts = new Map();\r\n this.accountsAddressToId = new Map();\r\n this.receiveAddresses = [];\r\n this.changeAddresses = [];\r\n this.vaults = new Map();\r\n this.pendingUpdates = new Map();\r\n this.addressResolvers = new Map();\r\n }\r\n\r\n public onUpdate(callback: WalletUpdateCallback): void {\r\n this.updateCallback = callback;\r\n }\r\n\r\n private notify(event: WalletEvent): void {\r\n this.updateCallback?.(event);\r\n }\r\n\r\n private getAllAddresses(): WalletAddress[] {\r\n return [...this.receiveAddresses, ...this.changeAddresses, ...this.accounts.values(), ...this.vaults.values()];\r\n }\r\n\r\n public getMainAddresses(): AddressDTO[] {\r\n return [...this.receiveAddresses, ...this.changeAddresses];\r\n }\r\n\r\n public getReceiveAddress(): string {\r\n return this.receiveAddresses.find(addr => !addr.used)!.address;\r\n }\r\n\r\n public getChangeAddress(accountId = MAIN_WALLET_ID): string {\r\n if (accountId != MAIN_WALLET_ID) {\r\n return this.accounts.get(accountId)!.address;\r\n }\r\n return this.changeAddresses.find(addr => !addr.used)!.address;\r\n }\r\n\r\n public getUsedAddressKeys(accountId = MAIN_WALLET_ID): AddressKey[] {\r\n if (accountId != MAIN_WALLET_ID) {\r\n const account = this.accounts.get(accountId)!;\r\n return [{\r\n address: account.address,\r\n keyPath: keyPathToString(AccountType.DAPP, 0, account.id),\r\n balance: account.balance,\r\n tokensBalance: account.tokensBalance\r\n }];\r\n }\r\n\r\n return this.getMainAddresses().filter(addr => addr.used).map(addr => ({\r\n address: addr.address,\r\n keyPath: keyPathToString(AccountType.MAIN, addr.space, addr.idx),\r\n balance: addr.balance,\r\n tokensBalance: addr.tokensBalance\r\n }));\r\n }\r\n\r\n public async reloadRostrum(params: RostrumParams): Promise<void> {\r\n await this.kvStore.saveRostrumParams(params);\r\n await this.rostrumService.disconnect(true);\r\n await this.initRostrum();\r\n await this.subscribeAddresses(this.getAllAddresses())\r\n }\r\n\r\n public async initRostrum(): Promise<void> {\r\n await this.rostrumService.connect();\r\n await this.rostrumService.subscribeHeaders(tip => this.notify({ type: 'new_tip', tip }));\r\n }\r\n\r\n public async initialize(): Promise<void> {\r\n await this.initRostrum();\r\n\r\n const isExist = await this.walletDb.countAddresses();\r\n if (isExist) {\r\n await this.loadWallet();\r\n } else {\r\n await this.discoverWallet();\r\n }\r\n }\r\n\r\n private async discoverWallet(): Promise<void> {\r\n this.notify({ type: 'discover_wallet', loading: true });\r\n\r\n const rIndexPromise = this.discoveryService.discoverWalletIndex(AccountType.MAIN, KeySpace.RECEIVE);\r\n const cIndexPromise = this.discoveryService.discoverWalletIndex(AccountType.MAIN, KeySpace.CHANGE);\r\n const dappIndexPromis = this.discoveryService.discoverWalletIndex(AccountType.DAPP, KeySpace.RECEIVE);\r\n \r\n const [rIndex, cIndex, dappIndex] = await Promise.all([rIndexPromise, cIndexPromise, dappIndexPromis]);\r\n\r\n this.receiveAddresses = this.deriveAddresses(KeySpace.RECEIVE, 0, rIndex + WalletManager.GAP_LIMIT);\r\n this.changeAddresses = this.deriveAddresses(KeySpace.CHANGE, 0, cIndex + WalletManager.GAP_LIMIT);\r\n this.accounts = this.deriveAccounts(0, dappIndex + 1);\r\n this.accounts.forEach(entry => this.accountsAddressToId.set(entry.address, entry.id));\r\n\r\n await this.saveAddresses(this.receiveAddresses);\r\n await this.saveAddresses(this.changeAddresses);\r\n await this.saveAccounts(this.accounts);\r\n\r\n this.initState();\r\n\r\n await this.initialSync();\r\n\r\n this.notify({ type: 'discover_wallet', loading: false });\r\n this.notify({ type: 'load_wallet', loading: false });\r\n\r\n await this.rescanVaults();\r\n }\r\n\r\n private async loadWallet(): Promise<void> {\r\n this.receiveAddresses = await this.walletDb.getReceiveAddresses();\r\n this.changeAddresses = await this.walletDb.getChangeAddresses();\r\n\r\n const accs = await this.walletDb.getAccounts();\r\n this.accounts = new Map(accs.map(a => [a.id, a]));\r\n this.accountsAddressToId = new Map(accs.map(a => [a.address, a.id]));\r\n\r\n const vaults = await this.walletDb.getVaults();\r\n this.vaults = new Map(vaults.map(v => [v.address, v]));\r\n\r\n this.initState();\r\n\r\n this.notify({ type: 'load_wallet', loading: false });\r\n\r\n await this.reconnectSync();\r\n }\r\n\r\n private async initialSync(): Promise<void> {\r\n await this.subscribeAddresses(this.getAllAddresses(), true);\r\n\r\n const tokensLoadPromises: Promise<void>[] = [];\r\n tokensLoadPromises.push(this.assetService.fetchAndSaveTokens(MAIN_WALLET_ID, sumTokensBalance(this.getMainAddresses().map(a => a.tokensBalance))));\r\n for (const account of this.accounts.values()) {\r\n tokensLoadPromises.push(this.assetService.fetchAndSaveTokens(account.id, account.tokensBalance));\r\n }\r\n\r\n await Promise.all(tokensLoadPromises);\r\n }\r\n\r\n public async reconnectSync(): Promise<void> {\r\n await Promise.all([\r\n this.sessionManager.reload(this.accounts),\r\n this.subscribeAddresses(this.getAllAddresses())\r\n ]);\r\n }\r\n\r\n private initState(): void {\r\n const walletAddresses = this.getMainAddresses();\r\n\r\n this.notify({\r\n type: 'new_account',\r\n account: {\r\n id: MAIN_WALLET_ID,\r\n name: 'Main Wallet',\r\n address: this.getReceiveAddress(),\r\n balance: sumBalance(walletAddresses.map(a => a.balance)),\r\n tokensBalance: sumTokensBalance(walletAddresses.map(a => a.tokensBalance)),\r\n tokens: [],\r\n sessions: {}\r\n }\r\n });\r\n\r\n for (const account of this.accounts.values()) {\r\n this.notify({\r\n type: 'new_account',\r\n account: {\r\n id: account.id,\r\n name: account.name,\r\n address: account.address,\r\n balance: account.balance,\r\n tokensBalance: account.tokensBalance,\r\n tokens: [],\r\n sessions: {}\r\n }\r\n });\r\n }\r\n\r\n for (const vault of this.vaults.values()) {\r\n this.notify({\r\n type: 'new_vault',\r\n vault: {\r\n address: vault.address,\r\n balance: vault.balance,\r\n block: vault.block,\r\n index: vault.idx\r\n }\r\n });\r\n }\r\n }\r\n\r\n private deriveAddresses(space: KeySpace, startIndex: number, count: number): AddressDTO[] {\r\n const newAddresses: AddressDTO[] = [];\r\n for (let i = startIndex; i < startIndex + count; i++) {\r\n const path = keyPathToString(AccountType.MAIN, space, i);\r\n const address = this.keyManager.getKey(path).privateKey.toAddress().toString();\r\n\r\n const addressDTO: AddressDTO = {\r\n address: address,\r\n space: space,\r\n idx: i,\r\n used: false,\r\n height: 0,\r\n statusHash: '',\r\n balance: { confirmed: \"0\", unconfirmed: \"0\" },\r\n tokensBalance: {},\r\n type: AccountType.MAIN\r\n };\r\n\r\n newAddresses.push(addressDTO);\r\n }\r\n\r\n return newAddresses;\r\n }\r\n\r\n private deriveAccounts(startIndex: number, count: number): Map<number, AccountDTO> {\r\n const newAccounts = new Map<number, AccountDTO>();\r\n for (let i = startIndex; i < startIndex + count; i++) {\r\n const path = keyPathToString(AccountType.DAPP, 0, i);\r\n const address = this.keyManager.getKey(path).privateKey.toAddress().toString();\r\n\r\n const account: AccountDTO = {\r\n id: i,\r\n name: `Account ${i + 1}`,\r\n address: address,\r\n height: 0,\r\n hidden: 0,\r\n statusHash: '',\r\n balance: { confirmed: \"0\", unconfirmed: \"0\" },\r\n tokensBalance: {},\r\n type: AccountType.DAPP\r\n };\r\n\r\n newAccounts.set(account.id, account);\r\n }\r\n\r\n return newAccounts;\r\n }\r\n\r\n private async saveAddresses(addresses: AddressDTO[]): Promise<void> {\r\n for (const addr of addresses) {\r\n await this.walletDb.saveAddress(addr);\r\n }\r\n }\r\n\r\n private async saveAccounts(accounts: Map<number, AccountDTO>): Promise<void> {\r\n for (const acc of accounts.values()) {\r\n await this.walletDb.saveAccount(acc);\r\n }\r\n }\r\n\r\n private async subscribeAddresses(addresses: WalletAddress[], isInit = false): Promise<void> {\r\n const subscriptionPromises = addresses.map(async addr => {\r\n const result = await this.rostrumService.subscribeAddress(addr.address, this.onSubscribeEvent);\r\n return { addr, result };\r\n });\r\n\r\n const initPromises: Promise<void>[] = [];\r\n const subscriptionResults = await Promise.all(subscriptionPromises);\r\n\r\n for (const { addr, result } of subscriptionResults) {\r\n if (result && typeof result === 'string' && addr.statusHash != result) {\r\n if (isInit) {\r\n const p = new Promise<void>((resolve) => {\r\n this.addressResolvers.set(addr.address, resolve);\r\n });\r\n initPromises.push(p);\r\n }\r\n this.registerUpdate({address: addr, result});\r\n }\r\n }\r\n\r\n await Promise.all(initPromises);\r\n }\r\n\r\n private onSubscribeEvent = (data: unknown): void => {\r\n if (!Array.isArray(data) || data.length < 2) {\r\n return;\r\n }\r\n\r\n const [address, hash] = data as [string, string];\r\n const allAddresses = this.getAllAddresses();\r\n const addrDTO = allAddresses.find(a => a.address === address);\r\n\r\n if (addrDTO && addrDTO.statusHash !== hash) {\r\n this.registerUpdate({address: addrDTO, result: hash});\r\n }\r\n }\r\n\r\n private registerUpdate(updateInfo: UpdateInfo): void {\r\n this.pendingUpdates.set(updateInfo.address.address, updateInfo);\r\n\r\n clearTimeout(this.updateTimer);\r\n this.updateTimer = setTimeout(() => {\r\n this.processPendingUpdates();\r\n }, WalletManager.DEBOUNCE_MS);\r\n }\r\n\r\n private async processPendingUpdates(): Promise<void> {\r\n if (this.pendingUpdates.size === 0) {\r\n return;\r\n }\r\n\r\n try {\r\n this.notify({ type: 'sync_wallet', loading: true });\r\n console.log(`Processing ${this.pendingUpdates.size} pending updates...`);\r\n\r\n const updates = Array.from(this.pendingUpdates);\r\n this.pendingUpdates.clear();\r\n\r\n const accountsHistoryPromises: Promise<AddressHistory>[] = [];\r\n const vaultsHistoryPromises: Promise<AddressHistory>[] = [];\r\n const walletHistoryPromises: Promise<AddressHistory>[] = [];\r\n for (const [, update] of updates) {\r\n if (this.isAccountAddress(update.address)) {\r\n const p = this.fetchAndUpdateAccount(update.address, update.result);\r\n accountsHistoryPromises.push(p);\r\n } else if (this.isVaultAddress(update.address)) {\r\n const p = this.fetchAndUpdateVault(update.address, update.result);\r\n vaultsHistoryPromises.push(p);\r\n } else {\r\n const p = this.fetchAndUpdateAddress(update.address, update.result);\r\n walletHistoryPromises.push(p);\r\n }\r\n }\r\n \r\n const accountsTxs = await Promise.all(accountsHistoryPromises);\r\n await Promise.all(vaultsHistoryPromises);\r\n const walletTxs = await Promise.all(walletHistoryPromises);\r\n\r\n if (this.addressResolvers.size > 0) {\r\n for (const [address,] of updates) {\r\n const resolver = this.addressResolvers.get(address);\r\n if (resolver) {\r\n resolver();\r\n this.addressResolvers.delete(address);\r\n }\r\n }\r\n }\r\n\r\n await Promise.all([this.postProcessWalletUpdate(walletTxs), this.postProcessAccountUpdate(accountsTxs)]);\r\n } catch (e) {\r\n console.error('Error processing pending updates:', e);\r\n } finally {\r\n this.notify({ type: 'sync_wallet', loading: false });\r\n }\r\n }\r\n\r\n private async postProcessWalletUpdate(history: AddressHistory[]): Promise<void> {\r\n if (history.length === 0) {\r\n return;\r\n }\r\n\r\n const txHistoryMap = new Map<string, ITXHistory>();\r\n for (const { txs } of history) {\r\n for (const tx of txs) {\r\n txHistoryMap.set(tx.tx_hash, tx);\r\n }\r\n }\r\n\r\n await this.checkGapLimit(KeySpace.RECEIVE);\r\n await this.checkGapLimit(KeySpace.CHANGE);\r\n\r\n const walletAddresses = this.getMainAddresses();\r\n const walletBalance = sumBalance(walletAddresses.map(a => a.balance));\r\n const walletTokenBalances = sumTokensBalance(walletAddresses.map(a => a.tokensBalance));\r\n\r\n this.notify({ type: 'account_balance_updated', accountId: MAIN_WALLET_ID, balance: walletBalance, tokensBalance: walletTokenBalances });\r\n this.notify({ type: 'main_address_updated', address: this.getReceiveAddress() });\r\n\r\n const nftPromise = this.assetService.syncNfts(MAIN_WALLET_ID, walletTokenBalances);\r\n for (const tx of txHistoryMap.values()) {\r\n await this.transactionService.classifyAndSaveTransaction(MAIN_WALLET_ID, tx.tx_hash, walletAddresses.map(a => a.address));\r\n }\r\n await nftPromise;\r\n }\r\n\r\n private async postProcessAccountUpdate(history: AddressHistory[]): Promise<void> {\r\n if (history.length === 0) {\r\n return;\r\n }\r\n\r\n for (const { address, txs } of history) {\r\n const account = address as AccountDTO;\r\n \r\n this.notify({ type: 'account_balance_updated', accountId: account.id, balance: account.balance, tokensBalance: account.tokensBalance });\r\n\r\n const nftPromise = this.assetService.syncNfts(account.id, account.tokensBalance);\r\n for (const tx of txs) {\r\n await this.transactionService.classifyAndSaveTransaction(account.id, tx.tx_hash, [account.address]);\r\n }\r\n await nftPromise;\r\n }\r\n }\r\n\r\n private async fetchAndUpdateAddress(addrDTO: AddressDTO, hash: string): Promise<AddressHistory> {\r\n addrDTO.statusHash = hash;\r\n addrDTO.balance = await this.rostrumService.getBalance(addrDTO.address);\r\n addrDTO.tokensBalance = await this.rostrumService.getTokensBalance(addrDTO.address);\r\n\r\n const history = await this.transactionService.fetchTransactionsHistory(addrDTO.address, addrDTO.height);\r\n addrDTO.height = history.lastHeight;\r\n if (!addrDTO.used) {\r\n addrDTO.used = history.txs.length > 0;\r\n }\r\n\r\n await this.walletDb.saveAddress(addrDTO);\r\n\r\n return { address: addrDTO, txs: history.txs };\r\n }\r\n\r\n private async fetchAndUpdateAccount(account: AccountDTO, hash: string): Promise<AddressHistory> {\r\n account.statusHash = hash;\r\n account.balance = await this.rostrumService.getBalance(account.address);\r\n account.tokensBalance = await this.rostrumService.getTokensBalance(account.address);\r\n\r\n const history = await this.transactionService.fetchTransactionsHistory(account.address, account.height);\r\n account.height = history.lastHeight;\r\n\r\n await this.walletDb.saveAccount(account);\r\n\r\n return { address: account, txs: history.txs };\r\n }\r\n\r\n private async fetchAndUpdateVault(vault: VaultDTO, hash: string): Promise<AddressHistory> {\r\n vault.statusHash = hash;\r\n vault.balance = await this.rostrumService.getBalance(vault.address);\r\n\r\n const history = await this.transactionService.fetchTransactionsHistory(vault.address, vault.height);\r\n vault.height = history.lastHeight;\r\n\r\n await this.walletDb.saveVault(vault);\r\n this.notify({ type: 'vault_balance_updated', address: vault.address, balance: vault.balance });\r\n\r\n return { address: vault, txs: history.txs };\r\n }\r\n\r\n private async checkGapLimit(keySpace: KeySpace): Promise<void> {\r\n const addresses = keySpace === KeySpace.RECEIVE \r\n ? this.receiveAddresses \r\n : this.changeAddresses;\r\n\r\n const spaceName = keySpace === KeySpace.RECEIVE ? 'Receive' : 'Change';\r\n const unused = addresses.filter(a => !a.used).length;\r\n\r\n if (unused < WalletManager.GAP_LIMIT) {\r\n const needed = WalletManager.GAP_LIMIT - unused;\r\n const lastIndex = addresses[addresses.length - 1].idx;\r\n \r\n console.log(`Deriving ${needed} more ${spaceName} addresses...`);\r\n \r\n const newAddresses = this.deriveAddresses(keySpace, lastIndex + 1, needed);\r\n\r\n if (keySpace === KeySpace.RECEIVE) {\r\n this.receiveAddresses.push(...newAddresses);\r\n } else {\r\n this.changeAddresses.push(...newAddresses);\r\n }\r\n\r\n await this.saveAddresses(newAddresses);\r\n await this.subscribeAddresses(newAddresses);\r\n }\r\n }\r\n\r\n public async addNewAccount(id: number, name: string): Promise<void> {\r\n const path = keyPathToString(AccountType.DAPP, 0, id);\r\n const address = this.keyManager.getKey(path).privateKey.toAddress().toString();\r\n\r\n const account: AccountDTO = {\r\n id: id,\r\n name: name,\r\n address: address,\r\n height: 0,\r\n hidden: 0,\r\n statusHash: '',\r\n balance: { confirmed: \"0\", unconfirmed: \"0\" },\r\n tokensBalance: {},\r\n type: AccountType.DAPP\r\n };\r\n\r\n this.accounts.set(id, account);\r\n this.accountsAddressToId.set(address, id);\r\n await this.walletDb.saveAccount(account);\r\n await this.subscribeAddresses([account]);\r\n\r\n this.notify({\r\n type: 'new_account',\r\n account: {\r\n id: account.id,\r\n name: account.name,\r\n address: account.address,\r\n balance: account.balance,\r\n tokensBalance: account.tokensBalance,\r\n tokens: [],\r\n sessions: {}\r\n }\r\n });\r\n }\r\n\r\n public async updateAccountName(id: number, name: string): Promise<void> {\r\n if (!name) {\r\n return;\r\n }\r\n\r\n const account = this.accounts.get(id)!;\r\n account.name = name;\r\n\r\n await this.walletDb.updateAccountName(id, name);\r\n }\r\n\r\n public rescanAccount(id: number): void {\r\n if (id == MAIN_WALLET_ID) {\r\n const addrs = this.getMainAddresses();\r\n for (const addr of addrs) {\r\n addr.height = 0;\r\n this.registerUpdate({address: addr, result: addr.statusHash});\r\n }\r\n } else {\r\n const account = this.accounts.get(id)!\r\n account.height = 0;\r\n this.registerUpdate({address: account, result: account.statusHash});\r\n }\r\n }\r\n \r\n public getVaultNextIndex(): number {\r\n if (this.vaults.size == 0) {\r\n return 0;\r\n }\r\n return Math.max(...Array.from(this.vaults.values(), v => v.idx)) + 1;\r\n }\r\n\r\n public async addNewVault(address: string, block: number, index: number): Promise<void> {\r\n const vault: VaultDTO = {\r\n address: address,\r\n block: block,\r\n idx: index,\r\n height: 0,\r\n statusHash: '',\r\n balance: { confirmed: \"0\", unconfirmed: \"0\" },\r\n tokensBalance: {},\r\n type: AccountType.VAULT\r\n };\r\n await this.addVault(vault);\r\n }\r\n\r\n private async addVault(vault: VaultDTO): Promise<void> {\r\n this.vaults.set(vault.address, vault);\r\n await this.walletDb.saveVault(vault);\r\n await this.subscribeAddresses([vault]);\r\n\r\n this.notify({\r\n type: 'new_vault',\r\n vault: {\r\n address: vault.address,\r\n balance: vault.balance,\r\n block: vault.block,\r\n index: vault.idx\r\n }\r\n });\r\n }\r\n\r\n public async rescanVaults(): Promise<boolean> {\r\n let found = false;\r\n const vaults = await this.discoveryService.discoverVaults(this.getMainAddresses().map(a => a.address));\r\n const promises: Promise<void>[] = [];\r\n for (const [address, vault] of vaults) {\r\n if (!this.vaults.has(address)) {\r\n found = true;\r\n promises.push(this.addVault(vault));\r\n }\r\n }\r\n await Promise.all(promises);\r\n return found;\r\n }\r\n\r\n private isVaultAddress(address: AccountDTO | AddressDTO | VaultDTO): address is VaultDTO {\r\n return address.type == AccountType.VAULT;\r\n }\r\n\r\n private isAccountAddress(address: AccountDTO | AddressDTO | VaultDTO): address is AccountDTO {\r\n return address.type == AccountType.DAPP;\r\n }\r\n\r\n private isMainAddress(address: AccountDTO | AddressDTO | VaultDTO): address is AddressDTO {\r\n return address.type == AccountType.MAIN;\r\n }\r\n}","import type { PayloadAction } from \"@reduxjs/toolkit\";\nimport { createSlice } from \"@reduxjs/toolkit\";\r\n\r\nexport interface AuthState {\r\n isWalletExist: boolean;\r\n isAuthorized: boolean;\r\n}\r\n\r\nconst initialState: AuthState = {\r\n isWalletExist: false,\r\n isAuthorized: false,\r\n};\r\n\r\nconst authSlice = createSlice({\r\n name: 'auth',\r\n initialState,\r\n reducers: {\r\n setWalletExist: (state, action: PayloadAction<boolean>) => {\r\n state.isWalletExist = action.payload;\r\n },\r\n setAuthorized: (state, action: PayloadAction<boolean>) => {\r\n state.isAuthorized = action.payload;\r\n }\r\n }\r\n});\r\n\r\nexport const authActions = authSlice.actions;\r\nexport const authReducer = authSlice.reducer;","import type { PayloadAction } from \"@reduxjs/toolkit\";\nimport { createSlice } from \"@reduxjs/toolkit\";\nimport type { SessionRequestType } from \"../../utils\";\nimport type { DappRpcRequest } from \"../../types\";\n\nexport interface DappModalState {\n modalType: SessionRequestType | null;\n currentRequest: DappRpcRequest | null;\n}\n\nconst initialState: DappModalState = {\n modalType: null,\n currentRequest: null,\n};\n\nconst dappModalSlice = createSlice({\n name: 'dappModal',\n initialState,\n reducers: {\n showRequest(state, action: PayloadAction<DappRpcRequest>) {\n state.modalType = action.payload.type;\n state.currentRequest = action.payload;\n },\n clear(state) {\n state.modalType = null;\n state.currentRequest = null;\n },\n },\n});\n\nexport const dappModalActions = dappModalSlice.actions;\nexport const dappModalReducer = dappModalSlice.reducer;","import type { PayloadAction } from \"@reduxjs/toolkit\";\nimport { createSlice } from \"@reduxjs/toolkit\";\n\nexport interface LoaderState {\n counter: number\n loading: boolean;\n text?: string;\n}\n\nconst initState: LoaderState = {\n counter: 0,\n loading: false\n}\n\nconst loaderSlice = createSlice({\n name: 'loader',\n initialState: initState,\n reducers: {\n setLoader: (state, action: PayloadAction<Omit<LoaderState, 'counter'>>) => {\n const counter = action.payload.loading\n ? state.counter + 1\n : Math.max(0, state.counter - 1);\n state.counter = counter;\n state.loading = counter > 0;\n state.text = action.payload.text;\n },\n }\n});\n\nexport const loaderActions = loaderSlice.actions;\nexport const loaderReducer = loaderSlice.reducer;","import type { PayloadAction } from \"@reduxjs/toolkit\";\nimport { createSlice } from \"@reduxjs/toolkit\";\nimport type { AppNotification } from \"../../types\";\n\nexport interface NotificationsState {\n wallet: Record<string, AppNotification>;\n web3: Record<string, AppNotification>;\n}\n\nconst initialState: NotificationsState = {\n wallet: {},\n web3: {}\n};\n\nconst notificationsSlice = createSlice({\n name: 'notifications',\n initialState,\n reducers: {\n addNotification: (state, action: PayloadAction<AppNotification>) => {\n if (action.payload.type == 'wallet') {\n state.wallet[action.payload.id] = action.payload;\n } else if (action.payload.type == 'web3') {\n state.web3[action.payload.id] = action.payload;\n }\n },\n removeNotification: (state, action: PayloadAction<string>) => {\n delete state.wallet[action.payload];\n delete state.web3[action.payload];\n },\n clearAll: (state, action: PayloadAction<'wallet' | 'web3' | 'all'>) => {\n if (action.payload === 'wallet') {\n state.wallet = {};\n } else if (action.payload === 'web3') {\n state.web3 = {};\n } else if (action.payload === 'all') {\n state.wallet = {};\n state.web3 = {};\n }\n }\n }\n});\n\nexport const notificationsActions = notificationsSlice.actions;\nexport const notificationsReducer = notificationsSlice.reducer;","import type { PayloadAction } from \"@reduxjs/toolkit\";\nimport { createAsyncThunk, createSlice } from \"@reduxjs/toolkit\";\r\nimport type { Price } from \"../../types\";\r\nimport { getNexaPrices, initializePrices } from \"../../utils\";\r\n\r\nexport interface StatusState {\r\n status: \"Online\" | \"Offline\";\r\n height: number;\r\n price: Record<string, Price>;\r\n hasNetwork: boolean;\r\n isSuspended: boolean;\r\n}\r\n\r\nconst initialState: StatusState = {\r\n status: \"Offline\",\r\n height: 0,\r\n price: initializePrices(),\r\n hasNetwork: true,\r\n isSuspended: false,\r\n};\r\n\r\nexport const fetchPrice = createAsyncThunk('status/fetchPrice', async () => {\r\n const prices = initializePrices();\r\n try {\r\n const p = await getNexaPrices();\r\n Object.keys(p).forEach(currency => {\r\n prices[currency] = { \r\n value: p[currency],\r\n change: p[`${currency}_24h_change`]\r\n };\r\n });\r\n } catch {\r\n // prices remain at 0\r\n }\r\n return prices ;\r\n});\r\n\r\nconst statusSlice = createSlice({\r\n name: 'status',\r\n initialState,\r\n reducers: {\r\n setHeight: (state, action: PayloadAction<number>) => {\r\n if (action.payload > 0) {\r\n state.status = \"Online\";\r\n }\r\n state.height = action.payload;\r\n },\r\n setOffline: (state) => {\r\n state.status = \"Offline\";\r\n },\r\n setHasNetwork: (state, action: PayloadAction<boolean>) => {\r\n state.hasNetwork = action.payload;\r\n },\r\n setIsSuspended: (state, action: PayloadAction<boolean>) => {\r\n state.isSuspended = action.payload;\r\n }\r\n },\r\n extraReducers: (builder) => {\r\n builder\r\n .addCase(fetchPrice.fulfilled, (state, action) => {\r\n state.price = action.payload;\r\n })\r\n .addCase(fetchPrice.rejected, (_, action) => {\r\n console.error(action.error.message);\r\n });\r\n }\r\n});\r\n\r\nexport const statusActions = statusSlice.actions;\r\nexport const statusReducer = statusSlice.reducer;","import type { PayloadAction } from \"@reduxjs/toolkit\";\nimport { createSlice } from \"@reduxjs/toolkit\";\r\nimport type { Account, AssetEntity, Balance, SessionInfo, VaultInfo } from \"../../types\";\r\nimport { MAIN_WALLET_ID } from \"../../utils\";\r\n\r\ninterface AddSessionPayload {\r\n accountId: number;\r\n sessionInfo: SessionInfo;\r\n}\r\n\r\ninterface RemoveSessionPayload {\r\n accountId: number;\r\n sessionId: string;\r\n}\r\n\r\nexport interface WalletState {\r\n isAuthorized: boolean;\r\n selectedAccount: number;\r\n accounts: Record<number, Account>;\r\n vaults: Record<string, VaultInfo>;\r\n sync: boolean;\r\n initLoad: boolean;\r\n txUpdateTrigger: number;\r\n nftsUpdateTrigger: number;\r\n}\r\n\r\nconst initialState: WalletState = {\r\n isAuthorized: false,\r\n selectedAccount: MAIN_WALLET_ID,\r\n accounts: {\r\n \"-1\": {\r\n id: MAIN_WALLET_ID,\r\n name: 'Main Wallet',\r\n address: '',\r\n balance: {confirmed: \"0\", unconfirmed: \"0\"},\r\n tokensBalance: {},\r\n tokens: [],\r\n sessions: {}\r\n }\r\n },\r\n vaults: {},\r\n sync: false,\r\n initLoad: true,\r\n txUpdateTrigger: 0,\r\n nftsUpdateTrigger: 0\r\n}\r\n\r\nconst walletSlice = createSlice({\r\n name: 'wallet',\r\n initialState,\r\n reducers: {\r\n setInitLoad: (state, action: PayloadAction<boolean>) => {\r\n state.initLoad = action.payload;\r\n },\r\n setSelectedAccount: (state, action: PayloadAction<number>) => {\r\n state.selectedAccount = action.payload;\r\n },\r\n setSync: (state, action: PayloadAction<boolean>) => {\r\n state.sync = action.payload;\r\n },\r\n setVault: (state, action: PayloadAction<VaultInfo>) => {\r\n state.vaults[action.payload.address] = action.payload;\r\n },\r\n setVaultBalance: (state, action: PayloadAction<{ address: string, balance: Balance }>) => {\r\n state.vaults[action.payload.address].balance = action.payload.balance;\r\n },\r\n setAccount: (state, action: PayloadAction<Account>) => {\r\n state.accounts[action.payload.id] = action.payload;\r\n },\r\n setMainAddress: (state, action: PayloadAction<string>) => {\r\n state.accounts[MAIN_WALLET_ID].address = action.payload;\r\n },\r\n setAccountBalance: (state, action: PayloadAction<{ id: number, balance: Balance, tokensBalance: Record<string, Balance> }>) => {\r\n state.accounts[action.payload.id].balance = action.payload.balance;\r\n state.accounts[action.payload.id].tokensBalance = action.payload.tokensBalance;\r\n },\r\n setAccountName: (state, action: PayloadAction<{ id: number, name: string }>) => {\r\n state.accounts[action.payload.id].name = action.payload.name;\r\n },\r\n setTokens: (state, action: PayloadAction<{ id: number, assets: AssetEntity[] }>) => {\r\n state.accounts[action.payload.id].tokens = action.payload.assets;\r\n },\r\n addToken: (state, action: PayloadAction<{ id: number, asset: AssetEntity }>) => {\r\n state.accounts[action.payload.id].tokens.unshift(action.payload.asset);\r\n },\r\n removeToken: (state, action: PayloadAction<{ id: number, tokenId: string }>) => {\r\n state.accounts[action.payload.id].tokens = state.accounts[action.payload.id].tokens.filter(n => n.tokenIdHex !== action.payload.tokenId);\r\n },\r\n refreshTxs: (state) => {\r\n state.txUpdateTrigger++;\r\n },\r\n refreshNfts: (state) => {\r\n state.nftsUpdateTrigger++;\r\n },\r\n addSession(state, action: PayloadAction<AddSessionPayload>) {\r\n const { accountId, sessionInfo } = action.payload;\r\n state.accounts[accountId].sessions[sessionInfo.details.sessionId] = sessionInfo;\r\n },\r\n removeSession(state, action: PayloadAction<RemoveSessionPayload>) {\r\n const { accountId, sessionId } = action.payload;\r\n if (state.accounts[accountId].sessions[sessionId]) {\r\n delete state.accounts[accountId].sessions[sessionId];\r\n }\r\n },\r\n clearSessions(state, action: PayloadAction<{ accountId: number }>) {\r\n state.accounts[action.payload.accountId].sessions = {};\r\n }\r\n }\r\n});\r\n\r\nexport const walletActions = walletSlice.actions;\r\nexport const walletReducer = walletSlice.reducer;","import { authReducer } from \"./slices/auth\";\r\nimport { dappModalReducer } from \"./slices/dapp\";\r\nimport { loaderReducer } from \"./slices/loader\";\r\nimport { notificationsReducer } from \"./slices/notifications\";\r\nimport { statusReducer } from \"./slices/status\";\r\nimport { walletReducer } from \"./slices/wallet\";\r\n\r\nexport const sharedReducers = {\r\n loader: loaderReducer,\r\n dapp: dappModalReducer,\r\n status: statusReducer,\r\n wallet: walletReducer,\r\n auth: authReducer,\r\n notifications: notificationsReducer,\r\n};\r\n\r\nexport type SharedState = {\r\n loader: ReturnType<typeof loaderReducer>;\r\n dapp: ReturnType<typeof dappModalReducer>;\r\n status: ReturnType<typeof statusReducer>;\r\n wallet: ReturnType<typeof walletReducer>;\r\n auth: ReturnType<typeof authReducer>;\r\n notifications: ReturnType<typeof notificationsReducer>;\r\n};","import { useSelector } from \"react-redux\";\r\nimport type { SharedState } from \"./store\";\r\nimport { createSelector } from \"@reduxjs/toolkit\";\r\nimport type { AuthState } from \"./slices\";\r\nimport type { Account, AppNotification, Balance, SessionInfo, VaultInfo } from \"../types\";\r\n\r\nconst useSharedSelector = useSelector.withTypes<SharedState>();\r\n\r\nexport const useAuth = (): AuthState => useSharedSelector(state => state.auth);\r\n\r\nexport const useBlockHeight = (): number => useSharedSelector(state => state.status.height);\r\n\r\nexport const useAccount = (id: number): Account => useSharedSelector(state => state.wallet.accounts[id]);\r\nexport const useSelectedAccount = (): number => useSharedSelector(state => state.wallet.selectedAccount);\r\nexport const useLastAccountId = (): number => useSharedSelector(state => Math.max(...Object.keys(state.wallet.accounts).map(Number)));\r\n\r\nexport const useMainReceiveAddress = (account: number): string => useSharedSelector(state => state.wallet.accounts[account].address);\r\n\r\nexport const useWalletBalance = (account: number): Balance => useSharedSelector(state => state.wallet.accounts[account].balance);\r\nexport const useTokenBalance = (account: number, tokenIdHex: string): Balance => \r\n useSharedSelector(state => state.wallet.accounts[account].tokensBalance[tokenIdHex]);\r\n\r\nexport const useDAppSession = (account: number, session: string): SessionInfo =>\r\n useSharedSelector(state => state.wallet.accounts[account].sessions[session]);\r\n\r\nexport const useVaults = (): Record<string, VaultInfo> => useSharedSelector(state => state.wallet.vaults);\r\n\r\nconst selectWalletNotificationsArray = createSelector(\r\n [(state: SharedState) => state.notifications.wallet],\r\n (wallet) => Object.values(wallet).sort((a, b) => b.createdAt - a.createdAt)\r\n);\r\n\r\nconst selectWeb3NotificationsArray = createSelector(\r\n [(state: SharedState) => state.notifications.web3],\r\n (web3) => Object.values(web3).sort((a, b) => b.createdAt - a.createdAt)\r\n);\r\n\r\nconst selectAllNotificationsArray = createSelector(\r\n [selectWalletNotificationsArray, selectWeb3NotificationsArray],\r\n (wallet, web3) => [...wallet, ...web3].sort((a, b) => b.createdAt - a.createdAt)\r\n);\r\n\r\nexport const useWalletNotifications = (): AppNotification[] => useSharedSelector(selectWalletNotificationsArray);\r\nexport const useWeb3Notifications = (): AppNotification[] => useSharedSelector(selectWeb3NotificationsArray);\r\nexport const useAllNotifications = (): AppNotification[] => useSharedSelector(selectAllNotificationsArray);\r\n"],"names":["MAIN_WALLET_ID","MAX_INT64","VAULT_FIRST_BLOCK","VAULT_SCRIPT_PREFIX","isTestnet","Networks","isGenesisHashValid","hash","isValidNexaAddress","address","type","AddressType","Address","getExplorerUrl","currentTimestamp","estimateDateByFutureBlock","current","future","estimateMins","time","isNullOrEmpty","arg","truncateStringMiddle","str","maxLength","ellipsis","halfLength","firstHalf","secondHalf","capitalizeFirstLetter","getAddressBuffer","CommonUtils","BufferUtils","tokenIdToHex","token","tokenHexToAddr","tokenAmountToAssetAmount","amount","sumBalance","balances","confirmed","unconfirmed","b","sumTokensBalance","tokensBalance","key","FILE_EXTENSION_TO_TYPE","getFileMediaType","filename","lastDotIndex","extension","getFileMimeType","KVStore","seed","code","release","params","hide","currency","useBiometric","value","requireAuth","autoLock","AccountType","KeySpace","SessionRequestType","AssetType","WalletDB","store","callback","event","tx","error","assetTx","account","tokenId","pageNum","pageSize","asset","id","nft","notify","notifyNft","accountEntity","a","name","session","accountId","sessionId","addressEntity","v","vault","vaultEntity","WalletCache","walletDb","RostrumService","kvStore","fromHeight","firstUse","e","verbose","outpoint","balance","cToken","uToken","txHex","handler","response","data","height","start","ElectrumClient","force","method","parameters","res","timeout","resolve","reject","check","ConnectionStatus","TransportScheme","keyPathToString","index","stringToKeyPath","path","parts","KeyManager","mnemonic","mnemonicToSeedSync","HDPrivateKey","keyPath","getNiftyToken","fetchNiftyNFT","performGet","getNiftyEndpoint","isNiftySubgroup","group","addrBuf","GroupToken","fetchAssetDoc","url","translateIfIpfsUrl","fetchAssetBlob","transformTokenIconUrl","icon","documentUrl","parseTokenDataUrl","gateway","responseType","arrayBuffer","AssetService","rostrumService","walletCache","checkCache","cachedToken","genesis","groupId","parent","iconUrl","GroupIdType","token_zip","info","JSZip","infoData","infoJson","tokenIdHex","parentGroupId","parentGenesis","hexId","source","collection","nftEntity","tokenBalances","currentAssets","internalAssets","handleNftDelete","staleAssets","hasBalance","isAssetExist","TransactionService","keysManager","maxHeight","fromHeightFilter","txHistory","transactions","txEntry","txHash","myAddresses","txDto","txEntity","involvedAssets","m","assetId","t","myInputs","othersInputs","myOutputs","othersOutputs","vin","movement","vout","isConfirmed","from","toAddr","toChange","feeFromAmount","feePerByte","txOptions","txBuilder","tokenPrivKeys","privKeys","k","templateData","TransactionBuilder","Transaction","builder","options","allKeys","usedKeys","origAmount","out","utxos","utxo","input","hdkey","unspent","txFee","hasChange","err","UnitUtils","outTokenAmount","tokenHex","inTokenAmount","tip","obj","generateNewMnemonic","size","generateMnemonic","wordlist","isMnemonicValid","validateMnemonic","deriveKey","password","salt","argon2idAsync","encryptMnemonic","phrase","iv","cipher","gcm","encBuf","decryptMnemonic","encSeed","validateAndDecryptMnemonic","decMn","currencySymbols","currencies","getNexaPrices","vs_currencies","getCurrencySymbol","initializePrices","prices","getVaultTemplate","Script","Opcode","getVaultTemplateHash","template","Hash","generateVaultConstraint","pubKey","getVaultConstraintHash","constraint","generateVaultVisibleArgs","args","ScriptOpcode","BNExtended","generateVaultAddress","templateHash","constraintHash","visibleArgs","SessionManager","keyManager","request","provider","sessionInfo","accountSessions","sessionMap","accounts","storedSessions","currentSessions","loadedSessions","DAppProvider","details","appInfo","messages","msg","results","result","sessions","payload","handleRequest","signMsgReq","addTokenReq","sendTransactionReq","signTransactionReq","TransactionTransformer","assetService","hex","addressKey","context","promises","i","p","Output","output","subscript","txSig","TxSigner","SighashType","ScriptFactory","placeholderIndex","sigHashBuf","sigHashType","templateBuf","OutputSighashType","n","sentAmount","sum","receivedAmount","HODL_FIRST_BLOCK","HODL_SCRIPT_PREFIX","WalletDiscoveryService","keySpace","stop","addrBatch","rAddr","addresses","vaultsPromises","vaults","set","history","hodls","hodl","scirptTemplate","buf","BufferWriter","actualAddress","block","expectedAddress","WalletManager","transactionService","sessionManager","addr","rIndexPromise","cIndexPromise","dappIndexPromis","rIndex","cIndex","dappIndex","entry","accs","tokensLoadPromises","walletAddresses","space","startIndex","count","newAddresses","addressDTO","newAccounts","acc","isInit","subscriptionPromises","initPromises","subscriptionResults","addrDTO","updateInfo","updates","accountsHistoryPromises","vaultsHistoryPromises","walletHistoryPromises","update","accountsTxs","walletTxs","resolver","txHistoryMap","txs","walletBalance","walletTokenBalances","nftPromise","spaceName","unused","needed","lastIndex","addrs","found","initialState","authSlice","createSlice","state","action","authActions","authReducer","dappModalSlice","dappModalActions","dappModalReducer","initState","loaderSlice","counter","loaderActions","loaderReducer","notificationsSlice","notificationsActions","notificationsReducer","fetchPrice","createAsyncThunk","statusSlice","_","statusActions","statusReducer","walletSlice","walletActions","walletReducer","sharedReducers","useSharedSelector","useSelector","useAuth","useBlockHeight","useAccount","useSelectedAccount","useLastAccountId","useMainReceiveAddress","useWalletBalance","useTokenBalance","useDAppSession","useVaults","selectWalletNotificationsArray","createSelector","wallet","selectWeb3NotificationsArray","web3","selectAllNotificationsArray","useWalletNotifications","useWeb3Notifications","useAllNotifications"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/utils/common.ts","../src/persistence/datastore/kv.ts","../src/utils/enums.ts","../src/persistence/wallet-db.ts","../src/services/cache.ts","../src/services/rostrum.ts","../src/utils/keypath.ts","../src/services/key.ts","../src/utils/asset.ts","../src/services/asset.ts","../src/services/transaction.ts","../src/utils/seed.ts","../src/utils/price.ts","../src/utils/vault.ts","../src/services/session.ts","../src/services/tx-transformer.ts","../src/services/discovery.ts","../src/services/wallet.ts","../src/state/slices/auth.ts","../src/state/slices/dapp.ts","../src/state/slices/loader.ts","../src/state/slices/notifications.ts","../src/state/slices/status.ts","../src/state/slices/wallet.ts","../src/state/store.ts","../src/state/hooks.ts"],"sourcesContent":["import { Address, AddressType, BufferUtils, CommonUtils, Networks } from \"libnexa-ts\";\r\nimport type { Balance } from \"../types/wallet.types\";\r\n\r\nexport const MAIN_WALLET_ID = -1;\r\nexport const MAX_INT64 = 9223372036854775807n;\r\nexport const VAULT_FIRST_BLOCK = 274710;\r\nexport const VAULT_SCRIPT_PREFIX = \"0014461ad25081cb0119d034385ff154c8d3ad6bdd76\";\r\n\r\nexport function isTestnet(): boolean {\r\n return Networks.defaultNetwork == Networks.testnet;\r\n}\r\n\r\nexport function isGenesisHashValid(hash: string): boolean {\r\n if(isTestnet()) {\r\n return hash == \"508c843a4b98fb25f57cf9ebafb245a5c16468f06519cdd467059a91e7b79d52\";\r\n }\r\n return hash == \"edc7144fe1ba4edd0edf35d7eea90f6cb1dba42314aa85da8207e97c5339c801\";\r\n}\r\n\r\nexport function isValidNexaAddress(address: string, type = AddressType.PayToScriptTemplate): boolean {\r\n return Address.isValid(address, Networks.defaultNetwork, type);\r\n}\r\n\r\nexport function getExplorerUrl(): string {\r\n return `https://${(isTestnet() ? 'testnet-' : '')}explorer.nexa.org`;\r\n}\r\n\r\nexport function currentTimestamp(): number {\r\n return Math.floor(Date.now() / 1000);\r\n}\r\n\r\nexport function estimateDateByFutureBlock(current: number, future: number): string {\r\n const estimateMins = (future - current) * 2;\r\n const time = new Date();\r\n time.setMinutes(time.getMinutes() + estimateMins);\r\n return time.toLocaleDateString();\r\n}\r\n\r\nexport function isNullOrEmpty(arg?: string | any[] | null): arg is undefined | [] | null | '' {\r\n return !arg || arg.length === 0;\r\n}\r\n\r\nexport function truncateStringMiddle(str?: string, maxLength = 0): string {\r\n if (!str || str.length <= maxLength) {\r\n return str || '';\r\n }\r\n\r\n const ellipsis = '...';\r\n const halfLength = Math.floor((maxLength - ellipsis.length) / 2);\r\n const firstHalf = str.slice(0, halfLength);\r\n const secondHalf = str.slice(str.length - halfLength);\r\n\r\n return firstHalf + ellipsis + secondHalf;\r\n};\r\n\r\nexport function capitalizeFirstLetter(str: string): string {\r\n if (str.length === 0) {\r\n return \"\";\r\n }\r\n return str.charAt(0).toUpperCase() + str.substring(1);\r\n}\r\n\r\nexport function getAddressBuffer(address: string): Uint8Array {\r\n if (CommonUtils.isHexa(address)) {\r\n return BufferUtils.hexToBuffer(address) ;\r\n }\r\n return Address.fromString(address).data;\r\n}\r\n\r\nexport function tokenIdToHex(token: string): string {\r\n if (CommonUtils.isHexa(token)) {\r\n return token;\r\n }\r\n return BufferUtils.bufferToHex(getAddressBuffer(token));\r\n}\r\n\r\nexport function tokenHexToAddr(token: string): string {\r\n if (!CommonUtils.isHexa(token)) {\r\n return token;\r\n }\r\n return new Address(getAddressBuffer(token), Networks.defaultNetwork, AddressType.GroupIdAddress).toString();\r\n}\r\n\r\nexport function tokenAmountToAssetAmount(amount?: string | number | bigint): string {\r\n if (amount == null || amount === \"\") {\r\n return \"\";\r\n }\r\n if (BigInt(amount) <= 0n) {\r\n return \"0\";\r\n }\r\n return amount.toString();\r\n}\r\n\r\nexport function sumBalance(balances: Balance[]): Balance {\r\n let confirmed = BigInt(0), unconfirmed = BigInt(0);\r\n balances.forEach(b => {\r\n confirmed += BigInt(b.confirmed);\r\n unconfirmed += BigInt(b.unconfirmed);\r\n });\r\n return {confirmed: confirmed.toString(), unconfirmed: unconfirmed.toString()};\r\n}\r\n\r\nexport function sumTokensBalance(balances: Record<string, Balance>[]): Record<string, Balance> {\r\n const tokensBalance: Record<string, Balance> = {};\r\n balances.forEach(b => {\r\n for (const key in b) {\r\n if (tokensBalance[key]) {\r\n tokensBalance[key].confirmed = (BigInt(tokensBalance[key].confirmed) + BigInt(b[key].confirmed)).toString();\r\n tokensBalance[key].unconfirmed = (BigInt(tokensBalance[key].unconfirmed) + BigInt(b[key].unconfirmed)).toString();\r\n } else {\r\n tokensBalance[key] = { confirmed: BigInt(b[key].confirmed).toString(), unconfirmed: BigInt(b[key].unconfirmed).toString() };\r\n }\r\n }\r\n });\r\n \r\n return tokensBalance;\r\n}\r\n\r\nconst FILE_EXTENSION_TO_TYPE = {\r\n // Images\r\n //'.svg': { media: 'image', mime: 'image/svg+xml' },\r\n '.gif': { media: 'image', mime: 'image/gif' },\r\n '.png': { media: 'image', mime: 'image/png' },\r\n '.apng': { media: 'image', mime: 'image/apng' },\r\n '.jpg': { media: 'image', mime: 'image/jpeg' },\r\n '.jpeg': { media: 'image', mime: 'image/jpeg' },\r\n '.avif': { media: 'image', mime: 'image/avif' },\r\n '.webp': { media: 'image', mime: 'image/webp' },\r\n '.bmp': { media: 'image', mime: 'image/bmp' },\r\n \r\n // Videos\r\n '.mp4': { media: 'video', mime: 'video/mp4' },\r\n '.mpeg': { media: 'video', mime: 'video/mpeg' },\r\n '.mpg': { media: 'video', mime: 'video/mpeg' },\r\n '.webm': { media: 'video', mime: 'video/webm' },\r\n '.mov': { media: 'video', mime: 'video/quicktime' },\r\n \r\n // Audio\r\n '.mp3': { media: 'audio', mime: 'audio/mpeg' },\r\n '.ogg': { media: 'audio', mime: 'audio/ogg' },\r\n '.wav': { media: 'audio', mime: 'audio/wav' },\r\n '.m4a': { media: 'audio', mime: 'audio/mp4' },\r\n} as const;\r\n\r\nexport function getFileMediaType(filename: string): 'video' | 'audio' | 'image' | 'unknown' {\r\n const lastDotIndex = filename.lastIndexOf('.');\r\n if (lastDotIndex === -1) return 'unknown';\r\n \r\n const extension = filename.slice(lastDotIndex).toLowerCase();\r\n return FILE_EXTENSION_TO_TYPE[extension as keyof typeof FILE_EXTENSION_TO_TYPE]?.media ?? 'unknown';\r\n}\r\n\r\nexport function getFileMimeType(filename: string): string {\r\n const lastDotIndex = filename.lastIndexOf('.');\r\n if (lastDotIndex === -1) return 'application/octet-stream';\r\n \r\n const extension = filename.slice(lastDotIndex).toLowerCase();\r\n return FILE_EXTENSION_TO_TYPE[extension as keyof typeof FILE_EXTENSION_TO_TYPE]?.mime ?? 'application/octet-stream';\r\n}","import type { RostrumParams } from \"../../types/rostrum.types\";\r\nimport { isNullOrEmpty, isTestnet } from \"../../utils/common\";\r\n\r\nexport abstract class KVStore {\r\n \r\n public abstract getValue(key: string): Promise<string | null>;\r\n public abstract setValue(key: string, value: string): Promise<void>;\r\n public abstract removeValue(key: string): Promise<void>;\r\n public abstract clearData(): Promise<void>;\r\n\r\n protected getPrefix(): string {\r\n return isTestnet() ? 'testnet-' : '';\r\n }\r\n\r\n public async getEncryptedSeed(): Promise<string | null> {\r\n return this.getValue(\"seed\");\r\n }\r\n\r\n public async saveEncryptedSeed(seed: string): Promise<void> {\r\n return this.setValue('seed', seed);\r\n }\r\n\r\n public async getVersionCode(): Promise<string | null> {\r\n return this.getValue(\"version-code\");\r\n }\r\n\r\n public async setVersionCode(code: string): Promise<void> {\r\n return this.setValue('version-code', code);\r\n }\r\n\r\n public async getReleaseNumber(): Promise<string | null> {\r\n return this.getValue(\"release-number\");\r\n }\r\n\r\n public async setReleaseNumber(release: string): Promise<void> {\r\n return this.setValue('release-number', release);\r\n }\r\n\r\n public async getRostrumParams(): Promise<RostrumParams | undefined> {\r\n const params = await this.getValue(this.getPrefix() + \"rostrum-params\");\r\n if (params) {\r\n return JSON.parse(params);\r\n }\r\n }\r\n\r\n public async saveRostrumParams(params: RostrumParams): Promise<void> {\r\n return this.setValue(this.getPrefix() + \"rostrum-params\", JSON.stringify(params));\r\n }\r\n\r\n public async removeRostrumParams(): Promise<void> {\r\n return this.removeValue(this.getPrefix() + \"rostrum-params\");\r\n }\r\n\r\n public async setHideZeroTokenConfig(hide: boolean): Promise<void> {\r\n return this.setValue(\"zero-tokens\", JSON.stringify(hide));\r\n }\r\n\r\n public async getHideZeroTokenConfig(): Promise<boolean> {\r\n const hide = await this.getValue(\"zero-tokens\");\r\n return hide === \"true\";\r\n }\r\n\r\n public async setHideZeroVaultsConfig(hide: boolean): Promise<void> {\r\n return this.setValue(\"zero-vaults\", JSON.stringify(hide));\r\n }\r\n\r\n public async getHideZeroVaultsConfig(): Promise<boolean> {\r\n const hide = await this.getValue(\"zero-vaults\");\r\n return hide === \"true\";\r\n }\r\n\r\n public async getSelectedCurrency(): Promise<string> {\r\n const value = await this.getValue('selectedCurrency');\r\n return value || 'usd';\r\n }\r\n\r\n public async setSelectedCurrency(currency: string): Promise<void> {\r\n return this.setValue('selectedCurrency', currency);\r\n }\r\n\r\n public async getUseBiometric(): Promise<boolean> {\r\n const value = await this.getValue('biometrics');\r\n return value === \"true\";\r\n }\r\n\r\n public async setUseBiometric(useBiometric: boolean): Promise<void> {\r\n return this.setValue('biometrics', JSON.stringify(useBiometric));\r\n }\r\n\r\n public async getRequireAuth(): Promise<boolean> {\r\n const value = await this.getValue('auth');\r\n return isNullOrEmpty(value) || value === \"true\";\r\n }\r\n\r\n public async setRequireAuth(requireAuth: boolean): Promise<void> {\r\n await this.setValue('auth', JSON.stringify(requireAuth));\r\n }\r\n\r\n public async getReleaseNotesTime(): Promise<number | undefined> {\r\n const value = await this.getValue('show-notes');\r\n return value ? Number(value) : undefined;\r\n }\r\n\r\n public async setReleaseNotesTime(time: string): Promise<void> {\r\n if (isNullOrEmpty(time)) {\r\n await this.removeValue('show-notes');\r\n } else {\r\n await this.setValue('show-notes', time);\r\n }\r\n }\r\n\r\n public async getIsTestnet(): Promise<boolean> {\r\n const value = await this.getValue('testnet');\r\n return value === \"1\";\r\n }\r\n\r\n public async setIsTestnet(isTestnet: boolean): Promise<void> {\r\n await this.setValue('testnet', isTestnet ? \"1\" : \"0\");\r\n }\r\n\r\n public async getAutoLockSeconds(): Promise<number> {\r\n const value = await this.getValue('auto-lock');\r\n return value ? parseInt(value) : 60;\r\n }\r\n\r\n public async setAutoLockSeconds(autoLock: number): Promise<void> {\r\n await this.setValue('auto-lock', `${autoLock}`);\r\n }\r\n}","export enum AccountType {\r\n MAIN = 0,\r\n VAULT = 1,\r\n DAPP = 2\r\n}\r\n\r\nexport enum KeySpace {\r\n RECEIVE = 0,\r\n CHANGE = 1\r\n}\r\n\r\nexport enum SessionRequestType {\r\n SignMessage = 'signMessage',\r\n AddToken = 'addToken',\r\n SignTransaction = 'signTransaction',\r\n SendTransaction = 'sendTransaction',\r\n}\r\n\r\nexport enum AssetType {\r\n TOKEN = 'token',\r\n NFT = 'nft'\r\n}","import type { DBStore } from \"./datastore/db\";\r\nimport { AccountType, AssetType } from \"../utils/enums\";\r\nimport type { AccountDTO, AccountEntity, AddressDTO, AddressEntity, AssetEntity, AssetTransactionEntity, NftEntity, SessionEntity, TokenEntity, TransactionEntity, VaultDTO, VaultEntity } from \"../types/db.types\";\r\nimport { currentTimestamp } from \"../utils/common\";\r\n\r\nexport type DBEvent =\r\n | { type: 'tx_refresh'; }\r\n | { type: 'nft_refresh'; }\r\n | { type: 'token_added'; accountId: number; token: AssetEntity; }\r\n | { type: 'token_removed'; accountId: number; tokenId: string; }\r\n | { type: 'nft_deleted'; id: string; }\r\n\r\nexport type DBUpdateCallback = (event: DBEvent) => void;\r\n\r\nexport class WalletDB {\r\n\r\n private readonly store: DBStore;\r\n private updateCallback?: DBUpdateCallback;\r\n\r\n constructor(store: DBStore) {\r\n this.store = store;\r\n }\r\n\r\n public onUpdate(callback: DBUpdateCallback): void {\r\n this.updateCallback = callback;\r\n }\r\n\r\n private notify(event: DBEvent): void {\r\n this.updateCallback?.(event);\r\n }\r\n\r\n public async initSchema(): Promise<boolean> {\r\n return this.store.initSchema();\r\n }\r\n\r\n public async clearData(): Promise<void> {\r\n return this.store.clearData();\r\n }\r\n\r\n public async addLocalTransaction(tx: TransactionEntity): Promise<void> {\r\n try {\r\n await this.store.upsertTransaction(tx);\r\n this.notify({ type: 'tx_refresh' });\r\n } catch (error) {\r\n console.error(error);\r\n }\r\n }\r\n\r\n public async addAssetTransaction(assetTx: AssetTransactionEntity): Promise<void> {\r\n return this.store.upsertAssetTransaction(assetTx);\r\n }\r\n\r\n public async getLocalTransactions(account: number, tokenId?: string): Promise<TransactionEntity[] | undefined> {\r\n return this.store.getTransactions(account, tokenId);\r\n }\r\n\r\n public async getPageLocalTransactions(account: number, pageNum: number, pageSize: number, tokenId?: string): Promise<TransactionEntity[] | undefined> {\r\n return this.store.getPageTransactions(account, pageNum, pageSize, tokenId);\r\n }\r\n\r\n public async countLocalTransactions(account: number, tokenId?: string): Promise<number> {\r\n return this.store.countTransactions(account, tokenId);\r\n }\r\n\r\n public async clearLocalTransactions(account: number): Promise<void> {\r\n await this.store.clearTransactions(account);\r\n this.notify({ type: 'tx_refresh' });\r\n }\r\n\r\n public async saveToken(account: number, token: TokenEntity): Promise<void> {\r\n const asset: AssetEntity = {\r\n accountId: account,\r\n tokenIdHex: token.tokenIdHex,\r\n type: AssetType.TOKEN,\r\n addedTime: currentTimestamp()\r\n }\r\n await this.store.upsertAsset(asset);\r\n await this.store.upsertToken(token);\r\n this.notify({ type: 'token_added', accountId: account, token: asset });\r\n }\r\n\r\n public async getLocalTokens(account: number): Promise<AssetEntity[] | undefined> {\r\n return this.store.getTokens(account);\r\n }\r\n\r\n public async getToken(id: string): Promise<TokenEntity | undefined> {\r\n return this.store.getToken(id);\r\n }\r\n\r\n public async deleteToken(account: number, tokenId: string): Promise<void> {\r\n await this.removeAsset(account, tokenId);\r\n const count = await this.store.countAssetsById(tokenId);\r\n if (count == 0) {\r\n await this.store.deleteToken(tokenId);\r\n }\r\n this.notify({ type: 'token_removed', accountId: account, tokenId: tokenId });\r\n }\r\n\r\n public async saveNft(asset: AssetEntity, nft: NftEntity): Promise<void> {\r\n await this.store.upsertNft(nft);\r\n await this.saveAsset(asset, true);\r\n }\r\n\r\n public async getLocalNfts(account: number, pageNum: number, pageSize: number): Promise<AssetEntity[] | undefined> {\r\n return this.store.getNfts(account, pageNum, pageSize);\r\n }\r\n\r\n public async getLocalNft(id: string): Promise<NftEntity | undefined> {\r\n return this.store.getNft(id);\r\n }\r\n\r\n public async deleteNft(account: number, tokenId: string, notify = false): Promise<void> {\r\n await this.removeAsset(account, tokenId);\r\n const count = await this.store.countAssetsById(tokenId);\r\n if (count == 0) {\r\n await this.store.deleteNft(tokenId);\r\n this.notify({ type: 'nft_deleted', id: tokenId });\r\n }\r\n if (notify) {\r\n this.notify({ type: 'nft_refresh' });\r\n }\r\n }\r\n\r\n public async countLocalNfts(account: number): Promise<number> {\r\n return this.store.countNfts(account);\r\n }\r\n\r\n public async isNftExist(id: string): Promise<boolean> {\r\n return this.store.isNftExist(id);\r\n }\r\n\r\n public async saveAsset(asset: AssetEntity, notifyNft = false): Promise<void> {\r\n await this.store.upsertAsset(asset);\r\n if (notifyNft) {\r\n this.notify({ type: 'nft_refresh' });\r\n }\r\n }\r\n\r\n public async removeAsset(account: number, id: string): Promise<void> {\r\n return this.store.deleteAsset(account, id);\r\n }\r\n\r\n public async isAssetExistForAccount(account: number, id: string): Promise<boolean> {\r\n return this.store.isAssetExistForAccount(account, id);\r\n }\r\n\r\n public async saveAccount(account: AccountDTO): Promise<void> {\r\n const accountEntity: AccountEntity = {\r\n id: account.id,\r\n address: account.address,\r\n name: account.name,\r\n height: account.height,\r\n hidden: account.hidden,\r\n statusHash: account.statusHash,\r\n balance: JSON.stringify(account.balance),\r\n tokensBalance: JSON.stringify(account.tokensBalance)\r\n }\r\n return this.store.upsertAccount(accountEntity);\r\n }\r\n\r\n public async getAccounts(): Promise<AccountDTO[]> {\r\n const accs = await this.store.getAccounts();\r\n return accs.map(a => ({\r\n ...a,\r\n type: AccountType.DAPP,\r\n balance: JSON.parse(a.balance),\r\n tokensBalance: JSON.parse(a.tokensBalance)\r\n }));\r\n }\r\n\r\n public async countAccounts(): Promise<number> {\r\n return this.store.countAccounts();\r\n }\r\n\r\n public async updateAccountName(account: number, name: string): Promise<void> {\r\n return this.store.updateAccountName(account, name);\r\n }\r\n\r\n public async saveSession(session: SessionEntity): Promise<void> {\r\n return this.store.upsertSession(session);\r\n }\r\n\r\n public async getAccountSessions(accountId: number): Promise<SessionEntity[]> {\r\n return this.store.getSessionsByAccount(accountId);\r\n }\r\n\r\n public async removeSession(sessionId: string): Promise<void> {\r\n return this.store.deleteSession(sessionId);\r\n }\r\n\r\n public async saveAddress(address: AddressDTO): Promise<void> {\r\n const addressEntity: AddressEntity = {\r\n address: address.address,\r\n idx: address.idx,\r\n space: address.space,\r\n height: address.height,\r\n statusHash: address.statusHash,\r\n used: address.used,\r\n balance: JSON.stringify(address.balance),\r\n tokensBalance: JSON.stringify(address.tokensBalance)\r\n }\r\n return this.store.upsertAddress(addressEntity);\r\n }\r\n\r\n public async getReceiveAddresses(): Promise<AddressDTO[]> {\r\n const addrs = await this.store.getReceiveAddresses();\r\n return addrs.map(a => ({\r\n ...a,\r\n type: AccountType.MAIN,\r\n balance: JSON.parse(a.balance),\r\n tokensBalance: JSON.parse(a.tokensBalance)\r\n }));\r\n }\r\n\r\n public async getChangeAddresses(): Promise<AddressDTO[]> {\r\n const addrs = await this.store.getChangeAddresses();\r\n return addrs.map(a => ({\r\n ...a,\r\n type: AccountType.MAIN,\r\n balance: JSON.parse(a.balance),\r\n tokensBalance: JSON.parse(a.tokensBalance)\r\n }));\r\n }\r\n\r\n public async countAddresses(): Promise<number> {\r\n return this.store.countAddresses();\r\n }\r\n\r\n public async getVaults(): Promise<VaultDTO[]> {\r\n const vaults = await this.store.getVaults();\r\n return vaults.map(v => ({\r\n ...v,\r\n type: AccountType.VAULT,\r\n balance: JSON.parse(v.balance),\r\n tokensBalance: JSON.parse(v.tokensBalance)\r\n }));\r\n }\r\n\r\n public async saveVault(vault: VaultDTO): Promise<void> {\r\n const vaultEntity: VaultEntity = {\r\n address: vault.address,\r\n idx: vault.idx,\r\n block: vault.block,\r\n height: vault.height,\r\n statusHash: vault.statusHash,\r\n balance: JSON.stringify(vault.balance),\r\n tokensBalance: JSON.stringify(vault.tokensBalance)\r\n };\r\n return this.store.upsertVault(vaultEntity);\r\n }\r\n}\r\n","import type { NftEntity, TokenEntity } from \"../types/db.types\";\r\nimport { tokenIdToHex } from \"../utils/common\";\r\nimport type { WalletDB } from \"../persistence/wallet-db\";\r\n\r\nexport class WalletCache {\r\n\r\n private readonly walletDb: WalletDB;\r\n\r\n private readonly tokens = new Map<string, TokenEntity>();\r\n private readonly nfts = new Map<string, NftEntity>();\r\n\r\n public constructor(walletDb: WalletDB) {\r\n this.walletDb = walletDb;\r\n }\r\n\r\n public clear(): void {\r\n this.tokens.clear();\r\n this.nfts.clear();\r\n }\r\n\r\n public async getTokenById(id: string): Promise<TokenEntity | undefined> {\r\n id = tokenIdToHex(id);\r\n if (this.tokens.has(id)) {\r\n return this.tokens.get(id)!;\r\n }\r\n\r\n const token = await this.walletDb.getToken(id);\r\n if (token) {\r\n this.tokens.set(id, token);\r\n }\r\n return token;\r\n }\r\n\r\n public async getNftById(id: string): Promise<NftEntity | undefined> {\r\n id = tokenIdToHex(id);\r\n if (this.nfts.has(id)) {\r\n return this.nfts.get(id)!;\r\n }\r\n\r\n const nft = await this.walletDb.getLocalNft(id);\r\n if (nft) {\r\n this.nfts.set(id, nft);\r\n }\r\n return nft;\r\n }\r\n\r\n public removeToken(id: string): void {\r\n this.tokens.delete(tokenIdToHex(id));\r\n }\r\n\r\n public removeNft(id: string): void {\r\n this.nfts.delete(tokenIdToHex(id));\r\n }\r\n}","import type { RequestResponse} from \"@otoplo/electrum-client\";\r\nimport { ConnectionStatus, ElectrumClient, TransportScheme } from \"@otoplo/electrum-client\";\r\nimport type { BlockTip, IFirstUse, IListUnspentRecord, ITokenGenesis, ITokenListUnspent, ITokensBalance, ITokenUtxo, ITransaction, ITXHistory, IUtxo, RostrumParams, ServerFeatures } from \"../types/rostrum.types\";\r\nimport type { Balance } from \"../types/wallet.types\";\r\nimport { isTestnet } from \"../utils/common\";\r\nimport type { KVStore } from \"../persistence/datastore/kv\";\r\n\r\ntype RPCParameter = object | string | number | boolean | null;\r\n\r\nexport class RostrumService {\r\n\r\n private readonly kvStore: KVStore;\r\n\r\n private client?: ElectrumClient;\r\n\r\n public constructor(kvStore: KVStore) {\r\n this.kvStore = kvStore;\r\n }\r\n \r\n public getFeatures(): Promise<ServerFeatures> {\r\n return this.execute<ServerFeatures>('server.features');\r\n }\r\n\r\n public getBlockTip(): Promise<BlockTip> {\r\n return this.execute<BlockTip>('blockchain.headers.tip');\r\n }\r\n\r\n public getBalance(address: string): Promise<Balance> {\r\n return this.execute<Balance>('blockchain.address.get_balance', address, 'exclude_tokens');\r\n }\r\n\r\n public getTransactionsHistory(address: string, fromHeight = 0): Promise<ITXHistory[]> {\r\n return this.execute<ITXHistory[]>('blockchain.address.get_history', address, { from_height: fromHeight });\r\n }\r\n\r\n public getFirstUse(address: string): Promise<IFirstUse> {\r\n return this.execute<IFirstUse>('blockchain.address.get_first_use', address);\r\n }\r\n\r\n public async isAddressUsed(address: string): Promise<boolean> {\r\n try {\r\n const firstUse = await this.getFirstUse(address);\r\n return !!(firstUse.tx_hash && firstUse.tx_hash !== \"\");\r\n } catch (e) {\r\n if (e instanceof Error && e.message.includes(\"not found\")) {\r\n return false;\r\n }\r\n throw e;\r\n }\r\n }\r\n \r\n public getTransaction(id: string, verbose = true): Promise<ITransaction> {\r\n return this.execute<ITransaction>('blockchain.transaction.get', id, verbose);\r\n }\r\n\r\n public getUtxo(outpoint: string): Promise<IUtxo> {\r\n return this.execute<IUtxo>('blockchain.utxo.get', outpoint);\r\n }\r\n\r\n public getNexaUtxos(address: string): Promise<IListUnspentRecord[]> {\r\n return this.execute<IListUnspentRecord[]>('blockchain.address.listunspent', address, 'exclude_tokens');\r\n }\r\n \r\n public async getTokenUtxos(address: string, token: string): Promise<ITokenUtxo[]> {\r\n const listunspent = await this.execute<ITokenListUnspent>('token.address.listunspent', address, null, token);\r\n return listunspent.unspent;\r\n }\r\n\r\n public async getTokensBalance(address: string): Promise<Record<string, Balance>> {\r\n const tokensBalance = await this.execute<ITokensBalance>('token.address.get_balance', address);\r\n const balance: Record<string, Balance> = {};\r\n \r\n for (const cToken in tokensBalance.confirmed) {\r\n if (tokensBalance.confirmed[cToken] != 0) {\r\n balance[cToken] = { confirmed: BigInt(tokensBalance.confirmed[cToken]).toString(), unconfirmed: \"0\" }\r\n }\r\n }\r\n \r\n for (const uToken in tokensBalance.unconfirmed) {\r\n if (tokensBalance.unconfirmed[uToken] != 0) {\r\n if (balance[uToken]) {\r\n balance[uToken].unconfirmed = BigInt(tokensBalance.unconfirmed[uToken]).toString();\r\n } else {\r\n balance[uToken] = { confirmed: \"0\", unconfirmed: BigInt(tokensBalance.unconfirmed[uToken]).toString() }\r\n }\r\n }\r\n }\r\n \r\n return balance;\r\n }\r\n \r\n public getTokenGenesis(token: string): Promise<ITokenGenesis> {\r\n return this.execute<ITokenGenesis>('token.genesis.info', token);\r\n }\r\n\r\n public broadcast(txHex: string): Promise<string> {\r\n return this.execute<string>('blockchain.transaction.broadcast', txHex);\r\n }\r\n\r\n public subscribeHeaders(handler: (block: number) => void): Promise<Error | RequestResponse> {\r\n return this.client!.subscribe((response: any) => {\r\n const data = Array.isArray(response) ? response[0] : response;\r\n const height = typeof data?.height === 'number' ? data.height : 0;\r\n handler(height);\r\n }, 'blockchain.headers.subscribe');\r\n }\r\n\r\n public subscribeAddress(address: string, handler: (data: unknown) => void): Promise<Error | RequestResponse> {\r\n return this.client!.subscribe(handler, 'blockchain.address.subscribe', address);\r\n }\r\n \r\n public async getLatency(): Promise<number> {\r\n try {\r\n const start = Date.now();\r\n const res = await this.getBlockTip();\r\n if (res) {\r\n return Date.now() - start;\r\n }\r\n return 0;\r\n } catch {\r\n return 0;\r\n }\r\n }\r\n \r\n public async connect(params?: RostrumParams): Promise<void> {\r\n try {\r\n if (!params) {\r\n params = await this.getCurrentInstance();\r\n }\r\n\r\n this.client = new ElectrumClient(\"com.otoplo.wallet\", \"1.4.3\", params.host, params.port, params.scheme, 45*1000, 10*1000);\r\n await this.client.connect();\r\n } catch (e) {\r\n if (e instanceof Error) {\r\n console.info(e.message);\r\n } else {\r\n console.error(e);\r\n }\r\n throw e;\r\n }\r\n }\r\n \r\n public async disconnect(force?: boolean): Promise<boolean> {\r\n try {\r\n return await this.client?.disconnect(force) ?? false;\r\n } catch (e) {\r\n console.error(e)\r\n return false;\r\n }\r\n }\r\n \r\n private async execute<T>(method: string, ...parameters: RPCParameter[]): Promise<T> {\r\n await this.waitForConnection();\r\n const res = await this.client!.request(method, ...parameters);\r\n if (res instanceof Error) {\r\n throw res;\r\n }\r\n return res as T;\r\n }\r\n\r\n private waitForConnection(timeout = 5000): Promise<void> {\r\n const start = Date.now();\r\n\r\n return new Promise((resolve, reject) => {\r\n const check = (): void => {\r\n if (this.client?.connectionStatus == ConnectionStatus.CONNECTED) {\r\n return resolve();\r\n }\r\n if (Date.now() - start > timeout) {\r\n return reject(new Error(\"Rostrum Connection timeout\"));\r\n }\r\n setTimeout(check, 250);\r\n };\r\n\r\n check();\r\n });\r\n }\r\n\r\n public async getCurrentInstance(): Promise<RostrumParams> {\r\n const params = await this.kvStore.getRostrumParams();\r\n if (params) {\r\n return params;\r\n }\r\n return RostrumService.getPredefinedInstances()[0];\r\n }\r\n\r\n public static getPredefinedInstances(): RostrumParams[] { \r\n if (isTestnet()) {\r\n return [\r\n {\r\n scheme: TransportScheme.WSS,\r\n host: 'testnet-electrum.nexa.org',\r\n port: 30004,\r\n label: 'NexaOrg'\r\n }\r\n ];\r\n } else {\r\n return [\r\n {\r\n scheme: TransportScheme.WSS,\r\n host: 'rostrum.otoplo.com',\r\n port: 443,\r\n label: 'Otoplo'\r\n },\r\n {\r\n scheme: TransportScheme.WSS,\r\n host: 'electrum.nexa.org',\r\n port: 20004,\r\n label: 'NexaOrg'\r\n }\r\n ];\r\n }\r\n }\r\n}","import type { KeyPath } from \"../types\";\r\nimport type { AccountType, KeySpace } from \"./enums\";\r\n\r\nexport function keyPathToString(account: AccountType, type: KeySpace, index: number): string {\r\n return `${account}'/${type}/${index}`;\r\n}\r\n\r\nexport function stringToKeyPath(path: string): KeyPath {\r\n const parts = path.split('/');\r\n return {\r\n account: parseInt(parts[0].replace(\"'\", \"\")) as AccountType,\r\n type: parseInt(parts[1]) as KeySpace,\r\n index: parseInt(parts[2])\r\n };\r\n}","import { mnemonicToSeedSync } from \"@scure/bip39\";\r\nimport { HDPrivateKey } from \"libnexa-ts\";\r\nimport type { AccountType } from \"../utils/enums\";\r\nimport type { KeyPath } from \"../types/wallet.types\";\r\nimport { keyPathToString, stringToKeyPath } from \"../utils/keypath\";\r\n\r\nexport class KeyManager {\r\n\r\n private seed!: Uint8Array;\r\n private masterKey!: HDPrivateKey;\r\n private accountKeys = new Map<number, HDPrivateKey>();\r\n private walletKeys = new Map<string, HDPrivateKey>();\r\n\r\n public init(mnemonic: string | Uint8Array): void {\r\n this.seed = typeof mnemonic === \"string\" ? mnemonicToSeedSync(mnemonic) : mnemonic;\r\n this.masterKey = HDPrivateKey.fromSeed(this.seed).deriveChild(44, true).deriveChild(29223, true);\r\n }\r\n\r\n public reset(): void {\r\n if (!this.seed) {\r\n throw new Error(\"KeysManager not initialized\");\r\n }\r\n this.masterKey = HDPrivateKey.fromSeed(this.seed).deriveChild(44, true).deriveChild(29223, true);\r\n this.accountKeys.clear();\r\n this.walletKeys.clear();\r\n }\r\n\r\n private getAccountKey(account: AccountType): HDPrivateKey {\r\n let key = this.accountKeys.get(account);\r\n if (!key) {\r\n key = this.masterKey.deriveChild(account, true);\r\n this.accountKeys.set(account, key);\r\n }\r\n\r\n return key;\r\n }\r\n\r\n public getKey(keyPath: string | KeyPath): HDPrivateKey {\r\n const path = typeof keyPath === 'string'\r\n ? keyPath\r\n : keyPathToString(keyPath.account, keyPath.type, keyPath.index);\r\n\r\n let key = this.walletKeys.get(path);\r\n if (!key) {\r\n const { account, type, index } = typeof keyPath === 'string'\r\n ? stringToKeyPath(keyPath)\r\n : keyPath;\r\n const accountKey = this.getAccountKey(account);\r\n key = accountKey.deriveChild(type, false).deriveChild(index, false);\r\n this.walletKeys.set(path, key);\r\n }\r\n\r\n return key;\r\n }\r\n}","import { BufferUtils, GroupToken } from \"libnexa-ts\";\r\nimport type { TokenEntity } from \"../types/db.types\";\r\nimport { getAddressBuffer, isTestnet } from \"./common\";\r\n\r\nexport function getNiftyToken(): TokenEntity {\r\n return {\r\n name: 'NiftyArt',\r\n ticker: 'NIFTY',\r\n iconUrl: 'https://niftyart.cash/td/niftyicon.svg',\r\n parentGroup: '',\r\n token: isTestnet()\r\n ? 'nexatest:tq8r37lcjlqazz7vuvug84q2ev50573hesrnxkv9y6hvhhl5k5qqqnmyf79mx'\r\n : 'nexa:tr9v70v4s9s6jfwz32ts60zqmmkp50lqv7t0ux620d50xa7dhyqqqcg6kdm6f',\r\n tokenIdHex: isTestnet()\r\n ? '0e38fbf897c1d10bcce33883d40acb28fa7a37cc0733598526aecbdff4b50000'\r\n : 'cacf3d958161a925c28a970d3c40deec1a3fe06796fe1b4a7b68f377cdb90000',\r\n decimals: 0\r\n };\r\n}\r\n\r\nexport function fetchNiftyNFT(id: string): Promise<Uint8Array> {\r\n return performGet(getNiftyEndpoint() + id, 'raw');\r\n}\r\n\r\nexport function isNiftySubgroup(group: string): boolean {\r\n try {\r\n const addrBuf = getAddressBuffer(group);\r\n if (!GroupToken.isSubgroup(addrBuf)) {\r\n return false;\r\n }\r\n\r\n return BufferUtils.bufferToHex(addrBuf.subarray(0, 32)) === getNiftyToken().tokenIdHex;\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\nexport function fetchAssetDoc(url: string): Promise<any> {\r\n // it is possible that legacy token description is stored on IPFS, check for this\r\n // example: ipfs://bafkvmicdm2vdjgieqvk3s5ykqlddtzd42yuy7voum4cifpknjvhv3uarwu\r\n url = translateIfIpfsUrl(url);\r\n return performGet(url, 'json');\r\n}\r\n\r\nexport function fetchAssetBlob(url: string): Promise<Uint8Array> {\r\n // it is possible that NRC (Token / NFT) description is stored on IPFS, check for this\r\n // example: ipfs://bafkvmicdm2vdjgieqvk3s5ykqlddtzd42yuy7voum4cifpknjvhv3uarwu\r\n url = translateIfIpfsUrl(url);\r\n return performGet(url, 'raw');\r\n}\r\n\r\nexport function transformTokenIconUrl(icon: string, documentUrl: string): string {\r\n if (icon && typeof icon === 'string') {\r\n if (icon.startsWith('http')) {\r\n return icon.replace('http://', 'https://');\r\n }\r\n if (icon.startsWith('ipfs://')) {\r\n return icon;\r\n }\r\n const url = new URL(documentUrl);\r\n return `${url.origin}${icon}`;\r\n }\r\n return \"\";\r\n}\r\n\r\nexport function parseTokenDataUrl(data?: string): string | null {\r\n if (!data) {\r\n return null;\r\n }\r\n return translateIfIpfsUrl(data);\r\n}\r\n\r\nfunction translateIfIpfsUrl(url: string, gateway = \"https://ipfs.nebula.markets/\"): string {\r\n // if ipfs gateway is implemented properly, you will be able to trim\r\n // the ipfs:// from the url and append the url to the gateway path\r\n // see https://docs.ipfs.tech/concepts/ipfs-gateway/#path for more info\r\n if (url?.startsWith(\"ipfs://\")) {\r\n return gateway + url.substring(7);\r\n }\r\n return url;\r\n}\r\n\r\nfunction getNiftyEndpoint(): string {\r\n return `https://${isTestnet() ? 'testnet.' : ''}niftyart.cash/_public/`;\r\n}\r\n\r\nasync function performGet(url: string, responseType?: 'json' | 'raw'): Promise<any> {\r\n try {\r\n const response = await fetch(url);\r\n if (!response.ok) {\r\n throw new Error(`Failed to perform GET. status: ${response.status}`);\r\n }\r\n \r\n if (responseType === 'raw') {\r\n const arrayBuffer = await response.arrayBuffer();\r\n return new Uint8Array(arrayBuffer);\r\n } else {\r\n return await response.json();\r\n }\r\n } catch (e) {\r\n throw new Error(`Unexpected Error: ${e}`);\r\n }\r\n}\r\n","import { Address, AddressType, BufferUtils, GroupIdType, GroupToken, Networks } from \"libnexa-ts\";\r\nimport type { AssetEntity, NftEntity, TokenEntity } from \"../types/db.types\";\r\nimport { fetchAssetBlob, fetchAssetDoc, getNiftyToken, isNiftySubgroup, transformTokenIconUrl } from \"../utils/asset\";\r\nimport { currentTimestamp, getAddressBuffer, tokenHexToAddr, tokenIdToHex } from \"../utils/common\";\r\nimport { AssetType } from \"../utils/enums\";\r\nimport type { WalletDB } from \"../persistence/wallet-db\";\r\nimport type { RostrumService } from \"./rostrum\";\r\nimport type { WalletCache } from \"./cache\";\r\nimport JSZip from \"jszip\";\r\nimport type { AssetInfo, Balance } from \"../types/wallet.types\";\r\n\r\nexport class AssetService {\r\n\r\n private readonly walletDb: WalletDB;\r\n private readonly rostrumService: RostrumService;\r\n private readonly walletCache: WalletCache;\r\n\r\n constructor(walletDb: WalletDB, rostrumService: RostrumService, walletCache: WalletCache) {\r\n this.walletDb = walletDb;\r\n this.rostrumService = rostrumService;\r\n this.walletCache = walletCache;\r\n }\r\n\r\n public async getTokenInfo(token: string, checkCache = true): Promise<TokenEntity | undefined> {\r\n try {\r\n if (checkCache) {\r\n const cachedToken = await this.walletCache.getTokenById(token);\r\n if (cachedToken) {\r\n return cachedToken;\r\n }\r\n }\r\n\r\n const genesis = await this.rostrumService.getTokenGenesis(token);\r\n const groupId = BufferUtils.hexToBuffer(genesis.token_id_hex);\r\n let parent = \"\";\r\n let iconUrl = \"\";\r\n \r\n if (genesis.op_return_id == GroupIdType.NRC2 || genesis.op_return_id == GroupIdType.NRC3 || isNiftySubgroup(token)) {\r\n return undefined;\r\n }\r\n \r\n if (GroupToken.isSubgroup(groupId)) {\r\n parent = new Address(GroupToken.getParentGroupId(groupId), Networks.defaultNetwork, AddressType.GroupIdAddress).toString();\r\n }\r\n \r\n if (genesis.document_url) {\r\n try {\r\n if (genesis.op_return_id == GroupIdType.NRC1) {\r\n const token_zip = await fetchAssetBlob(genesis.document_url);\r\n const zip = await JSZip.loadAsync(token_zip);\r\n const info = zip.file('info.json');\r\n if (info) {\r\n const infoData = await info.async('string');\r\n const infoJson = JSON.parse(infoData);\r\n iconUrl = transformTokenIconUrl(infoJson[0]?.icon, genesis.document_url);\r\n }\r\n } else {\r\n const infoJson = await fetchAssetDoc(genesis.document_url);\r\n iconUrl = transformTokenIconUrl(infoJson[0]?.icon, genesis.document_url);\r\n }\r\n } catch (e) {\r\n console.error(\"Failed to load metadata\", e)\r\n }\r\n }\r\n \r\n const tokenEntity: TokenEntity = {\r\n token: genesis.group,\r\n tokenIdHex: genesis.token_id_hex,\r\n decimals: genesis.decimal_places ?? 0,\r\n parentGroup: parent,\r\n name: genesis.name ?? \"\",\r\n ticker: genesis.ticker ?? \"\",\r\n iconUrl: iconUrl\r\n };\r\n \r\n return tokenEntity;\r\n } catch (e) {\r\n console.error(e)\r\n return undefined;\r\n }\r\n }\r\n\r\n public async isNftToken(token: string): Promise<boolean> {\r\n try {\r\n if (isNiftySubgroup(token)) {\r\n return true;\r\n }\r\n\r\n const cachedToken = await this.walletCache.getNftById(token);\r\n if (cachedToken) {\r\n return true;\r\n }\r\n\r\n const genesis = await this.rostrumService.getTokenGenesis(token);\r\n if (genesis.op_return_id == GroupIdType.NRC3) {\r\n return true;\r\n }\r\n } catch (e) {\r\n console.error(e)\r\n }\r\n\r\n return false;\r\n }\r\n\r\n public async getAssetInfo(token: string): Promise<AssetInfo | undefined> {\r\n let asset: AssetInfo | undefined = await this.getTokenInfo(token);\r\n if (!asset) {\r\n const isNft = await this.isNftToken(token);\r\n if (isNft) {\r\n asset = {\r\n token: tokenHexToAddr(token),\r\n tokenIdHex: tokenIdToHex(token),\r\n decimals: 0,\r\n };\r\n }\r\n }\r\n return asset;\r\n }\r\n\r\n public async handleNftReceive(accountId: number, tokenIdHex: string, time: number): Promise<void> {\r\n const exist = await this.walletDb.isNftExist(tokenIdHex);\r\n if (exist) {\r\n const asset: AssetEntity = {\r\n accountId: accountId,\r\n tokenIdHex: tokenIdHex,\r\n type: AssetType.NFT,\r\n addedTime: time\r\n }\r\n await this.walletDb.saveAsset(asset, true);\r\n return;\r\n }\r\n\r\n const genesis = await this.rostrumService.getTokenGenesis(tokenIdHex);\r\n if (genesis.op_return_id == GroupIdType.NRC3) {\r\n const groupId = getAddressBuffer(tokenIdHex);\r\n if (GroupToken.isSubgroup(groupId)) {\r\n const parentGroupId = new Address(groupId.subarray(0, 32), Networks.defaultNetwork, AddressType.GroupIdAddress).toString();\r\n const parentGenesis = await this.rostrumService.getTokenGenesis(parentGroupId);\r\n if (parentGenesis?.op_return_id == GroupIdType.NRC2) {\r\n // parent is an NRC-2 collection, this is an NRC-3 NFT. The name of the collection and NRC-3 NFT belongs\r\n // to is the name of the NRC-2 collection.\r\n await this.saveNft(accountId, tokenIdHex, genesis.document_url ?? '', parentGroupId, time, parentGenesis?.name ?? \"\");\r\n }\r\n }\r\n } else if (isNiftySubgroup(tokenIdHex)) {\r\n // NiftyArt does not have collections, pass \"\" for the collection\r\n await this.saveNft(accountId, tokenIdHex, 'nifty', getNiftyToken().token, time, \"\");\r\n }\r\n }\r\n\r\n private async saveNft(account: number, hexId: string, source: string, parent: string, time: number, collection: string): Promise<void> {\r\n if (!source) {\r\n return;\r\n }\r\n\r\n try {\r\n const asset: AssetEntity = {\r\n accountId: account,\r\n tokenIdHex: hexId,\r\n type: AssetType.NFT,\r\n addedTime: time\r\n }\r\n const nftEntity: NftEntity = {\r\n parentGroup: parent,\r\n token: tokenHexToAddr(hexId),\r\n tokenIdHex: hexId,\r\n source: source,\r\n collection: collection\r\n }\r\n\r\n await this.walletDb.saveNft(asset, nftEntity);\r\n } catch (e) {\r\n console.error('failed to save NFT', e);\r\n }\r\n }\r\n\r\n public async fetchAndSaveTokens(accountId: number, tokenBalances: Record<string, Balance>): Promise<void> {\r\n for (const tokenId in tokenBalances) {\r\n const token = await this.getTokenInfo(tokenId);\r\n if (token) {\r\n await this.walletDb.saveToken(accountId, token);\r\n }\r\n }\r\n }\r\n\r\n public async syncNfts(accountId: number, tokensBalance: Record<string, Balance>): Promise<void> {\r\n const currentAssets = Object.keys(tokensBalance);\r\n const internalAssets = await this.walletDb.getLocalNfts(accountId, 1, 1000);\r\n\r\n const handleNftDelete = async (tokenId: string): Promise<void> => {\r\n await this.walletDb.deleteNft(accountId, tokenId, true);\r\n this.walletCache.removeNft(tokenId);\r\n }\r\n\r\n const staleAssets = internalAssets?.filter(a => !currentAssets.includes(a.tokenIdHex)) ?? [];\r\n for (const asset of staleAssets) {\r\n await handleNftDelete(asset.tokenIdHex);\r\n }\r\n\r\n for (const [token, balance] of Object.entries(tokensBalance)) {\r\n const tokenId = tokenIdToHex(token);\r\n const hasBalance = balance && BigInt(balance.confirmed) + BigInt(balance.unconfirmed) > 0n;\r\n const isAssetExist = internalAssets?.some(a => a.tokenIdHex == tokenId);\r\n if ((!hasBalance && !isAssetExist) || (hasBalance && isAssetExist)) {\r\n continue;\r\n }\r\n\r\n const isNft = await this.isNftToken(tokenId);\r\n if (!isNft) {\r\n continue;\r\n }\r\n \r\n if (!hasBalance && isAssetExist) {\r\n await handleNftDelete(tokenId);\r\n } else {\r\n await this.handleNftReceive(accountId, tokenId, currentTimestamp());\r\n }\r\n }\r\n }\r\n}","import type { PrivateKey, PublicKey, Script, UTXO } from \"libnexa-ts\";\r\nimport { Address, AddressType, Transaction, TransactionBuilder, UnitUtils } from \"libnexa-ts\";\r\nimport type { KeyManager } from \"./key\";\r\nimport type { RostrumService } from \"./rostrum\";\r\nimport type { AssetMovement, TransactionDTO, TransactionEntity, TransactionType } from \"../types/db.types\";\r\nimport { currentTimestamp, isNullOrEmpty, isValidNexaAddress, MAX_INT64, tokenAmountToAssetAmount, tokenIdToHex, VAULT_FIRST_BLOCK } from \"../utils/common\";\r\nimport type { WalletDB } from \"../persistence/wallet-db\";\r\nimport type { ITXHistory } from \"../types/rostrum.types\";\r\nimport type { AddressKey } from \"../types/wallet.types\";\r\n\r\nexport interface TxTemplateData {\r\n templateScript: Script;\r\n constraintScript: Script;\r\n visibleArgs: any[];\r\n publicKey: PublicKey;\r\n}\r\n\r\nexport interface TxOptions {\r\n isConsolidate?: boolean;\r\n templateData?: TxTemplateData;\r\n feeFromAmount?: boolean;\r\n}\r\n\r\nexport class TransactionService {\r\n\r\n private readonly rostrumService: RostrumService;\r\n private readonly keyManager: KeyManager;\r\n private readonly walletDb: WalletDB;\r\n\r\n private readonly MAX_INPUTS_OUTPUTS = 250;\r\n\r\n public constructor(rostrumService: RostrumService, keysManager: KeyManager, walletDb: WalletDB) {\r\n this.rostrumService = rostrumService;\r\n this.keyManager = keysManager;\r\n this.walletDb = walletDb;\r\n }\r\n\r\n public async broadcastTransaction(txHex: string): Promise<string> {\r\n return this.rostrumService.broadcast(txHex);\r\n }\r\n\r\n public async fetchTransactionsHistory(address: string, fromHeight: number): Promise<{txs: ITXHistory[], lastHeight: number}> {\r\n let maxHeight = fromHeight;\r\n \r\n const fromHeightFilter = fromHeight > 0 ? fromHeight + 1 : 0;\r\n const txHistory = await this.rostrumService.getTransactionsHistory(address, fromHeightFilter);\r\n \r\n for (const tx of txHistory) {\r\n maxHeight = Math.max(maxHeight, tx.height);\r\n }\r\n \r\n return {txs: txHistory, lastHeight: maxHeight};\r\n }\r\n\r\n public async fetchVaultTransactions(address: string): Promise<TransactionDTO[]> {\r\n const txHistory = await this.rostrumService.getTransactionsHistory(address, VAULT_FIRST_BLOCK);\r\n\r\n const transactions: Promise<TransactionDTO>[] = [];\r\n for (const tx of txHistory) {\r\n const txEntry = this.classifyTransaction(tx.tx_hash, [address]);\r\n transactions.push(txEntry);\r\n }\r\n\r\n return Promise.all(transactions);\r\n }\r\n\r\n public async classifyAndSaveTransaction(accountId: number, txHash: string, myAddresses: string[]): Promise<void> {\r\n const txDto = await this.classifyTransaction(txHash, myAddresses);\r\n txDto.accountId = accountId;\r\n\r\n const txEntity: TransactionEntity = {\r\n ...txDto,\r\n othersOutputs: JSON.stringify(txDto.othersOutputs),\r\n myOutputs: JSON.stringify(txDto.myOutputs),\r\n myInputs: JSON.stringify(txDto.myInputs)\r\n };\r\n\r\n const involvedAssets = new Set<string>();\r\n txDto.myInputs.forEach(m => m.assetId && involvedAssets.add(m.assetId));\r\n txDto.myOutputs.forEach(m => m.assetId && involvedAssets.add(m.assetId));\r\n\r\n for (const assetId of involvedAssets) {\r\n await this.walletDb.addAssetTransaction({\r\n accountId: accountId,\r\n assetId: assetId,\r\n txIdem: txDto.txIdem,\r\n time: txDto.time\r\n });\r\n }\r\n await this.walletDb.addLocalTransaction(txEntity);\r\n }\r\n\r\n private async classifyTransaction(txHash: string, myAddresses: string[]): Promise<TransactionDTO> {\r\n const t = await this.rostrumService.getTransaction(txHash);\r\n\r\n const myInputs: AssetMovement[] = [];\r\n const othersInputs: AssetMovement[] = [];\r\n const myOutputs: AssetMovement[] = [];\r\n const othersOutputs: AssetMovement[] = [];\r\n\r\n for (const vin of t.vin) {\r\n const movement: AssetMovement = {\r\n address: vin.addresses[0],\r\n nexaAmount: vin.value_satoshi.toString(),\r\n assetId: vin.token_id_hex ?? \"\",\r\n assetAmount: tokenAmountToAssetAmount(vin.groupQuantity)\r\n };\r\n if (myAddresses.includes(movement.address)) {\r\n myInputs.push(movement);\r\n } else {\r\n othersInputs.push(movement);\r\n }\r\n }\r\n\r\n for (const vout of t.vout) {\r\n if (isNullOrEmpty(vout.scriptPubKey.addresses)) continue;\r\n const movement: AssetMovement = {\r\n address: vout.scriptPubKey.addresses[0],\r\n nexaAmount: vout.value_satoshi.toString(),\r\n assetId: vout.scriptPubKey.token_id_hex ?? \"\",\r\n assetAmount: tokenAmountToAssetAmount(vout.scriptPubKey.groupQuantity)\r\n };\r\n if (myAddresses.includes(movement.address)) {\r\n myOutputs.push(movement);\r\n } else {\r\n othersOutputs.push(movement);\r\n }\r\n }\r\n\r\n let type: TransactionType;\r\n if (myInputs.length === 0) {\r\n type = 'receive';\r\n } else if (myOutputs.length === 0) {\r\n type = 'send';\r\n } else if (othersInputs.length === 0 && othersOutputs.length === 0) {\r\n type = 'self';\r\n } else if (othersInputs.length === 0 && othersOutputs.length > 0) {\r\n type = 'send';\r\n } else if (othersInputs.length > 0 && othersOutputs.length === 0) {\r\n type = 'receive';\r\n } else {\r\n type = 'swap';\r\n }\r\n\r\n const isConfirmed = t.height > 0;\r\n const txDto: TransactionDTO = {\r\n accountId: 0, // Will be set in classifyAndSaveTransaction\r\n txId: t.txid,\r\n txIdem: t.txidem,\r\n time: isConfirmed ? t.time : currentTimestamp(),\r\n height: isConfirmed ? t.height : 0,\r\n type: type,\r\n fee: t.fee_satoshi.toString(),\r\n othersOutputs: type == 'send' || type == 'swap' ? othersOutputs : [],\r\n myOutputs: myOutputs,\r\n myInputs: myInputs\r\n };\r\n\r\n return txDto;\r\n }\r\n\r\n public async buildAndSignTransferTransaction(\r\n from: AddressKey[],\r\n toAddr: string,\r\n toChange: string,\r\n amount: string,\r\n feeFromAmount?: boolean,\r\n token?: string,\r\n feePerByte?: number,\r\n data?: string\r\n ): Promise<Transaction> {\r\n const txOptions: TxOptions = {\r\n feeFromAmount: feeFromAmount\r\n }\r\n \r\n const txBuilder = this.prepareTransaction(toAddr, amount, token, data);\r\n if (feePerByte) {\r\n txBuilder.feePerByte(feePerByte);\r\n }\r\n\r\n let tokenPrivKeys = new Map<string, PrivateKey>();\r\n if (token) {\r\n tokenPrivKeys = await this.populateTokenInputsAndChange(txBuilder, from, toChange, token, BigInt(amount));\r\n }\r\n const privKeys = await this.populateNexaInputsAndChange(txBuilder, from, toChange, txOptions);\r\n tokenPrivKeys.forEach((v, k) => privKeys.set(k, v));\r\n\r\n return await this.finalizeTransaction(txBuilder, Array.from(privKeys.values()));\r\n }\r\n\r\n public async buildAndSignConsolidateTransaction(from: AddressKey[], toChange: string, templateData?: TxTemplateData): Promise<Transaction> {\r\n const txOptions: TxOptions = {\r\n isConsolidate: true,\r\n templateData: templateData\r\n }\r\n \r\n const txBuilder = new TransactionBuilder();\r\n const privKeys = await this.populateNexaInputsAndChange(txBuilder, from, toChange, txOptions);\r\n \r\n return this.finalizeTransaction(txBuilder, Array.from(privKeys.values()));\r\n }\r\n\r\n private prepareTransaction(toAddr: string, amount: string, token?: string, data?: string): TransactionBuilder {\r\n if (!isValidNexaAddress(toAddr) && !isValidNexaAddress(toAddr, AddressType.PayToPublicKeyHash)) {\r\n throw new Error('Invalid Address.');\r\n }\r\n if ((token && BigInt(amount) < 1n) || (!token && parseInt(amount) < Transaction.DUST_AMOUNT)) {\r\n throw new Error(\"The amount is too low.\");\r\n }\r\n if ((token && BigInt(amount) > MAX_INT64) || (!token && parseInt(amount) > Transaction.MAX_MONEY)) {\r\n throw new Error(\"The amount is too high.\");\r\n }\r\n \r\n const builder = new TransactionBuilder();\r\n if (data) {\r\n builder.addData(data);\r\n }\r\n\r\n if (token) {\r\n if (!isValidNexaAddress(token, AddressType.GroupIdAddress)) {\r\n throw new Error('Invalid Token ID');\r\n }\r\n if (Address.getOutputType(toAddr) === 0) {\r\n throw new Error('Token must be sent to script template address');\r\n }\r\n builder.to(toAddr, Transaction.DUST_AMOUNT, token, BigInt(amount))\r\n } else {\r\n builder.to(toAddr, amount);\r\n }\r\n \r\n return builder;\r\n }\r\n\r\n private async populateNexaInputsAndChange(txBuilder: TransactionBuilder, from: AddressKey[], toChange: string, options: TxOptions): Promise<Map<string, PrivateKey>> {\r\n const allKeys = from.filter(k => BigInt(k.balance.confirmed) + BigInt(k.balance.unconfirmed) > 0n);\r\n if (isNullOrEmpty(allKeys)) {\r\n throw new Error(\"Not enough Nexa balance.\");\r\n }\r\n \r\n const usedKeys = new Map<string, PrivateKey>();\r\n const origAmount = options.isConsolidate ? 0 : Number(txBuilder.transaction.outputs.find(out => out.value > 0n)!.value);\r\n \r\n for (const key of allKeys) {\r\n const utxos = await this.rostrumService.getNexaUtxos(key.address);\r\n for (const utxo of utxos) {\r\n const input: UTXO = {\r\n outpoint: utxo.outpoint_hash,\r\n address: key.address,\r\n satoshis: utxo.value,\r\n templateData: options.templateData\r\n }\r\n txBuilder.from(input);\r\n \r\n if (!usedKeys.has(key.address)) {\r\n const hdkey = this.keyManager.getKey(key.keyPath);\r\n usedKeys.set(key.address, hdkey.privateKey);\r\n }\r\n \r\n if (options.isConsolidate) {\r\n txBuilder.change(toChange);\r\n if (txBuilder.transaction.inputs.length > this.MAX_INPUTS_OUTPUTS) {\r\n return usedKeys;\r\n }\r\n } else {\r\n const tx = txBuilder.transaction;\r\n if (tx.inputs.length > this.MAX_INPUTS_OUTPUTS) {\r\n throw new Error(\"Too many inputs. Consider consolidate transactions or reduce the send amount.\");\r\n }\r\n \r\n const unspent = tx.getUnspentValue();\r\n if (unspent < 0n) {\r\n continue;\r\n }\r\n \r\n if (unspent == 0n && options.feeFromAmount) {\r\n const txFee = tx.estimateRequiredFee();\r\n tx.updateOutputAmount(0, origAmount - txFee);\r\n return usedKeys;\r\n }\r\n \r\n txBuilder.change(toChange);\r\n if (options.feeFromAmount) {\r\n const hasChange = tx.getChangeOutput();\r\n let txFee = tx.estimateRequiredFee();\r\n tx.updateOutputAmount(0, origAmount - txFee);\r\n \r\n // edge case where change added after update\r\n if (!hasChange && tx.getChangeOutput()) {\r\n txFee = tx.estimateRequiredFee();\r\n tx.updateOutputAmount(0, origAmount - txFee);\r\n }\r\n }\r\n \r\n // check again after change output manipulation\r\n if (tx.getUnspentValue() < tx.estimateRequiredFee()) {\r\n // try to add more utxos to satisfy the minimum fee\r\n continue;\r\n }\r\n \r\n return usedKeys;\r\n }\r\n }\r\n }\r\n \r\n if (options.isConsolidate) {\r\n if (usedKeys.size > 0) {\r\n return usedKeys;\r\n }\r\n throw new Error(\"Not enough Nexa balance.\");\r\n }\r\n \r\n const err = {\r\n errorMsg: \"Not enough Nexa balance.\",\r\n amount: UnitUtils.formatNEXA(txBuilder.transaction.outputs[0].value),\r\n fee: UnitUtils.formatNEXA(txBuilder.transaction.estimateRequiredFee())\r\n }\r\n \r\n throw new Error(JSON.stringify(err));\r\n }\r\n\r\n private async populateTokenInputsAndChange(txBuilder: TransactionBuilder, from: AddressKey[], toChange: string, token: string, outTokenAmount: bigint): Promise<Map<string, PrivateKey>> {\r\n const tokenHex = tokenIdToHex(token);\r\n const allKeys = from.filter(k => Object.keys(k.tokensBalance).includes(tokenHex));\r\n \r\n if (isNullOrEmpty(allKeys)) {\r\n throw new Error(\"Not enough token balance.\");\r\n }\r\n \r\n const usedKeys = new Map<string, PrivateKey>();\r\n let inTokenAmount = 0n;\r\n \r\n for (const key of allKeys) {\r\n const utxos = await this.rostrumService.getTokenUtxos(key.address, token);\r\n for (const utxo of utxos) {\r\n if (BigInt(utxo.token_amount) < 0n) {\r\n continue;\r\n }\r\n txBuilder.from({\r\n outpoint: utxo.outpoint_hash,\r\n address: key.address,\r\n satoshis: utxo.value,\r\n groupId: utxo.group,\r\n groupAmount: BigInt(utxo.token_amount),\r\n });\r\n \r\n inTokenAmount = inTokenAmount + BigInt(utxo.token_amount);\r\n if (!usedKeys.has(key.address)) {\r\n const hdkey = this.keyManager.getKey(key.keyPath);\r\n usedKeys.set(key.address, hdkey.privateKey);\r\n }\r\n \r\n if (inTokenAmount > MAX_INT64) {\r\n throw new Error(\"Token inputs exceeded max amount. Consider sending in small chunks\");\r\n }\r\n if (txBuilder.transaction.inputs.length > this.MAX_INPUTS_OUTPUTS) {\r\n throw new Error(\"Too many inputs. Consider consolidating transactions or reduce the send amount.\");\r\n }\r\n \r\n if (inTokenAmount == outTokenAmount) {\r\n return usedKeys;\r\n }\r\n if (inTokenAmount > outTokenAmount) {\r\n // change\r\n txBuilder.to(toChange, Transaction.DUST_AMOUNT, token, inTokenAmount - outTokenAmount);\r\n return usedKeys;\r\n }\r\n }\r\n }\r\n \r\n throw new Error(\"Not enough token balance\");\r\n }\r\n\r\n private async finalizeTransaction(tx: TransactionBuilder, privKeys: PrivateKey[]): Promise<Transaction> {\r\n const tip = await this.rostrumService.getBlockTip();\r\n return tx.lockUntilBlockHeight(tip.height).sign(privKeys).build();\r\n }\r\n\r\n public printTransactionJson(tx?: Transaction | null): string {\r\n if (!tx) {\r\n return \"\";\r\n }\r\n const obj = {\r\n ...tx.toObject(),\r\n hex: tx.toString(),\r\n }\r\n return JSON.stringify(obj, null, 2)\r\n }\r\n}","import { gcm } from \"@noble/ciphers/aes.js\";\r\nimport { argon2idAsync } from \"@noble/hashes/argon2.js\";\r\nimport { generateMnemonic, validateMnemonic } from \"@scure/bip39\";\r\nimport { wordlist } from \"@scure/bip39/wordlists/english.js\";\r\nimport { BufferUtils } from \"libnexa-ts\";\r\n\r\nexport function generateNewMnemonic(size: 12 | 24 = 12): string {\r\n return generateMnemonic(wordlist, size === 24 ? 256 : 128);\r\n}\r\n\r\nexport function isMnemonicValid(mnemonic: string): boolean {\r\n return validateMnemonic(mnemonic, wordlist);\r\n}\r\n\r\nasync function deriveKey(password: string, salt: Uint8Array): Promise<Uint8Array> {\r\n const start = performance.now();\r\n const key = await argon2idAsync(password, salt, { t: 2, m: 19456, p: 1, dkLen: 32 });\r\n console.log(performance.now() - start);\r\n return key;\r\n}\r\n\r\nexport async function encryptMnemonic(phrase: string, password: string): Promise<string> {\r\n const salt = BufferUtils.getRandomBuffer(16);\r\n const iv = BufferUtils.getRandomBuffer(12);\r\n const data = BufferUtils.utf8ToBuffer(phrase);\r\n\r\n const key = await deriveKey(password, salt);\r\n\r\n const cipher = gcm(key, iv).encrypt(data);\r\n const encBuf = BufferUtils.concat([salt, iv, cipher]);\r\n return BufferUtils.bufferToBase64(encBuf);\r\n}\r\n\r\nasync function decryptMnemonic(encSeed: string, password: string): Promise<string> {\r\n const encBuf = BufferUtils.base64ToBuffer(encSeed);\r\n\r\n const salt = encBuf.subarray(0, 16);\r\n const iv = encBuf.subarray(16, 28);\r\n const cipher = encBuf.subarray(28);\r\n\r\n const key = await deriveKey(password, salt);\r\n\r\n const data = gcm(key, iv).decrypt(cipher);\r\n return BufferUtils.bufferToUtf8(data);\r\n}\r\n\r\nexport async function validateAndDecryptMnemonic(encSeed: string, password: string): Promise<string | false> {\r\n try {\r\n if (encSeed) {\r\n const decMn = await decryptMnemonic(encSeed, password);\r\n if (decMn && isMnemonicValid(decMn)) {\r\n return decMn;\r\n }\r\n }\r\n return false;\r\n } catch {\r\n return false;\r\n }\r\n}","import type { Price } from \"../types/wallet.types\";\r\n\r\nconst currencySymbols = {\r\n usd: \"$\",\r\n eur: \"€\",\r\n gbp: \"£\",\r\n cny: \"¥\",\r\n jpy: \"¥\",\r\n aud: \"A$\",\r\n cad: \"C$\",\r\n chf: \"Fr\"\r\n} as const;\r\n\r\ntype Currency = keyof typeof currencySymbols;\r\n\r\nexport const currencies = Object.keys(currencySymbols);\r\n\r\nexport async function getNexaPrices(): Promise<Record<string, number>> {\r\n const vs_currencies = currencies.join(\",\");\r\n \r\n const res = await fetch(`https://api.coingecko.com/api/v3/simple/price?ids=nexacoin&include_24hr_change=true&vs_currencies=${vs_currencies}`);\r\n if (!res.ok) {\r\n throw new Error(\"Failed to fetch price\");\r\n }\r\n\r\n const data = await res.json();\r\n return data.nexacoin || {};\r\n}\r\n\r\nexport function getCurrencySymbol(currency: Currency): string {\r\n return currencySymbols[currency] || currency;\r\n}\r\n\r\nexport function initializePrices(): Record<string, Price> {\r\n const prices: Record<string, Price> = {};\r\n currencies.forEach(currency => {\r\n prices[currency] = { value: 0, change: 0 };\r\n });\r\n return prices;\r\n}","import type { PublicKey, ScriptElement} from \"libnexa-ts\";\nimport { Address, BNExtended, Hash, Opcode, Script, ScriptOpcode } from \"libnexa-ts\";\r\n\r\nexport function getVaultTemplate(): Script {\r\n return Script.empty()\r\n .add(Opcode.OP_FROMALTSTACK).add(Opcode.OP_DROP)\r\n .add(Opcode.OP_FROMALTSTACK).add(Opcode.OP_CHECKLOCKTIMEVERIFY).add(Opcode.OP_DROP)\r\n .add(Opcode.OP_FROMALTSTACK).add(Opcode.OP_CHECKSIGVERIFY);\r\n}\r\n\r\nexport function getVaultTemplateHash(): Uint8Array {\r\n const template = getVaultTemplate();\r\n return Hash.sha256ripemd160(template.toBuffer());\r\n}\r\n\r\nexport function generateVaultConstraint(pubKey: PublicKey): Script {\r\n return Script.empty().add(pubKey.toBuffer());\r\n}\r\n\r\nexport function getVaultConstraintHash(pubKey: PublicKey): Uint8Array {\r\n const constraint = generateVaultConstraint(pubKey);\r\n return Hash.sha256ripemd160(constraint.toBuffer());\r\n}\r\n\r\nexport function generateVaultVisibleArgs(args: number[]): ScriptElement[] {\r\n return args.map(arg => arg <= 16 ? ScriptOpcode.smallInt(arg) : BNExtended.fromNumber(arg).toScriptNumBuffer());\r\n}\r\n\r\nexport function generateVaultAddress(pubKey: PublicKey, args: number[]): string | undefined {\r\n if (args.length !== 2) {\r\n return undefined;\r\n }\r\n\r\n const templateHash = getVaultTemplateHash();\r\n const constraintHash = getVaultConstraintHash(pubKey);\r\n const visibleArgs = generateVaultVisibleArgs(args);\r\n const address = Address.fromScriptTemplate(templateHash, constraintHash, visibleArgs);\r\n return address.toString();\r\n}","import { DAppProvider } from \"wallet-comms-sdk\";\r\nimport type { SessionInfo, AccountDTO, KeyPath, AppNotification, DappRpcRequest } from \"../types\";\r\nimport type { WalletDB } from \"../persistence\";\r\nimport { AccountType, KeySpace, MAIN_WALLET_ID, SessionRequestType } from \"../utils\";\r\nimport { Networks } from \"libnexa-ts\";\r\nimport type { KeyManager } from \"./key\";\r\n\r\ntype MethodHandler = {\r\n resolve: (value: any) => void;\r\n reject: (value: any) => void;\r\n}\r\n\r\nexport type SessionEvent =\r\n | { type: 'session_added'; accountId: number; sessionInfo: SessionInfo }\r\n | { type: 'session_removed'; accountId: number; sessionId: string }\r\n | { type: 'sessions_cleared', accountId: number }\r\n | { type: 'new_notification'; notification: AppNotification }\r\n | { type: 'new_request'; request: DappRpcRequest };\r\n\r\nexport type SessionUpdateCallback = (event: SessionEvent) => void;\r\n\r\nexport class SessionManager {\r\n\r\n private readonly walletDb: WalletDB;\r\n private readonly keyManager: KeyManager;\r\n\r\n private readonly providers: Map<number, Map<string, DAppProvider>>;\r\n private readonly handlers: Map<string, MethodHandler>;\r\n\r\n private removeOnClose: boolean;\r\n\r\n private updateCallback?: SessionUpdateCallback;\r\n \r\n public constructor(walletDb: WalletDB, keyManager: KeyManager) {\r\n this.walletDb = walletDb;\r\n this.keyManager = keyManager;\r\n this.providers = new Map();\r\n this.handlers = new Map();\r\n this.removeOnClose = true;\r\n }\r\n\r\n public onUpdate(callback: SessionUpdateCallback): void {\r\n this.updateCallback = callback;\r\n }\r\n\r\n private notify(event: SessionEvent): void {\r\n this.updateCallback?.(event);\r\n }\r\n\r\n public getHandler(request: string): MethodHandler | undefined {\r\n return this.handlers.get(request);\r\n }\r\n\r\n public add(account: AccountDTO, provider: DAppProvider, sessionInfo: SessionInfo): void {\r\n if (!this.providers.has(account.id)) {\r\n this.providers.set(account.id, new Map());\r\n }\r\n\r\n const sessionId = sessionInfo.details.sessionId;\r\n const accountSessions = this.providers.get(account.id)!;\r\n\r\n this.registerHandlers(account, provider, sessionId);\r\n accountSessions.set(sessionId, provider);\r\n this.notify({ type: 'session_added', accountId: account.id, sessionInfo });\r\n }\r\n\r\n public remove(accountId: number, sessionId: string): void {\r\n const sessionMap = this.providers.get(accountId);\r\n if (sessionMap) {\r\n const provider = sessionMap.get(sessionId);\r\n if (provider) {\r\n provider.disconnect();\r\n sessionMap.delete(sessionId);\r\n }\r\n if (sessionMap.size === 0) {\r\n this.providers.delete(accountId);\r\n }\r\n }\r\n this.notify({ type: 'session_removed', accountId, sessionId });\r\n }\r\n\r\n public async reload(accounts: Map<number, AccountDTO>): Promise<void> {\r\n for (const account of accounts.values()) {\r\n if (account.id == MAIN_WALLET_ID) {\r\n continue;\r\n }\r\n const storedSessions = await this.walletDb.getAccountSessions(account.id);\r\n const currentSessions = this.providers.get(account.id);\r\n\r\n const loadedSessions = storedSessions.map(async (session) => {\r\n if (currentSessions?.has(session.sessionId)) {\r\n return;\r\n }\r\n\r\n let provider;\r\n try {\r\n provider = new DAppProvider(session.uri);\r\n const details = provider.getSessionInfo();\r\n await provider.connect(3000);\r\n const appInfo = await provider.getAppInfo(2000);\r\n await provider.joinSession(account.address, 2000);\r\n const messages = await provider.fetchPendingMessages();\r\n for (const msg of messages) {\r\n this.notify({\r\n type: 'new_notification',\r\n notification: {\r\n id: crypto.randomUUID(),\r\n createdAt: msg.createdAt,\r\n type: 'web3',\r\n title: 'Request pending approval',\r\n message: `A connected dApp (${appInfo.name}) has requested an action from your Account: ${account.name}. Review the request details before approving or rejecting.`,\r\n action: {\r\n type: 'DAPP_REQUEST',\r\n account: account.id,\r\n sessionId: details.sessionId,\r\n payload: msg.message\r\n }\r\n }\r\n });\r\n }\r\n return { account: account, provider, metadata: { details, appInfo } };\r\n } catch (error) {\r\n console.error(`Failed to reload session ${session.sessionId}`, error);\r\n provider?.disconnect();\r\n await this.walletDb.removeSession(session.sessionId);\r\n }\r\n });\r\n\r\n const results= await Promise.allSettled(loadedSessions);\r\n for (const result of results) {\r\n if (result.status === 'fulfilled' && result.value) {\r\n this.add(result.value.account, result.value.provider, result.value.metadata);\r\n }\r\n }\r\n }\r\n }\r\n \r\n public clear(): void {\r\n try {\r\n this.removeOnClose = false;\r\n for (const [accountId, sessions] of this.providers) {\r\n for (const [,provider] of sessions) {\r\n provider.disconnect();\r\n }\r\n sessions.clear();\r\n this.notify({ type: 'sessions_cleared', accountId });\r\n }\r\n this.providers.clear();\r\n } finally {\r\n this.removeOnClose = true;\r\n }\r\n }\r\n\r\n public async revoke(accountId: number, sessionId: string): Promise<void> {\r\n const sessionMap = this.providers.get(accountId);\r\n if (sessionMap) {\r\n const provider = sessionMap.get(sessionId);\r\n if (provider) {\r\n await provider.revokeSession();\r\n }\r\n }\r\n }\r\n\r\n public async replayMessage(accountId: number, sessionId: string, payload: string): Promise<void> {\r\n const sessionMap = this.providers.get(accountId);\r\n if (sessionMap) {\r\n const provider = sessionMap.get(sessionId);\r\n if (provider) {\r\n await provider.replayMessage(payload);\r\n }\r\n }\r\n }\r\n\r\n private registerHandlers(account: AccountDTO, provider: DAppProvider, sessionId: string): void {\r\n provider.onSessionDelete((): Promise<void> => {\r\n return this.walletDb.removeSession(sessionId);\r\n });\r\n\r\n provider.onClose((): void => {\r\n if (this.removeOnClose) {\r\n this.remove(account.id, sessionId);\r\n }\r\n });\r\n\r\n const handleRequest = <T>(type: SessionRequestType, request: unknown): Promise<T> => {\r\n return new Promise<T>((resolve, reject) => {\r\n this.handlers.set(type, { resolve, reject });\r\n this.notify({ type: 'new_request', request: { type, accountId: account.id, sessionId, request } });\r\n });\r\n }\r\n\r\n provider.onSignMessage(signMsgReq => {\r\n return handleRequest(SessionRequestType.SignMessage, signMsgReq);\r\n });\r\n\r\n provider.onAddToken(addTokenReq => {\r\n return handleRequest(SessionRequestType.AddToken, addTokenReq);\r\n });\r\n\r\n provider.onSendTransaction(sendTransactionReq => {\r\n return handleRequest(SessionRequestType.SendTransaction, sendTransactionReq);\r\n });\r\n\r\n provider.onSignTransaction(signTransactionReq => {\r\n return handleRequest(SessionRequestType.SignTransaction, signTransactionReq);\r\n });\r\n\r\n provider.onGetAccount(() => {\r\n const path: KeyPath = { account: AccountType.DAPP, type: KeySpace.RECEIVE, index: account.id };\r\n return {\r\n name: account.name,\r\n address: account.address,\r\n pubkey: this.keyManager.getKey(path).publicKey.toString(),\r\n blockchain: \"nexa\",\r\n network: Networks.defaultNetwork.name,\r\n capabilities: {\r\n addToken: true,\r\n sendTransaction: true,\r\n signMessage: true,\r\n signTransaction: true\r\n }\r\n }\r\n });\r\n }\r\n}","import type { Input, PrivateKey} from \"libnexa-ts\";\r\nimport { BufferUtils, Hash, Opcode, Output, OutputSighashType, Script, ScriptFactory, SighashType, Transaction, TxSigner } from \"libnexa-ts\";\r\nimport type { KeyManager } from \"./key\";\r\nimport type { RostrumService } from \"./rostrum\";\r\nimport type { AddressKey, AssetMovement, MovementDetails, TransactionDetails } from \"../types\";\r\nimport { tokenAmountToAssetAmount, tokenIdToHex } from \"../utils\";\r\nimport type { AssetService } from \"./asset\";\r\n\r\ninterface TransactionContext {\r\n address: string;\r\n privateKey: PrivateKey;\r\n txDetails: TransactionDetails;\r\n myInputs: Map<number, AssetMovement>;\r\n myOutputs: Map<number, AssetMovement>;\r\n involvedAssets: Set<string>;\r\n inputsToSign: Set<number>;\r\n coveredOutputs: Set<number>;\r\n allMyOutputsCovered: boolean;\r\n}\r\n\r\nexport class TransactionTransformer {\r\n\r\n private readonly rostrumService: RostrumService;\r\n private readonly keyManager: KeyManager;\r\n private readonly assetService: AssetService;\r\n\r\n public constructor(rostrumService: RostrumService, keyManager: KeyManager, assetService: AssetService) {\r\n this.rostrumService = rostrumService;\r\n this.keyManager = keyManager;\r\n this.assetService = assetService;\r\n }\r\n\r\n public async transformRawTransaction(hex: string, addressKey: AddressKey): Promise<TransactionDetails> {\r\n const context = this.createContext(hex, addressKey);\r\n\r\n await this.processInputs(context);\r\n this.processOutputs(context);\r\n this.signInputs(context);\r\n await this.processAssetMovements(context);\r\n\r\n return context.txDetails;\r\n }\r\n\r\n private createContext(hex: string, addressKey: AddressKey): TransactionContext {\r\n try {\r\n return {\r\n address: addressKey.address,\r\n privateKey: this.keyManager.getKey(addressKey.keyPath).privateKey,\r\n txDetails: {\r\n tx: new Transaction(hex),\r\n send: [],\r\n receive: []\r\n },\r\n myInputs: new Map<number, AssetMovement>(),\r\n myOutputs: new Map<number, AssetMovement>(),\r\n involvedAssets: new Set<string>(),\r\n inputsToSign: new Set<number>(),\r\n coveredOutputs: new Set<number>(),\r\n allMyOutputsCovered: false,\r\n };\r\n } catch {\r\n throw new Error(\"Invalid transaction format.\");\r\n }\r\n }\r\n\r\n private async processInputs(context: TransactionContext): Promise<void> {\r\n const promises = [];\r\n for (let i = 0; i < context.txDetails.tx.inputs.length; i++) {\r\n const p = this.processInput(context, i);\r\n promises.push(p);\r\n }\r\n await Promise.all(promises);\r\n }\r\n\r\n private async processInput(context: TransactionContext, index: number): Promise<void> {\r\n const input = context.txDetails.tx.inputs[index];\r\n const utxo = await this.rostrumService.getUtxo(BufferUtils.bufferToHex(input.outpoint));\r\n if (utxo.status == \"spent\") {\r\n throw new Error(\"Input UTXO is already spent.\");\r\n }\r\n\r\n input.output = new Output(utxo.amount, utxo.scriptpubkey);\r\n if (input.output.address == context.address) {\r\n const assetId = utxo.token_id_hex || \"NEXA\";\r\n context.myInputs.set(index, {\r\n address: context.address,\r\n nexaAmount: utxo.amount.toString(),\r\n assetId: assetId,\r\n assetAmount: tokenAmountToAssetAmount(utxo.group_quantity) || utxo.amount.toString()\r\n });\r\n context.involvedAssets.add(assetId);\r\n \r\n if (input.scriptSig.isEmpty()) {\r\n context.inputsToSign.add(index);\r\n }\r\n }\r\n\r\n if (input.scriptSig.findPlaceholder() > 0) {\r\n context.inputsToSign.add(index);\r\n }\r\n }\r\n\r\n private processOutputs(context: TransactionContext): void {\r\n for (let i = 0; i < context.txDetails.tx.outputs.length; i++) {\r\n const output = context.txDetails.tx.outputs[i].toObject();\r\n if (output.address !== context.address) {\r\n continue;\r\n }\r\n\r\n const assetId = output.groupId ? tokenIdToHex(output.groupId) : \"NEXA\";\r\n const movement = {\r\n address: output.address,\r\n nexaAmount: output.value.toString(),\r\n assetId: assetId,\r\n assetAmount: tokenAmountToAssetAmount(output.groupAmount) || output.value.toString()\r\n };\r\n\r\n context.involvedAssets.add(assetId);\r\n context.myOutputs.set(i, movement);\r\n }\r\n }\r\n\r\n private signInputs(context: TransactionContext): void {\r\n if (context.inputsToSign.size == 0) {\r\n throw new Error(\"No inputs to sign.\");\r\n }\r\n\r\n for (const index of context.inputsToSign) {\r\n const input = context.txDetails.tx.inputs[index];\r\n const subscript = this.validateAndGetSubscript(input);\r\n\r\n if (input.scriptSig.isEmpty()) { // only p2pkt can be empty\r\n context.allMyOutputsCovered = true;\r\n const txSig = TxSigner.sign(context.txDetails.tx, index, SighashType.ALL, subscript, context.privateKey).toTxFormat();\r\n const constraint = Script.empty().add(context.privateKey.publicKey.toBuffer());\r\n input.scriptSig = ScriptFactory.buildScriptTemplateIn(undefined, constraint, Script.empty().add(txSig))\r\n } else {\r\n const placeholderIndex = input.scriptSig.findPlaceholder();\r\n const placeholder = input.scriptSig.chunks[placeholderIndex];\r\n const sigHashBuf = placeholder.buf!.subarray(64);\r\n const sigHashType = SighashType.fromBuffer(sigHashBuf);\r\n this.processSignatureCoverage(context, sigHashType);\r\n\r\n const txSig = TxSigner.sign(context.txDetails.tx, index, sigHashType, subscript, context.privateKey).toTxFormat(sigHashBuf);\r\n input.scriptSig.replaceChunk(placeholderIndex, Script.empty().add(txSig));\r\n }\r\n }\r\n\r\n if (!context.allMyOutputsCovered) {\r\n throw new Error(\"Some of interested outputs are not covered by signatures.\");\r\n }\r\n }\r\n\r\n private validateAndGetSubscript(input: Input): Script {\r\n if (input.output!.scriptPubKey.isPublicKeyTemplateOut()) {\r\n if (input.scriptSig.isEmpty() || input.scriptSig.isPublicKeyTemplateIn()) {\r\n return Script.empty().add(Opcode.OP_FROMALTSTACK).add(Opcode.OP_CHECKSIGVERIFY);\r\n }\r\n throw new Error(\"Invalid input script type.\");\r\n }\r\n \r\n if (input.output!.scriptPubKey.isScriptTemplateOut()) {\r\n if (!input.scriptSig.isScriptTemplateIn()) {\r\n throw new Error(\"Unsupported input script type.\");\r\n }\r\n\r\n const templateHash = input.output!.scriptPubKey.getTemplateHash() as Uint8Array;\r\n const templateBuf = input.scriptSig.chunks[0].buf!;\r\n if (BufferUtils.equals(templateHash, Hash.sha256ripemd160(templateBuf)) || BufferUtils.equals(templateHash, Hash.sha256sha256(templateBuf))) {\r\n return Script.fromBuffer(templateBuf);\r\n }\r\n\r\n throw new Error(\"Invalid input script template.\");\r\n }\r\n \r\n throw new Error(\"Unsupported prevout script type.\");\r\n }\r\n\r\n private processSignatureCoverage(context: TransactionContext, sigHashType: SighashType): void {\r\n if (context.allMyOutputsCovered) {\r\n return;\r\n }\r\n\r\n if (sigHashType.outType == OutputSighashType.TWO) {\r\n context.coveredOutputs.add(sigHashType.outData[0]);\r\n context.coveredOutputs.add(sigHashType.outData[1]);\r\n this.checkSignatureCoverage(context);\r\n } else if (sigHashType.outType == OutputSighashType.FIRSTN) {\r\n const n = sigHashType.outData[0];\r\n for (let i = 0; i < n; i++) {\r\n context.coveredOutputs.add(i);\r\n }\r\n this.checkSignatureCoverage(context);\r\n } else {\r\n context.allMyOutputsCovered = true;\r\n }\r\n }\r\n\r\n private checkSignatureCoverage(context: TransactionContext): void {\r\n if (context.allMyOutputsCovered) {\r\n return;\r\n }\r\n\r\n for (const i of context.myOutputs.keys()) {\r\n if (!context.coveredOutputs.has(i)) {\r\n return;\r\n }\r\n }\r\n context.allMyOutputsCovered = true;\r\n }\r\n\r\n private async processAssetMovements(context: TransactionContext): Promise<void> {\r\n const myInputs = Array.from(context.myInputs.values());\r\n const myOutputs = Array.from(context.myOutputs.values());\r\n\r\n const promises = [];\r\n for (const assetId of context.involvedAssets) {\r\n const p = this.processAssetMovement(context, assetId, myInputs, myOutputs);\r\n promises.push(p);\r\n }\r\n await Promise.all(promises);\r\n }\r\n\r\n private async processAssetMovement(context: TransactionContext, assetId: string, myInputs: AssetMovement[], myOutputs: AssetMovement[]): Promise<void> {\r\n const sentAmount = myInputs\r\n .reduce((sum, m) => m.assetId === assetId ? sum + BigInt(m.assetAmount) : sum, 0n);\r\n\r\n const receivedAmount = myOutputs\r\n .reduce((sum, m) => m.assetId === assetId ? sum + BigInt(m.assetAmount) : sum, 0n);\r\n\r\n if (sentAmount > 0n || receivedAmount > 0n) {\r\n const movement: MovementDetails = { amount: receivedAmount - sentAmount };\r\n if (assetId !== \"NEXA\") {\r\n movement.asset = await this.assetService.getAssetInfo(assetId);\r\n }\r\n\r\n if (movement.amount > 0n) {\r\n context.txDetails.receive.push(movement);\r\n } else if (movement.amount < 0n) {\r\n context.txDetails.send.push(movement);\r\n }\r\n }\r\n }\r\n}","import { Address, BNExtended, BufferWriter, Script, ScriptOpcode } from \"libnexa-ts\";\r\nimport type { VaultDTO } from \"../types\";\r\nimport { AccountType, generateVaultAddress, KeySpace } from \"../utils\";\r\nimport type { KeyManager } from \"./key\";\r\nimport type { RostrumService } from \"./rostrum\";\r\n\r\nconst HODL_FIRST_BLOCK = 274710;\r\nconst HODL_SCRIPT_PREFIX = \"0014461ad25081cb0119d034385ff154c8d3ad6bdd76\";\r\n\r\nexport class WalletDiscoveryService {\r\n\r\n private readonly rostrumService: RostrumService;\r\n private readonly keyManager: KeyManager;\r\n\r\n public constructor(rostrumService: RostrumService, keyManager: KeyManager) {\r\n this.rostrumService = rostrumService;\r\n this.keyManager = keyManager;\r\n }\r\n\r\n public async discoverWalletIndex(type: AccountType, keySpace: KeySpace): Promise<number> {\r\n let index = 0, stop = false, addrBatch = 0;\r\n \r\n do {\r\n stop = true;\r\n for (let i = addrBatch; i < addrBatch+20; i++) {\r\n const keyPath = { account: type, type: keySpace, index: i };\r\n const rAddr = this.keyManager.getKey(keyPath).privateKey.toAddress().toString();\r\n const isUsed = await this.rostrumService.isAddressUsed(rAddr);\r\n if (isUsed) {\r\n index = i;\r\n stop = false;\r\n }\r\n }\r\n addrBatch += 20;\r\n } while (!stop);\r\n \r\n return index;\r\n }\r\n\r\n public async discoverVaults(addresses: string[]): Promise<Map<string, VaultDTO>> {\r\n const vaultsPromises: Promise<Set<string>>[] = [];\r\n for (const address of addresses) {\r\n const p = this.checkVaultsForAddress(address);\r\n vaultsPromises.push(p);\r\n }\r\n\r\n const res = await Promise.all(vaultsPromises);\r\n const vaults = new Map<string, VaultDTO>();\r\n\r\n res.forEach(set => {\r\n set.forEach(hex => {\r\n const vault = this.parseVaultDetails(hex);\r\n if (vault) {\r\n vaults.set(vault.address, vault);\r\n }\r\n });\r\n });\r\n\r\n return vaults;\r\n }\r\n\r\n private async checkVaultsForAddress(address: string): Promise<Set<string>> {\r\n const vaults = new Set<string>();\r\n\r\n const history = await this.rostrumService.getTransactionsHistory(address, HODL_FIRST_BLOCK);\r\n for (const txHistory of history) {\r\n const tx = await this.rostrumService.getTransaction(txHistory.tx_hash);\r\n const hodls = tx.vout.filter(out => out.scriptPubKey.hex.startsWith(HODL_SCRIPT_PREFIX));\r\n for (const hodl of hodls) { \r\n vaults.add(hodl.scriptPubKey.hex);\r\n }\r\n }\r\n \r\n return vaults;\r\n }\r\n\r\n private parseVaultDetails(hex: string): VaultDTO | undefined {\r\n const scirptTemplate = Script.fromHex(hex);\r\n const buf = new BufferWriter().writeVarLengthBuf(scirptTemplate.toBuffer()).toBuffer();\r\n const actualAddress = new Address(buf).toString();\r\n\r\n const args = scirptTemplate.getVisibleArgs();\r\n\r\n const block = BNExtended.fromScriptNumBuffer(args.chunks[0].buf!).toNumber();\r\n const index = ScriptOpcode.isSmallIntOp(args.chunks[1].opcodenum)\r\n ? ScriptOpcode.decodeOP_N(args.chunks[1].opcodenum)\r\n : BNExtended.fromScriptNumBuffer(args.chunks[1].buf!).toNumber();\r\n\r\n const visibleArgs = [block, index];\r\n const key = this.keyManager.getKey({ account: AccountType.VAULT, type: KeySpace.RECEIVE, index: index });\r\n const expectedAddress = generateVaultAddress(key.publicKey, visibleArgs);\r\n\r\n if (actualAddress != expectedAddress) {\r\n return undefined;\r\n }\r\n\r\n const dto: VaultDTO = {\r\n address: actualAddress,\r\n block: block,\r\n idx: index,\r\n statusHash: '',\r\n balance: { confirmed: \"0\", unconfirmed: \"0\" },\r\n tokensBalance: {},\r\n height: 0,\r\n type: AccountType.VAULT\r\n }\r\n\r\n return dto;\r\n }\r\n}","import type { KVStore, WalletDB } from \"../persistence\";\r\nimport type { Account, AccountDTO, AddressDTO, AddressKey, Balance, ITXHistory, RostrumParams, VaultDTO, VaultInfo } from \"../types\";\r\nimport { AccountType, keyPathToString, KeySpace, MAIN_WALLET_ID, sumBalance, sumTokensBalance } from \"../utils\";\r\nimport type { AssetService } from \"./asset\";\r\nimport { WalletDiscoveryService } from \"./discovery\";\r\nimport type { KeyManager } from \"./key\";\r\nimport type { RostrumService } from \"./rostrum\";\r\nimport type { SessionManager } from \"./session\";\r\nimport type { TransactionService } from \"./transaction\";\r\n\r\ntype WalletAddress = AccountDTO | AddressDTO | VaultDTO;\r\n\r\ninterface AddressHistory {\r\n address: WalletAddress;\r\n txs: ITXHistory[];\r\n}\r\n\r\ninterface UpdateInfo {\r\n address: WalletAddress;\r\n result: string\r\n}\r\n\r\nexport type WalletEvent =\r\n | { type: 'new_tip'; tip: number; }\r\n | { type: 'new_account'; account: Account; }\r\n | { type: 'new_vault'; vault: VaultInfo; }\r\n | { type: 'discover_wallet'; loading: boolean; }\r\n | { type: 'load_wallet'; loading: boolean; }\r\n | { type: 'sync_wallet'; loading: boolean; }\r\n | { type: 'account_balance_updated'; accountId: number; balance: Balance, tokensBalance: Record<string, Balance>; }\r\n | { type: 'vault_balance_updated'; address: string, balance: Balance; }\r\n | { type: 'main_address_updated'; address: string; };\r\n\r\nexport type WalletUpdateCallback = (event: WalletEvent) => void;\r\n\r\nexport class WalletManager {\r\n\r\n private static readonly GAP_LIMIT = 20;\r\n private static readonly DEBOUNCE_MS = 1000;\r\n\r\n private addressResolvers: Map<string, () => void>;\r\n\r\n public accounts: Map<number, AccountDTO>;\r\n public accountsAddressToId: Map<string, number>;\r\n\r\n public receiveAddresses: AddressDTO[];\r\n public changeAddresses: AddressDTO[];\r\n\r\n public vaults: Map<string, VaultDTO>;\r\n\r\n private pendingUpdates: Map<string, UpdateInfo>;\r\n private updateTimer?: number;\r\n\r\n private updateCallback?: WalletUpdateCallback;\r\n\r\n private readonly discoveryService: WalletDiscoveryService;\r\n\r\n public constructor(\r\n private readonly keyManager: KeyManager,\r\n private readonly kvStore: KVStore,\r\n private readonly walletDb: WalletDB,\r\n private readonly rostrumService: RostrumService,\r\n private readonly assetService: AssetService,\r\n private readonly transactionService: TransactionService,\r\n private readonly sessionManager: SessionManager,\r\n ) {\r\n this.discoveryService = new WalletDiscoveryService(this.rostrumService, this.keyManager);\r\n this.accounts = new Map();\r\n this.accountsAddressToId = new Map();\r\n this.receiveAddresses = [];\r\n this.changeAddresses = [];\r\n this.vaults = new Map();\r\n this.pendingUpdates = new Map();\r\n this.addressResolvers = new Map();\r\n }\r\n\r\n public onUpdate(callback: WalletUpdateCallback): void {\r\n this.updateCallback = callback;\r\n }\r\n\r\n private notify(event: WalletEvent): void {\r\n this.updateCallback?.(event);\r\n }\r\n\r\n private getAllAddresses(): WalletAddress[] {\r\n return [...this.receiveAddresses, ...this.changeAddresses, ...this.accounts.values(), ...this.vaults.values()];\r\n }\r\n\r\n public getMainAddresses(): AddressDTO[] {\r\n return [...this.receiveAddresses, ...this.changeAddresses];\r\n }\r\n\r\n public getReceiveAddress(): string {\r\n return this.receiveAddresses.find(addr => !addr.used)!.address;\r\n }\r\n\r\n public getChangeAddress(accountId = MAIN_WALLET_ID): string {\r\n if (accountId != MAIN_WALLET_ID) {\r\n return this.accounts.get(accountId)!.address;\r\n }\r\n return this.changeAddresses.find(addr => !addr.used)!.address;\r\n }\r\n\r\n public getUsedAddressKeys(accountId = MAIN_WALLET_ID): AddressKey[] {\r\n if (accountId != MAIN_WALLET_ID) {\r\n const account = this.accounts.get(accountId)!;\r\n return [{\r\n address: account.address,\r\n keyPath: keyPathToString(AccountType.DAPP, 0, account.id),\r\n balance: account.balance,\r\n tokensBalance: account.tokensBalance\r\n }];\r\n }\r\n\r\n return this.getMainAddresses().filter(addr => addr.used).map(addr => ({\r\n address: addr.address,\r\n keyPath: keyPathToString(AccountType.MAIN, addr.space, addr.idx),\r\n balance: addr.balance,\r\n tokensBalance: addr.tokensBalance\r\n }));\r\n }\r\n\r\n public async reloadRostrum(params: RostrumParams): Promise<void> {\r\n await this.kvStore.saveRostrumParams(params);\r\n await this.rostrumService.disconnect(true);\r\n await this.initRostrum();\r\n await this.subscribeAddresses(this.getAllAddresses())\r\n }\r\n\r\n public async initRostrum(): Promise<void> {\r\n await this.rostrumService.connect();\r\n await this.rostrumService.subscribeHeaders(tip => this.notify({ type: 'new_tip', tip }));\r\n }\r\n\r\n public async initialize(): Promise<void> {\r\n await this.initRostrum();\r\n\r\n const isExist = await this.walletDb.countAddresses();\r\n if (isExist) {\r\n await this.loadWallet();\r\n } else {\r\n await this.discoverWallet();\r\n }\r\n }\r\n\r\n private async discoverWallet(): Promise<void> {\r\n this.notify({ type: 'discover_wallet', loading: true });\r\n\r\n const rIndexPromise = this.discoveryService.discoverWalletIndex(AccountType.MAIN, KeySpace.RECEIVE);\r\n const cIndexPromise = this.discoveryService.discoverWalletIndex(AccountType.MAIN, KeySpace.CHANGE);\r\n const dappIndexPromis = this.discoveryService.discoverWalletIndex(AccountType.DAPP, KeySpace.RECEIVE);\r\n \r\n const [rIndex, cIndex, dappIndex] = await Promise.all([rIndexPromise, cIndexPromise, dappIndexPromis]);\r\n\r\n this.receiveAddresses = this.deriveAddresses(KeySpace.RECEIVE, 0, rIndex + WalletManager.GAP_LIMIT);\r\n this.changeAddresses = this.deriveAddresses(KeySpace.CHANGE, 0, cIndex + WalletManager.GAP_LIMIT);\r\n this.accounts = this.deriveAccounts(0, dappIndex + 1);\r\n this.accounts.forEach(entry => this.accountsAddressToId.set(entry.address, entry.id));\r\n\r\n await this.saveAddresses(this.receiveAddresses);\r\n await this.saveAddresses(this.changeAddresses);\r\n await this.saveAccounts(this.accounts);\r\n\r\n this.initState();\r\n\r\n await this.initialSync();\r\n\r\n this.notify({ type: 'discover_wallet', loading: false });\r\n this.notify({ type: 'load_wallet', loading: false });\r\n\r\n await this.rescanVaults();\r\n }\r\n\r\n private async loadWallet(): Promise<void> {\r\n this.receiveAddresses = await this.walletDb.getReceiveAddresses();\r\n this.changeAddresses = await this.walletDb.getChangeAddresses();\r\n\r\n const accs = await this.walletDb.getAccounts();\r\n this.accounts = new Map(accs.map(a => [a.id, a]));\r\n this.accountsAddressToId = new Map(accs.map(a => [a.address, a.id]));\r\n\r\n const vaults = await this.walletDb.getVaults();\r\n this.vaults = new Map(vaults.map(v => [v.address, v]));\r\n\r\n this.initState();\r\n\r\n this.notify({ type: 'load_wallet', loading: false });\r\n\r\n await this.reconnectSync();\r\n }\r\n\r\n private async initialSync(): Promise<void> {\r\n await this.subscribeAddresses(this.getAllAddresses(), true);\r\n\r\n const tokensLoadPromises: Promise<void>[] = [];\r\n tokensLoadPromises.push(this.assetService.fetchAndSaveTokens(MAIN_WALLET_ID, sumTokensBalance(this.getMainAddresses().map(a => a.tokensBalance))));\r\n for (const account of this.accounts.values()) {\r\n tokensLoadPromises.push(this.assetService.fetchAndSaveTokens(account.id, account.tokensBalance));\r\n }\r\n\r\n await Promise.all(tokensLoadPromises);\r\n }\r\n\r\n public async reconnectSync(): Promise<void> {\r\n await Promise.all([\r\n this.sessionManager.reload(this.accounts),\r\n this.subscribeAddresses(this.getAllAddresses())\r\n ]);\r\n }\r\n\r\n private initState(): void {\r\n const walletAddresses = this.getMainAddresses();\r\n\r\n this.notify({\r\n type: 'new_account',\r\n account: {\r\n id: MAIN_WALLET_ID,\r\n name: 'Main Wallet',\r\n address: this.getReceiveAddress(),\r\n balance: sumBalance(walletAddresses.map(a => a.balance)),\r\n tokensBalance: sumTokensBalance(walletAddresses.map(a => a.tokensBalance)),\r\n tokens: [],\r\n sessions: {}\r\n }\r\n });\r\n\r\n for (const account of this.accounts.values()) {\r\n this.notify({\r\n type: 'new_account',\r\n account: {\r\n id: account.id,\r\n name: account.name,\r\n address: account.address,\r\n balance: account.balance,\r\n tokensBalance: account.tokensBalance,\r\n tokens: [],\r\n sessions: {}\r\n }\r\n });\r\n }\r\n\r\n for (const vault of this.vaults.values()) {\r\n this.notify({\r\n type: 'new_vault',\r\n vault: {\r\n address: vault.address,\r\n balance: vault.balance,\r\n block: vault.block,\r\n index: vault.idx\r\n }\r\n });\r\n }\r\n }\r\n\r\n private deriveAddresses(space: KeySpace, startIndex: number, count: number): AddressDTO[] {\r\n const newAddresses: AddressDTO[] = [];\r\n for (let i = startIndex; i < startIndex + count; i++) {\r\n const path = keyPathToString(AccountType.MAIN, space, i);\r\n const address = this.keyManager.getKey(path).privateKey.toAddress().toString();\r\n\r\n const addressDTO: AddressDTO = {\r\n address: address,\r\n space: space,\r\n idx: i,\r\n used: false,\r\n height: 0,\r\n statusHash: '',\r\n balance: { confirmed: \"0\", unconfirmed: \"0\" },\r\n tokensBalance: {},\r\n type: AccountType.MAIN\r\n };\r\n\r\n newAddresses.push(addressDTO);\r\n }\r\n\r\n return newAddresses;\r\n }\r\n\r\n private deriveAccounts(startIndex: number, count: number): Map<number, AccountDTO> {\r\n const newAccounts = new Map<number, AccountDTO>();\r\n for (let i = startIndex; i < startIndex + count; i++) {\r\n const path = keyPathToString(AccountType.DAPP, 0, i);\r\n const address = this.keyManager.getKey(path).privateKey.toAddress().toString();\r\n\r\n const account: AccountDTO = {\r\n id: i,\r\n name: `Account ${i + 1}`,\r\n address: address,\r\n height: 0,\r\n hidden: 0,\r\n statusHash: '',\r\n balance: { confirmed: \"0\", unconfirmed: \"0\" },\r\n tokensBalance: {},\r\n type: AccountType.DAPP\r\n };\r\n\r\n newAccounts.set(account.id, account);\r\n }\r\n\r\n return newAccounts;\r\n }\r\n\r\n private async saveAddresses(addresses: AddressDTO[]): Promise<void> {\r\n for (const addr of addresses) {\r\n await this.walletDb.saveAddress(addr);\r\n }\r\n }\r\n\r\n private async saveAccounts(accounts: Map<number, AccountDTO>): Promise<void> {\r\n for (const acc of accounts.values()) {\r\n await this.walletDb.saveAccount(acc);\r\n }\r\n }\r\n\r\n private async subscribeAddresses(addresses: WalletAddress[], isInit = false): Promise<void> {\r\n const subscriptionPromises = addresses.map(async addr => {\r\n const result = await this.rostrumService.subscribeAddress(addr.address, this.onSubscribeEvent);\r\n return { addr, result };\r\n });\r\n\r\n const initPromises: Promise<void>[] = [];\r\n const subscriptionResults = await Promise.all(subscriptionPromises);\r\n\r\n for (const { addr, result } of subscriptionResults) {\r\n if (result && typeof result === 'string' && addr.statusHash != result) {\r\n if (isInit) {\r\n const p = new Promise<void>((resolve) => {\r\n this.addressResolvers.set(addr.address, resolve);\r\n });\r\n initPromises.push(p);\r\n }\r\n this.registerUpdate({address: addr, result});\r\n }\r\n }\r\n\r\n await Promise.all(initPromises);\r\n }\r\n\r\n private onSubscribeEvent = (data: unknown): void => {\r\n if (!Array.isArray(data) || data.length < 2) {\r\n return;\r\n }\r\n\r\n const [address, hash] = data as [string, string];\r\n const allAddresses = this.getAllAddresses();\r\n const addrDTO = allAddresses.find(a => a.address === address);\r\n\r\n if (addrDTO && addrDTO.statusHash !== hash) {\r\n this.registerUpdate({address: addrDTO, result: hash});\r\n }\r\n }\r\n\r\n private registerUpdate(updateInfo: UpdateInfo): void {\r\n this.pendingUpdates.set(updateInfo.address.address, updateInfo);\r\n\r\n clearTimeout(this.updateTimer);\r\n this.updateTimer = setTimeout(() => {\r\n this.processPendingUpdates();\r\n }, WalletManager.DEBOUNCE_MS);\r\n }\r\n\r\n private async processPendingUpdates(): Promise<void> {\r\n if (this.pendingUpdates.size === 0) {\r\n return;\r\n }\r\n\r\n try {\r\n this.notify({ type: 'sync_wallet', loading: true });\r\n console.log(`Processing ${this.pendingUpdates.size} pending updates...`);\r\n\r\n const updates = Array.from(this.pendingUpdates);\r\n this.pendingUpdates.clear();\r\n\r\n const accountsHistoryPromises: Promise<AddressHistory>[] = [];\r\n const vaultsHistoryPromises: Promise<AddressHistory>[] = [];\r\n const walletHistoryPromises: Promise<AddressHistory>[] = [];\r\n for (const [, update] of updates) {\r\n if (this.isAccountAddress(update.address)) {\r\n const p = this.fetchAndUpdateAccount(update.address, update.result);\r\n accountsHistoryPromises.push(p);\r\n } else if (this.isVaultAddress(update.address)) {\r\n const p = this.fetchAndUpdateVault(update.address, update.result);\r\n vaultsHistoryPromises.push(p);\r\n } else {\r\n const p = this.fetchAndUpdateAddress(update.address, update.result);\r\n walletHistoryPromises.push(p);\r\n }\r\n }\r\n \r\n const accountsTxs = await Promise.all(accountsHistoryPromises);\r\n await Promise.all(vaultsHistoryPromises);\r\n const walletTxs = await Promise.all(walletHistoryPromises);\r\n\r\n if (this.addressResolvers.size > 0) {\r\n for (const [address,] of updates) {\r\n const resolver = this.addressResolvers.get(address);\r\n if (resolver) {\r\n resolver();\r\n this.addressResolvers.delete(address);\r\n }\r\n }\r\n }\r\n\r\n await Promise.all([this.postProcessWalletUpdate(walletTxs), this.postProcessAccountUpdate(accountsTxs)]);\r\n } catch (e) {\r\n console.error('Error processing pending updates:', e);\r\n } finally {\r\n this.notify({ type: 'sync_wallet', loading: false });\r\n }\r\n }\r\n\r\n private async postProcessWalletUpdate(history: AddressHistory[]): Promise<void> {\r\n if (history.length === 0) {\r\n return;\r\n }\r\n\r\n const txHistoryMap = new Map<string, ITXHistory>();\r\n for (const { txs } of history) {\r\n for (const tx of txs) {\r\n txHistoryMap.set(tx.tx_hash, tx);\r\n }\r\n }\r\n\r\n await this.checkGapLimit(KeySpace.RECEIVE);\r\n await this.checkGapLimit(KeySpace.CHANGE);\r\n\r\n const walletAddresses = this.getMainAddresses();\r\n const walletBalance = sumBalance(walletAddresses.map(a => a.balance));\r\n const walletTokenBalances = sumTokensBalance(walletAddresses.map(a => a.tokensBalance));\r\n\r\n this.notify({ type: 'account_balance_updated', accountId: MAIN_WALLET_ID, balance: walletBalance, tokensBalance: walletTokenBalances });\r\n this.notify({ type: 'main_address_updated', address: this.getReceiveAddress() });\r\n\r\n const nftPromise = this.assetService.syncNfts(MAIN_WALLET_ID, walletTokenBalances);\r\n for (const tx of txHistoryMap.values()) {\r\n await this.transactionService.classifyAndSaveTransaction(MAIN_WALLET_ID, tx.tx_hash, walletAddresses.map(a => a.address));\r\n }\r\n await nftPromise;\r\n }\r\n\r\n private async postProcessAccountUpdate(history: AddressHistory[]): Promise<void> {\r\n if (history.length === 0) {\r\n return;\r\n }\r\n\r\n for (const { address, txs } of history) {\r\n const account = address as AccountDTO;\r\n \r\n this.notify({ type: 'account_balance_updated', accountId: account.id, balance: account.balance, tokensBalance: account.tokensBalance });\r\n\r\n const nftPromise = this.assetService.syncNfts(account.id, account.tokensBalance);\r\n for (const tx of txs) {\r\n await this.transactionService.classifyAndSaveTransaction(account.id, tx.tx_hash, [account.address]);\r\n }\r\n await nftPromise;\r\n }\r\n }\r\n\r\n private async fetchAndUpdateAddress(addrDTO: AddressDTO, hash: string): Promise<AddressHistory> {\r\n addrDTO.statusHash = hash;\r\n addrDTO.balance = await this.rostrumService.getBalance(addrDTO.address);\r\n addrDTO.tokensBalance = await this.rostrumService.getTokensBalance(addrDTO.address);\r\n\r\n const history = await this.transactionService.fetchTransactionsHistory(addrDTO.address, addrDTO.height);\r\n addrDTO.height = history.lastHeight;\r\n if (!addrDTO.used) {\r\n addrDTO.used = history.txs.length > 0;\r\n }\r\n\r\n await this.walletDb.saveAddress(addrDTO);\r\n\r\n return { address: addrDTO, txs: history.txs };\r\n }\r\n\r\n private async fetchAndUpdateAccount(account: AccountDTO, hash: string): Promise<AddressHistory> {\r\n account.statusHash = hash;\r\n account.balance = await this.rostrumService.getBalance(account.address);\r\n account.tokensBalance = await this.rostrumService.getTokensBalance(account.address);\r\n\r\n const history = await this.transactionService.fetchTransactionsHistory(account.address, account.height);\r\n account.height = history.lastHeight;\r\n\r\n await this.walletDb.saveAccount(account);\r\n\r\n return { address: account, txs: history.txs };\r\n }\r\n\r\n private async fetchAndUpdateVault(vault: VaultDTO, hash: string): Promise<AddressHistory> {\r\n vault.statusHash = hash;\r\n vault.balance = await this.rostrumService.getBalance(vault.address);\r\n\r\n const history = await this.transactionService.fetchTransactionsHistory(vault.address, vault.height);\r\n vault.height = history.lastHeight;\r\n\r\n await this.walletDb.saveVault(vault);\r\n this.notify({ type: 'vault_balance_updated', address: vault.address, balance: vault.balance });\r\n\r\n return { address: vault, txs: history.txs };\r\n }\r\n\r\n private async checkGapLimit(keySpace: KeySpace): Promise<void> {\r\n const addresses = keySpace === KeySpace.RECEIVE \r\n ? this.receiveAddresses \r\n : this.changeAddresses;\r\n\r\n const spaceName = keySpace === KeySpace.RECEIVE ? 'Receive' : 'Change';\r\n const unused = addresses.filter(a => !a.used).length;\r\n\r\n if (unused < WalletManager.GAP_LIMIT) {\r\n const needed = WalletManager.GAP_LIMIT - unused;\r\n const lastIndex = addresses[addresses.length - 1].idx;\r\n \r\n console.log(`Deriving ${needed} more ${spaceName} addresses...`);\r\n \r\n const newAddresses = this.deriveAddresses(keySpace, lastIndex + 1, needed);\r\n\r\n if (keySpace === KeySpace.RECEIVE) {\r\n this.receiveAddresses.push(...newAddresses);\r\n } else {\r\n this.changeAddresses.push(...newAddresses);\r\n }\r\n\r\n await this.saveAddresses(newAddresses);\r\n await this.subscribeAddresses(newAddresses);\r\n }\r\n }\r\n\r\n public async addNewAccount(id: number, name: string): Promise<void> {\r\n const path = keyPathToString(AccountType.DAPP, 0, id);\r\n const address = this.keyManager.getKey(path).privateKey.toAddress().toString();\r\n\r\n const account: AccountDTO = {\r\n id: id,\r\n name: name,\r\n address: address,\r\n height: 0,\r\n hidden: 0,\r\n statusHash: '',\r\n balance: { confirmed: \"0\", unconfirmed: \"0\" },\r\n tokensBalance: {},\r\n type: AccountType.DAPP\r\n };\r\n\r\n this.accounts.set(id, account);\r\n this.accountsAddressToId.set(address, id);\r\n await this.walletDb.saveAccount(account);\r\n await this.subscribeAddresses([account]);\r\n\r\n this.notify({\r\n type: 'new_account',\r\n account: {\r\n id: account.id,\r\n name: account.name,\r\n address: account.address,\r\n balance: account.balance,\r\n tokensBalance: account.tokensBalance,\r\n tokens: [],\r\n sessions: {}\r\n }\r\n });\r\n }\r\n\r\n public async updateAccountName(id: number, name: string): Promise<void> {\r\n if (!name) {\r\n return;\r\n }\r\n\r\n const account = this.accounts.get(id)!;\r\n account.name = name;\r\n\r\n await this.walletDb.updateAccountName(id, name);\r\n }\r\n\r\n public rescanAccount(id: number): void {\r\n if (id == MAIN_WALLET_ID) {\r\n const addrs = this.getMainAddresses();\r\n for (const addr of addrs) {\r\n addr.height = 0;\r\n this.registerUpdate({address: addr, result: addr.statusHash});\r\n }\r\n } else {\r\n const account = this.accounts.get(id)!\r\n account.height = 0;\r\n this.registerUpdate({address: account, result: account.statusHash});\r\n }\r\n }\r\n \r\n public getVaultNextIndex(): number {\r\n if (this.vaults.size == 0) {\r\n return 0;\r\n }\r\n return Math.max(...Array.from(this.vaults.values(), v => v.idx)) + 1;\r\n }\r\n\r\n public async addNewVault(address: string, block: number, index: number): Promise<void> {\r\n const vault: VaultDTO = {\r\n address: address,\r\n block: block,\r\n idx: index,\r\n height: 0,\r\n statusHash: '',\r\n balance: { confirmed: \"0\", unconfirmed: \"0\" },\r\n tokensBalance: {},\r\n type: AccountType.VAULT\r\n };\r\n await this.addVault(vault);\r\n }\r\n\r\n private async addVault(vault: VaultDTO): Promise<void> {\r\n this.vaults.set(vault.address, vault);\r\n await this.walletDb.saveVault(vault);\r\n await this.subscribeAddresses([vault]);\r\n\r\n this.notify({\r\n type: 'new_vault',\r\n vault: {\r\n address: vault.address,\r\n balance: vault.balance,\r\n block: vault.block,\r\n index: vault.idx\r\n }\r\n });\r\n }\r\n\r\n public async rescanVaults(): Promise<boolean> {\r\n let found = false;\r\n const vaults = await this.discoveryService.discoverVaults(this.getMainAddresses().map(a => a.address));\r\n const promises: Promise<void>[] = [];\r\n for (const [address, vault] of vaults) {\r\n if (!this.vaults.has(address)) {\r\n found = true;\r\n promises.push(this.addVault(vault));\r\n }\r\n }\r\n await Promise.all(promises);\r\n return found;\r\n }\r\n\r\n private isVaultAddress(address: AccountDTO | AddressDTO | VaultDTO): address is VaultDTO {\r\n return address.type == AccountType.VAULT;\r\n }\r\n\r\n private isAccountAddress(address: AccountDTO | AddressDTO | VaultDTO): address is AccountDTO {\r\n return address.type == AccountType.DAPP;\r\n }\r\n\r\n private isMainAddress(address: AccountDTO | AddressDTO | VaultDTO): address is AddressDTO {\r\n return address.type == AccountType.MAIN;\r\n }\r\n}","import type { PayloadAction } from \"@reduxjs/toolkit\";\nimport { createSlice } from \"@reduxjs/toolkit\";\r\n\r\nexport interface AuthState {\r\n isWalletExist: boolean;\r\n isAuthorized: boolean;\r\n}\r\n\r\nconst initialState: AuthState = {\r\n isWalletExist: false,\r\n isAuthorized: false,\r\n};\r\n\r\nconst authSlice = createSlice({\r\n name: 'auth',\r\n initialState,\r\n reducers: {\r\n setWalletExist: (state, action: PayloadAction<boolean>) => {\r\n state.isWalletExist = action.payload;\r\n },\r\n setAuthorized: (state, action: PayloadAction<boolean>) => {\r\n state.isAuthorized = action.payload;\r\n }\r\n }\r\n});\r\n\r\nexport const authActions = authSlice.actions;\r\nexport const authReducer = authSlice.reducer;","import type { PayloadAction } from \"@reduxjs/toolkit\";\nimport { createSlice } from \"@reduxjs/toolkit\";\nimport type { SessionRequestType } from \"../../utils\";\nimport type { DappRpcRequest } from \"../../types\";\n\nexport interface DappModalState {\n modalType: SessionRequestType | null;\n currentRequest: DappRpcRequest | null;\n}\n\nconst initialState: DappModalState = {\n modalType: null,\n currentRequest: null,\n};\n\nconst dappModalSlice = createSlice({\n name: 'dappModal',\n initialState,\n reducers: {\n showRequest(state, action: PayloadAction<DappRpcRequest>) {\n state.modalType = action.payload.type;\n state.currentRequest = action.payload;\n },\n clear(state) {\n state.modalType = null;\n state.currentRequest = null;\n },\n },\n});\n\nexport const dappModalActions = dappModalSlice.actions;\nexport const dappModalReducer = dappModalSlice.reducer;","import type { PayloadAction } from \"@reduxjs/toolkit\";\nimport { createSlice } from \"@reduxjs/toolkit\";\n\nexport interface LoaderState {\n counter: number\n loading: boolean;\n text?: string;\n}\n\nconst initState: LoaderState = {\n counter: 0,\n loading: false\n}\n\nconst loaderSlice = createSlice({\n name: 'loader',\n initialState: initState,\n reducers: {\n setLoader: (state, action: PayloadAction<Omit<LoaderState, 'counter'>>) => {\n const counter = action.payload.loading\n ? state.counter + 1\n : Math.max(0, state.counter - 1);\n state.counter = counter;\n state.loading = counter > 0;\n state.text = action.payload.text;\n },\n }\n});\n\nexport const loaderActions = loaderSlice.actions;\nexport const loaderReducer = loaderSlice.reducer;","import type { PayloadAction } from \"@reduxjs/toolkit\";\nimport { createSlice } from \"@reduxjs/toolkit\";\nimport type { AppNotification } from \"../../types\";\n\nexport interface NotificationsState {\n wallet: Record<string, AppNotification>;\n web3: Record<string, AppNotification>;\n}\n\nconst initialState: NotificationsState = {\n wallet: {},\n web3: {}\n};\n\nconst notificationsSlice = createSlice({\n name: 'notifications',\n initialState,\n reducers: {\n addNotification: (state, action: PayloadAction<AppNotification>) => {\n if (action.payload.type == 'wallet') {\n state.wallet[action.payload.id] = action.payload;\n } else if (action.payload.type == 'web3') {\n state.web3[action.payload.id] = action.payload;\n }\n },\n removeNotification: (state, action: PayloadAction<string>) => {\n delete state.wallet[action.payload];\n delete state.web3[action.payload];\n },\n clearAll: (state, action: PayloadAction<'wallet' | 'web3' | 'all'>) => {\n if (action.payload === 'wallet') {\n state.wallet = {};\n } else if (action.payload === 'web3') {\n state.web3 = {};\n } else if (action.payload === 'all') {\n state.wallet = {};\n state.web3 = {};\n }\n }\n }\n});\n\nexport const notificationsActions = notificationsSlice.actions;\nexport const notificationsReducer = notificationsSlice.reducer;","import type { PayloadAction } from \"@reduxjs/toolkit\";\nimport { createAsyncThunk, createSlice } from \"@reduxjs/toolkit\";\r\nimport type { Price } from \"../../types\";\r\nimport { getNexaPrices, initializePrices } from \"../../utils\";\r\n\r\nexport interface StatusState {\r\n status: \"Online\" | \"Offline\";\r\n height: number;\r\n price: Record<string, Price>;\r\n hasNetwork: boolean;\r\n isSuspended: boolean;\r\n}\r\n\r\nconst initialState: StatusState = {\r\n status: \"Offline\",\r\n height: 0,\r\n price: initializePrices(),\r\n hasNetwork: true,\r\n isSuspended: false,\r\n};\r\n\r\nexport const fetchPrice = createAsyncThunk('status/fetchPrice', async () => {\r\n const prices = initializePrices();\r\n try {\r\n const p = await getNexaPrices();\r\n Object.keys(p).forEach(currency => {\r\n prices[currency] = { \r\n value: p[currency],\r\n change: p[`${currency}_24h_change`]\r\n };\r\n });\r\n } catch {\r\n // prices remain at 0\r\n }\r\n return prices ;\r\n});\r\n\r\nconst statusSlice = createSlice({\r\n name: 'status',\r\n initialState,\r\n reducers: {\r\n setHeight: (state, action: PayloadAction<number>) => {\r\n if (action.payload > 0) {\r\n state.status = \"Online\";\r\n }\r\n state.height = action.payload;\r\n },\r\n setOffline: (state) => {\r\n state.status = \"Offline\";\r\n },\r\n setHasNetwork: (state, action: PayloadAction<boolean>) => {\r\n state.hasNetwork = action.payload;\r\n },\r\n setIsSuspended: (state, action: PayloadAction<boolean>) => {\r\n state.isSuspended = action.payload;\r\n }\r\n },\r\n extraReducers: (builder) => {\r\n builder\r\n .addCase(fetchPrice.fulfilled, (state, action) => {\r\n state.price = action.payload;\r\n })\r\n .addCase(fetchPrice.rejected, (_, action) => {\r\n console.error(action.error.message);\r\n });\r\n }\r\n});\r\n\r\nexport const statusActions = statusSlice.actions;\r\nexport const statusReducer = statusSlice.reducer;","import type { PayloadAction } from \"@reduxjs/toolkit\";\nimport { createSlice } from \"@reduxjs/toolkit\";\r\nimport type { Account, AssetEntity, Balance, SessionInfo, VaultInfo } from \"../../types\";\r\nimport { MAIN_WALLET_ID } from \"../../utils\";\r\n\r\ninterface AddSessionPayload {\r\n accountId: number;\r\n sessionInfo: SessionInfo;\r\n}\r\n\r\ninterface RemoveSessionPayload {\r\n accountId: number;\r\n sessionId: string;\r\n}\r\n\r\nexport interface WalletState {\r\n isAuthorized: boolean;\r\n selectedAccount: number;\r\n accounts: Record<number, Account>;\r\n vaults: Record<string, VaultInfo>;\r\n sync: boolean;\r\n initLoad: boolean;\r\n txUpdateTrigger: number;\r\n nftsUpdateTrigger: number;\r\n}\r\n\r\nconst initialState: WalletState = {\r\n isAuthorized: false,\r\n selectedAccount: MAIN_WALLET_ID,\r\n accounts: {\r\n \"-1\": {\r\n id: MAIN_WALLET_ID,\r\n name: 'Main Wallet',\r\n address: '',\r\n balance: {confirmed: \"0\", unconfirmed: \"0\"},\r\n tokensBalance: {},\r\n tokens: [],\r\n sessions: {}\r\n }\r\n },\r\n vaults: {},\r\n sync: false,\r\n initLoad: true,\r\n txUpdateTrigger: 0,\r\n nftsUpdateTrigger: 0\r\n}\r\n\r\nconst walletSlice = createSlice({\r\n name: 'wallet',\r\n initialState,\r\n reducers: {\r\n setInitLoad: (state, action: PayloadAction<boolean>) => {\r\n state.initLoad = action.payload;\r\n },\r\n setSelectedAccount: (state, action: PayloadAction<number>) => {\r\n state.selectedAccount = action.payload;\r\n },\r\n setSync: (state, action: PayloadAction<boolean>) => {\r\n state.sync = action.payload;\r\n },\r\n setVault: (state, action: PayloadAction<VaultInfo>) => {\r\n state.vaults[action.payload.address] = action.payload;\r\n },\r\n setVaultBalance: (state, action: PayloadAction<{ address: string, balance: Balance }>) => {\r\n state.vaults[action.payload.address].balance = action.payload.balance;\r\n },\r\n setAccount: (state, action: PayloadAction<Account>) => {\r\n state.accounts[action.payload.id] = action.payload;\r\n },\r\n setMainAddress: (state, action: PayloadAction<string>) => {\r\n state.accounts[MAIN_WALLET_ID].address = action.payload;\r\n },\r\n setAccountBalance: (state, action: PayloadAction<{ id: number, balance: Balance, tokensBalance: Record<string, Balance> }>) => {\r\n state.accounts[action.payload.id].balance = action.payload.balance;\r\n state.accounts[action.payload.id].tokensBalance = action.payload.tokensBalance;\r\n },\r\n setAccountName: (state, action: PayloadAction<{ id: number, name: string }>) => {\r\n state.accounts[action.payload.id].name = action.payload.name;\r\n },\r\n setTokens: (state, action: PayloadAction<{ id: number, assets: AssetEntity[] }>) => {\r\n state.accounts[action.payload.id].tokens = action.payload.assets;\r\n },\r\n addToken: (state, action: PayloadAction<{ id: number, asset: AssetEntity }>) => {\r\n state.accounts[action.payload.id].tokens.unshift(action.payload.asset);\r\n },\r\n removeToken: (state, action: PayloadAction<{ id: number, tokenId: string }>) => {\r\n state.accounts[action.payload.id].tokens = state.accounts[action.payload.id].tokens.filter(n => n.tokenIdHex !== action.payload.tokenId);\r\n },\r\n refreshTxs: (state) => {\r\n state.txUpdateTrigger++;\r\n },\r\n refreshNfts: (state) => {\r\n state.nftsUpdateTrigger++;\r\n },\r\n addSession(state, action: PayloadAction<AddSessionPayload>) {\r\n const { accountId, sessionInfo } = action.payload;\r\n state.accounts[accountId].sessions[sessionInfo.details.sessionId] = sessionInfo;\r\n },\r\n removeSession(state, action: PayloadAction<RemoveSessionPayload>) {\r\n const { accountId, sessionId } = action.payload;\r\n if (state.accounts[accountId].sessions[sessionId]) {\r\n delete state.accounts[accountId].sessions[sessionId];\r\n }\r\n },\r\n clearSessions(state, action: PayloadAction<{ accountId: number }>) {\r\n state.accounts[action.payload.accountId].sessions = {};\r\n }\r\n }\r\n});\r\n\r\nexport const walletActions = walletSlice.actions;\r\nexport const walletReducer = walletSlice.reducer;","import { authReducer } from \"./slices/auth\";\r\nimport { dappModalReducer } from \"./slices/dapp\";\r\nimport { loaderReducer } from \"./slices/loader\";\r\nimport { notificationsReducer } from \"./slices/notifications\";\r\nimport { statusReducer } from \"./slices/status\";\r\nimport { walletReducer } from \"./slices/wallet\";\r\n\r\nexport const sharedReducers = {\r\n loader: loaderReducer,\r\n dapp: dappModalReducer,\r\n status: statusReducer,\r\n wallet: walletReducer,\r\n auth: authReducer,\r\n notifications: notificationsReducer,\r\n};\r\n\r\nexport type SharedState = {\r\n loader: ReturnType<typeof loaderReducer>;\r\n dapp: ReturnType<typeof dappModalReducer>;\r\n status: ReturnType<typeof statusReducer>;\r\n wallet: ReturnType<typeof walletReducer>;\r\n auth: ReturnType<typeof authReducer>;\r\n notifications: ReturnType<typeof notificationsReducer>;\r\n};","import { useSelector } from \"react-redux\";\r\nimport type { SharedState } from \"./store\";\r\nimport { createSelector } from \"@reduxjs/toolkit\";\r\nimport type { AuthState } from \"./slices\";\r\nimport type { Account, AppNotification, Balance, SessionInfo, VaultInfo } from \"../types\";\r\n\r\nconst useSharedSelector = useSelector.withTypes<SharedState>();\r\n\r\nexport const useAuth = (): AuthState => useSharedSelector(state => state.auth);\r\n\r\nexport const useBlockHeight = (): number => useSharedSelector(state => state.status.height);\r\n\r\nexport const useAccount = (id: number): Account => useSharedSelector(state => state.wallet.accounts[id]);\r\nexport const useSelectedAccount = (): number => useSharedSelector(state => state.wallet.selectedAccount);\r\nexport const useLastAccountId = (): number => useSharedSelector(state => Math.max(...Object.keys(state.wallet.accounts).map(Number)));\r\n\r\nexport const useMainReceiveAddress = (account: number): string => useSharedSelector(state => state.wallet.accounts[account].address);\r\n\r\nexport const useWalletBalance = (account: number): Balance => useSharedSelector(state => state.wallet.accounts[account].balance);\r\nexport const useTokenBalance = (account: number, tokenIdHex: string): Balance => \r\n useSharedSelector(state => state.wallet.accounts[account].tokensBalance[tokenIdHex]);\r\n\r\nexport const useDAppSession = (account: number, session: string): SessionInfo =>\r\n useSharedSelector(state => state.wallet.accounts[account].sessions[session]);\r\n\r\nexport const useVaults = (): Record<string, VaultInfo> => useSharedSelector(state => state.wallet.vaults);\r\n\r\nconst selectWalletNotificationsArray = createSelector(\r\n [(state: SharedState) => state.notifications.wallet],\r\n (wallet) => Object.values(wallet).sort((a, b) => b.createdAt - a.createdAt)\r\n);\r\n\r\nconst selectWeb3NotificationsArray = createSelector(\r\n [(state: SharedState) => state.notifications.web3],\r\n (web3) => Object.values(web3).sort((a, b) => b.createdAt - a.createdAt)\r\n);\r\n\r\nconst selectAllNotificationsArray = createSelector(\r\n [selectWalletNotificationsArray, selectWeb3NotificationsArray],\r\n (wallet, web3) => [...wallet, ...web3].sort((a, b) => b.createdAt - a.createdAt)\r\n);\r\n\r\nexport const useWalletNotifications = (): AppNotification[] => useSharedSelector(selectWalletNotificationsArray);\r\nexport const useWeb3Notifications = (): AppNotification[] => useSharedSelector(selectWeb3NotificationsArray);\r\nexport const useAllNotifications = (): AppNotification[] => useSharedSelector(selectAllNotificationsArray);\r\n"],"names":["MAIN_WALLET_ID","MAX_INT64","VAULT_FIRST_BLOCK","VAULT_SCRIPT_PREFIX","isTestnet","Networks","isGenesisHashValid","hash","isValidNexaAddress","address","type","AddressType","Address","getExplorerUrl","currentTimestamp","estimateDateByFutureBlock","current","future","estimateMins","time","isNullOrEmpty","arg","truncateStringMiddle","str","maxLength","ellipsis","halfLength","firstHalf","secondHalf","capitalizeFirstLetter","getAddressBuffer","CommonUtils","BufferUtils","tokenIdToHex","token","tokenHexToAddr","tokenAmountToAssetAmount","amount","sumBalance","balances","confirmed","unconfirmed","b","sumTokensBalance","tokensBalance","key","FILE_EXTENSION_TO_TYPE","getFileMediaType","filename","lastDotIndex","extension","getFileMimeType","KVStore","seed","code","release","params","hide","currency","useBiometric","value","requireAuth","autoLock","AccountType","KeySpace","SessionRequestType","AssetType","WalletDB","store","callback","event","tx","error","assetTx","account","tokenId","pageNum","pageSize","asset","id","nft","notify","notifyNft","accountEntity","a","name","session","accountId","sessionId","addressEntity","v","vault","vaultEntity","WalletCache","walletDb","RostrumService","kvStore","fromHeight","firstUse","e","verbose","outpoint","balance","cToken","uToken","txHex","handler","response","data","height","start","ElectrumClient","force","method","parameters","res","timeout","resolve","reject","check","ConnectionStatus","TransportScheme","keyPathToString","index","stringToKeyPath","path","parts","KeyManager","mnemonic","mnemonicToSeedSync","HDPrivateKey","keyPath","getNiftyToken","fetchNiftyNFT","performGet","getNiftyEndpoint","isNiftySubgroup","group","addrBuf","GroupToken","fetchAssetDoc","url","translateIfIpfsUrl","fetchAssetBlob","transformTokenIconUrl","icon","documentUrl","parseTokenDataUrl","gateway","responseType","arrayBuffer","AssetService","rostrumService","walletCache","checkCache","cachedToken","genesis","groupId","parent","iconUrl","GroupIdType","token_zip","info","JSZip","infoData","infoJson","tokenIdHex","parentGroupId","parentGenesis","hexId","source","collection","nftEntity","tokenBalances","currentAssets","internalAssets","handleNftDelete","staleAssets","hasBalance","isAssetExist","TransactionService","keysManager","maxHeight","fromHeightFilter","txHistory","transactions","txEntry","txHash","myAddresses","txDto","txEntity","involvedAssets","m","assetId","t","myInputs","othersInputs","myOutputs","othersOutputs","vin","movement","vout","isConfirmed","from","toAddr","toChange","feeFromAmount","feePerByte","txOptions","txBuilder","tokenPrivKeys","privKeys","k","templateData","TransactionBuilder","Transaction","builder","options","allKeys","usedKeys","origAmount","out","utxos","utxo","input","hdkey","unspent","txFee","hasChange","err","UnitUtils","outTokenAmount","tokenHex","inTokenAmount","tip","obj","generateNewMnemonic","size","generateMnemonic","wordlist","isMnemonicValid","validateMnemonic","deriveKey","password","salt","argon2idAsync","encryptMnemonic","phrase","iv","cipher","gcm","encBuf","decryptMnemonic","encSeed","validateAndDecryptMnemonic","decMn","currencySymbols","currencies","getNexaPrices","vs_currencies","getCurrencySymbol","initializePrices","prices","getVaultTemplate","Script","Opcode","getVaultTemplateHash","template","Hash","generateVaultConstraint","pubKey","getVaultConstraintHash","constraint","generateVaultVisibleArgs","args","ScriptOpcode","BNExtended","generateVaultAddress","templateHash","constraintHash","visibleArgs","SessionManager","keyManager","request","provider","sessionInfo","accountSessions","sessionMap","accounts","storedSessions","currentSessions","loadedSessions","DAppProvider","details","appInfo","messages","msg","results","result","sessions","payload","handleRequest","signMsgReq","addTokenReq","sendTransactionReq","signTransactionReq","TransactionTransformer","assetService","hex","addressKey","context","promises","i","p","Output","output","subscript","txSig","TxSigner","SighashType","ScriptFactory","placeholderIndex","sigHashBuf","sigHashType","templateBuf","OutputSighashType","n","sentAmount","sum","receivedAmount","HODL_FIRST_BLOCK","HODL_SCRIPT_PREFIX","WalletDiscoveryService","keySpace","stop","addrBatch","rAddr","addresses","vaultsPromises","vaults","set","history","hodls","hodl","scirptTemplate","buf","BufferWriter","actualAddress","block","expectedAddress","WalletManager","transactionService","sessionManager","addr","rIndexPromise","cIndexPromise","dappIndexPromis","rIndex","cIndex","dappIndex","entry","accs","tokensLoadPromises","walletAddresses","space","startIndex","count","newAddresses","addressDTO","newAccounts","acc","isInit","subscriptionPromises","initPromises","subscriptionResults","addrDTO","updateInfo","updates","accountsHistoryPromises","vaultsHistoryPromises","walletHistoryPromises","update","accountsTxs","walletTxs","resolver","txHistoryMap","txs","walletBalance","walletTokenBalances","nftPromise","spaceName","unused","needed","lastIndex","addrs","found","initialState","authSlice","createSlice","state","action","authActions","authReducer","dappModalSlice","dappModalActions","dappModalReducer","initState","loaderSlice","counter","loaderActions","loaderReducer","notificationsSlice","notificationsActions","notificationsReducer","fetchPrice","createAsyncThunk","statusSlice","_","statusActions","statusReducer","walletSlice","walletActions","walletReducer","sharedReducers","useSharedSelector","useSelector","useAuth","useBlockHeight","useAccount","useSelectedAccount","useLastAccountId","useMainReceiveAddress","useWalletBalance","useTokenBalance","useDAppSession","useVaults","selectWalletNotificationsArray","createSelector","wallet","selectWeb3NotificationsArray","web3","selectAllNotificationsArray","useWalletNotifications","useWeb3Notifications","useAllNotifications"],"mappings":";;;;;;;;;;AAGO,MAAMA,IAAiB,IACjBC,KAAY,sBACZC,KAAoB,QACpBC,KAAuB;AAE7B,SAASC,IAAqB;AACnC,SAAOC,EAAS,kBAAkBA,EAAS;AAC7C;AAEO,SAASC,GAAmBC,GAAuB;AACxD,SAAGH,MACMG,KAAQ,qEAEVA,KAAQ;AACjB;AAEO,SAASC,EAAmBC,GAAiBC,IAAOC,EAAY,qBAA8B;AACnG,SAAOC,EAAQ,QAAQH,GAASJ,EAAS,gBAAgBK,CAAI;AAC/D;AAEO,SAASG,KAAyB;AACvC,SAAO,WAAYT,EAAA,IAAc,aAAa,EAAG;AACnD;AAEO,SAASU,IAA2B;AACzC,SAAO,KAAK,MAAM,KAAK,IAAA,IAAQ,GAAI;AACrC;AAEO,SAASC,GAA0BC,GAAiBC,GAAwB;AACjF,QAAMC,KAAgBD,IAASD,KAAW,GACpCG,wBAAW,KAAA;AACjB,SAAAA,EAAK,WAAWA,EAAK,WAAA,IAAeD,CAAY,GACzCC,EAAK,mBAAA;AACd;AAEO,SAASC,EAAcC,GAAgE;AAC5F,SAAO,CAACA,KAAOA,EAAI,WAAW;AAChC;AAEO,SAASC,GAAqBC,GAAcC,IAAY,GAAW;AACxE,MAAI,CAACD,KAAOA,EAAI,UAAUC;AACxB,WAAOD,KAAO;AAGhB,QAAME,IAAW,OACXC,IAAa,KAAK,OAAOF,IAAYC,EAAS,UAAU,CAAC,GACzDE,IAAYJ,EAAI,MAAM,GAAGG,CAAU,GACnCE,IAAaL,EAAI,MAAMA,EAAI,SAASG,CAAU;AAEpD,SAAOC,IAAYF,IAAWG;AAChC;AAEO,SAASC,GAAsBN,GAAqB;AACzD,SAAIA,EAAI,WAAW,IACV,KAEFA,EAAI,OAAO,CAAC,EAAE,gBAAgBA,EAAI,UAAU,CAAC;AACtD;AAEO,SAASO,EAAiBrB,GAA6B;AAC5D,SAAIsB,EAAY,OAAOtB,CAAO,IACrBuB,EAAY,YAAYvB,CAAO,IAEjCG,EAAQ,WAAWH,CAAO,EAAE;AACrC;AAEO,SAASwB,EAAaC,GAAuB;AAClD,SAAIH,EAAY,OAAOG,CAAK,IACnBA,IAEFF,EAAY,YAAYF,EAAiBI,CAAK,CAAC;AACxD;AAEO,SAASC,GAAeD,GAAuB;AACpD,SAAKH,EAAY,OAAOG,CAAK,IAGtB,IAAItB,EAAQkB,EAAiBI,CAAK,GAAG7B,EAAS,gBAAgBM,EAAY,cAAc,EAAE,SAAA,IAFxFuB;AAGX;AAEO,SAASE,EAAyBC,GAA2C;AAClF,SAAIA,KAAU,QAAQA,MAAW,KACxB,KAEL,OAAOA,CAAM,KAAK,KACb,MAEFA,EAAO,SAAA;AAChB;AAEO,SAASC,GAAWC,GAA8B;AACvD,MAAIC,IAAY,OAAO,CAAC,GAAGC,IAAc,OAAO,CAAC;AACjD,SAAAF,EAAS,QAAQ,CAAAG,MAAK;AACpB,IAAAF,KAAa,OAAOE,EAAE,SAAS,GAC/BD,KAAe,OAAOC,EAAE,WAAW;AAAA,EACrC,CAAC,GACM,EAAC,WAAWF,EAAU,SAAA,GAAY,aAAaC,EAAY,WAAS;AAC7E;AAEO,SAASE,EAAiBJ,GAA8D;AAC7F,QAAMK,IAAyC,CAAA;AAC/C,SAAAL,EAAS,QAAQ,CAAAG,MAAK;AACpB,eAAWG,KAAOH;AAChB,MAAIE,EAAcC,CAAG,KACnBD,EAAcC,CAAG,EAAE,aAAa,OAAOD,EAAcC,CAAG,EAAE,SAAS,IAAI,OAAOH,EAAEG,CAAG,EAAE,SAAS,GAAG,SAAA,GACjGD,EAAcC,CAAG,EAAE,eAAe,OAAOD,EAAcC,CAAG,EAAE,WAAW,IAAI,OAAOH,EAAEG,CAAG,EAAE,WAAW,GAAG,SAAA,KAEvGD,EAAcC,CAAG,IAAI,EAAE,WAAW,OAAOH,EAAEG,CAAG,EAAE,SAAS,EAAE,YAAY,aAAa,OAAOH,EAAEG,CAAG,EAAE,WAAW,EAAE,WAAS;AAAA,EAG9H,CAAC,GAEMD;AACT;AAEA,MAAME,KAAyB;AAAA;AAAA;AAAA,EAG7B,QAAQ,EAAE,OAAO,SAAS,MAAM,YAAA;AAAA,EAChC,QAAQ,EAAE,OAAO,SAAS,MAAM,YAAA;AAAA,EAChC,SAAS,EAAE,OAAO,SAAS,MAAM,aAAA;AAAA,EACjC,QAAQ,EAAE,OAAO,SAAS,MAAM,aAAA;AAAA,EAChC,SAAS,EAAE,OAAO,SAAS,MAAM,aAAA;AAAA,EACjC,SAAS,EAAE,OAAO,SAAS,MAAM,aAAA;AAAA,EACjC,SAAS,EAAE,OAAO,SAAS,MAAM,aAAA;AAAA,EACjC,QAAQ,EAAE,OAAO,SAAS,MAAM,YAAA;AAAA;AAAA,EAGhC,QAAQ,EAAE,OAAO,SAAS,MAAM,YAAA;AAAA,EAChC,SAAS,EAAE,OAAO,SAAS,MAAM,aAAA;AAAA,EACjC,QAAQ,EAAE,OAAO,SAAS,MAAM,aAAA;AAAA,EAChC,SAAS,EAAE,OAAO,SAAS,MAAM,aAAA;AAAA,EACjC,QAAQ,EAAE,OAAO,SAAS,MAAM,kBAAA;AAAA;AAAA,EAGhC,QAAQ,EAAE,OAAO,SAAS,MAAM,aAAA;AAAA,EAChC,QAAQ,EAAE,OAAO,SAAS,MAAM,YAAA;AAAA,EAChC,QAAQ,EAAE,OAAO,SAAS,MAAM,YAAA;AAAA,EAChC,QAAQ,EAAE,OAAO,SAAS,MAAM,YAAA;AAClC;AAEO,SAASC,GAAiBC,GAA2D;AAC1F,QAAMC,IAAeD,EAAS,YAAY,GAAG;AAC7C,MAAIC,MAAiB,GAAI,QAAO;AAEhC,QAAMC,IAAYF,EAAS,MAAMC,CAAY,EAAE,YAAA;AAC/C,SAAOH,GAAuBI,CAAgD,GAAG,SAAS;AAC5F;AAEO,SAASC,GAAgBH,GAA0B;AACxD,QAAMC,IAAeD,EAAS,YAAY,GAAG;AAC7C,MAAIC,MAAiB,GAAI,QAAO;AAEhC,QAAMC,IAAYF,EAAS,MAAMC,CAAY,EAAE,YAAA;AAC/C,SAAOH,GAAuBI,CAAgD,GAAG,QAAQ;AAC3F;AC3JO,MAAeE,GAAQ;AAAA,EAOlB,YAAoB;AAC5B,WAAOhD,EAAA,IAAc,aAAa;AAAA,EACpC;AAAA,EAEA,MAAa,mBAA2C;AACtD,WAAO,KAAK,SAAS,MAAM;AAAA,EAC7B;AAAA,EAEA,MAAa,kBAAkBiD,GAA6B;AAC1D,WAAO,KAAK,SAAS,QAAQA,CAAI;AAAA,EACnC;AAAA,EAEA,MAAa,iBAAyC;AACpD,WAAO,KAAK,SAAS,cAAc;AAAA,EACrC;AAAA,EAEA,MAAa,eAAeC,GAA6B;AACvD,WAAO,KAAK,SAAS,gBAAgBA,CAAI;AAAA,EAC3C;AAAA,EAEA,MAAa,mBAA2C;AACtD,WAAO,KAAK,SAAS,gBAAgB;AAAA,EACvC;AAAA,EAEA,MAAa,iBAAiBC,GAAgC;AAC5D,WAAO,KAAK,SAAS,kBAAkBA,CAAO;AAAA,EAChD;AAAA,EAEA,MAAa,mBAAuD;AAClE,UAAMC,IAAS,MAAM,KAAK,SAAS,KAAK,UAAA,IAAc,gBAAgB;AACtE,QAAIA;AACF,aAAO,KAAK,MAAMA,CAAM;AAAA,EAE5B;AAAA,EAEA,MAAa,kBAAkBA,GAAsC;AACnE,WAAO,KAAK,SAAS,KAAK,UAAA,IAAc,kBAAkB,KAAK,UAAUA,CAAM,CAAC;AAAA,EAClF;AAAA,EAEA,MAAa,sBAAqC;AAChD,WAAO,KAAK,YAAY,KAAK,UAAA,IAAc,gBAAgB;AAAA,EAC7D;AAAA,EAEA,MAAa,uBAAuBC,GAA8B;AAChE,WAAO,KAAK,SAAS,eAAe,KAAK,UAAUA,CAAI,CAAC;AAAA,EAC1D;AAAA,EAEA,MAAa,yBAA2C;AAEtD,WADa,MAAM,KAAK,SAAS,aAAa,MAC9B;AAAA,EAClB;AAAA,EAEA,MAAa,wBAAwBA,GAA8B;AACjE,WAAO,KAAK,SAAS,eAAe,KAAK,UAAUA,CAAI,CAAC;AAAA,EAC1D;AAAA,EAEA,MAAa,0BAA4C;AAEvD,WADa,MAAM,KAAK,SAAS,aAAa,MAC9B;AAAA,EAClB;AAAA,EAEA,MAAa,sBAAuC;AAElD,WADc,MAAM,KAAK,SAAS,kBAAkB,KACpC;AAAA,EAClB;AAAA,EAEA,MAAa,oBAAoBC,GAAiC;AAChE,WAAO,KAAK,SAAS,oBAAoBA,CAAQ;AAAA,EACnD;AAAA,EAEA,MAAa,kBAAoC;AAE/C,WADc,MAAM,KAAK,SAAS,YAAY,MAC7B;AAAA,EACnB;AAAA,EAEA,MAAa,gBAAgBC,GAAsC;AACjE,WAAO,KAAK,SAAS,cAAc,KAAK,UAAUA,CAAY,CAAC;AAAA,EACjE;AAAA,EAEA,MAAa,iBAAmC;AAC9C,UAAMC,IAAQ,MAAM,KAAK,SAAS,MAAM;AACxC,WAAOxC,EAAcwC,CAAK,KAAKA,MAAU;AAAA,EAC3C;AAAA,EAEA,MAAa,eAAeC,GAAqC;AAC/D,UAAM,KAAK,SAAS,QAAQ,KAAK,UAAUA,CAAW,CAAC;AAAA,EACzD;AAAA,EAEA,MAAa,sBAAmD;AAC9D,UAAMD,IAAQ,MAAM,KAAK,SAAS,YAAY;AAC9C,WAAOA,IAAQ,OAAOA,CAAK,IAAI;AAAA,EACjC;AAAA,EAEA,MAAa,oBAAoBzC,GAA6B;AAC5D,IAAIC,EAAcD,CAAI,IACpB,MAAM,KAAK,YAAY,YAAY,IAEnC,MAAM,KAAK,SAAS,cAAcA,CAAI;AAAA,EAE1C;AAAA,EAEA,MAAa,eAAiC;AAE5C,WADc,MAAM,KAAK,SAAS,SAAS,MAC1B;AAAA,EACnB;AAAA,EAEA,MAAa,aAAaf,GAAmC;AAC3D,UAAM,KAAK,SAAS,WAAWA,IAAY,MAAM,GAAG;AAAA,EACtD;AAAA,EAEA,MAAa,qBAAsC;AACjD,UAAMwD,IAAQ,MAAM,KAAK,SAAS,WAAW;AAC7C,WAAOA,IAAQ,SAASA,CAAK,IAAI;AAAA,EACnC;AAAA,EAEA,MAAa,mBAAmBE,GAAiC;AAC/D,UAAM,KAAK,SAAS,aAAa,GAAGA,CAAQ,EAAE;AAAA,EAChD;AACF;AChIO,IAAKC,sBAAAA,OACVA,EAAAA,EAAA,OAAO,CAAA,IAAP,QACAA,EAAAA,EAAA,QAAQ,CAAA,IAAR,SACAA,EAAAA,EAAA,OAAO,CAAA,IAAP,QAHUA,IAAAA,KAAA,CAAA,CAAA,GAMAC,sBAAAA,OACVA,EAAAA,EAAA,UAAU,CAAA,IAAV,WACAA,EAAAA,EAAA,SAAS,CAAA,IAAT,UAFUA,IAAAA,KAAA,CAAA,CAAA,GAKAC,sBAAAA,OACVA,EAAA,cAAc,eACdA,EAAA,WAAW,YACXA,EAAA,kBAAkB,mBAClBA,EAAA,kBAAkB,mBAJRA,IAAAA,KAAA,CAAA,CAAA,GAOAC,sBAAAA,OACVA,EAAA,QAAQ,SACRA,EAAA,MAAM,OAFIA,IAAAA,KAAA,CAAA,CAAA;ACJL,MAAMC,GAAS;AAAA,EAEH;AAAA,EACT;AAAA,EAER,YAAYC,GAAgB;AAC1B,SAAK,QAAQA;AAAA,EACf;AAAA,EAEO,SAASC,GAAkC;AAChD,SAAK,iBAAiBA;AAAA,EACxB;AAAA,EAEQ,OAAOC,GAAsB;AACnC,SAAK,iBAAiBA,CAAK;AAAA,EAC7B;AAAA,EAEA,MAAa,aAA+B;AAC1C,WAAO,KAAK,MAAM,WAAA;AAAA,EACpB;AAAA,EAEA,MAAa,YAA2B;AACtC,WAAO,KAAK,MAAM,UAAA;AAAA,EACpB;AAAA,EAEA,MAAa,oBAAoBC,GAAsC;AACrE,QAAI;AACF,YAAM,KAAK,MAAM,kBAAkBA,CAAE,GACrC,KAAK,OAAO,EAAE,MAAM,aAAA,CAAc;AAAA,IACpC,SAASC,GAAO;AACd,cAAQ,MAAMA,CAAK;AAAA,IACrB;AAAA,EACF;AAAA,EAEA,MAAa,oBAAoBC,GAAgD;AAC/E,WAAO,KAAK,MAAM,uBAAuBA,CAAO;AAAA,EAClD;AAAA,EAEA,MAAa,qBAAqBC,GAAiBC,GAA4D;AAC7G,WAAO,KAAK,MAAM,gBAAgBD,GAASC,CAAO;AAAA,EACpD;AAAA,EAEA,MAAa,yBAAyBD,GAAiBE,GAAiBC,GAAkBF,GAA4D;AACpJ,WAAO,KAAK,MAAM,oBAAoBD,GAASE,GAASC,GAAUF,CAAO;AAAA,EAC3E;AAAA,EAEA,MAAa,uBAAuBD,GAAiBC,GAAmC;AACtF,WAAO,KAAK,MAAM,kBAAkBD,GAASC,CAAO;AAAA,EACtD;AAAA,EAEA,MAAa,uBAAuBD,GAAgC;AAClE,UAAM,KAAK,MAAM,kBAAkBA,CAAO,GAC1C,KAAK,OAAO,EAAE,MAAM,aAAA,CAAc;AAAA,EACpC;AAAA,EAEA,MAAa,UAAUA,GAAiBxC,GAAmC;AACzE,UAAM4C,IAAqB;AAAA,MACzB,WAAWJ;AAAA,MACX,YAAYxC,EAAM;AAAA,MAClB,MAAMgC,EAAU;AAAA,MAChB,WAAWpD,EAAA;AAAA,IAAiB;AAE9B,UAAM,KAAK,MAAM,YAAYgE,CAAK,GAClC,MAAM,KAAK,MAAM,YAAY5C,CAAK,GAClC,KAAK,OAAO,EAAE,MAAM,eAAe,WAAWwC,GAAS,OAAOI,GAAO;AAAA,EACvE;AAAA,EAEA,MAAa,eAAeJ,GAAqD;AAC/E,WAAO,KAAK,MAAM,UAAUA,CAAO;AAAA,EACrC;AAAA,EAEA,MAAa,SAASK,GAA8C;AAClE,WAAO,KAAK,MAAM,SAASA,CAAE;AAAA,EAC/B;AAAA,EAEA,MAAa,YAAYL,GAAiBC,GAAgC;AACxE,UAAM,KAAK,YAAYD,GAASC,CAAO,GACzB,MAAM,KAAK,MAAM,gBAAgBA,CAAO,KACzC,KACX,MAAM,KAAK,MAAM,YAAYA,CAAO,GAEtC,KAAK,OAAO,EAAE,MAAM,iBAAiB,WAAWD,GAAS,SAAAC,GAAkB;AAAA,EAC7E;AAAA,EAEA,MAAa,QAAQG,GAAoBE,GAA+B;AACtE,UAAM,KAAK,MAAM,UAAUA,CAAG,GAC9B,MAAM,KAAK,UAAUF,GAAO,EAAI;AAAA,EAClC;AAAA,EAEA,MAAa,aAAaJ,GAAiBE,GAAiBC,GAAsD;AAChH,WAAO,KAAK,MAAM,QAAQH,GAASE,GAASC,CAAQ;AAAA,EACtD;AAAA,EAEA,MAAa,YAAYE,GAA4C;AACnE,WAAO,KAAK,MAAM,OAAOA,CAAE;AAAA,EAC7B;AAAA,EAEA,MAAa,UAAUL,GAAiBC,GAAiBM,IAAS,IAAsB;AACtF,UAAM,KAAK,YAAYP,GAASC,CAAO,GACzB,MAAM,KAAK,MAAM,gBAAgBA,CAAO,KACzC,MACX,MAAM,KAAK,MAAM,UAAUA,CAAO,GAClC,KAAK,OAAO,EAAE,MAAM,eAAe,IAAIA,GAAS,IAE9CM,KACF,KAAK,OAAO,EAAE,MAAM,cAAA,CAAe;AAAA,EAEvC;AAAA,EAEA,MAAa,eAAeP,GAAkC;AAC5D,WAAO,KAAK,MAAM,UAAUA,CAAO;AAAA,EACrC;AAAA,EAEA,MAAa,WAAWK,GAA8B;AACpD,WAAO,KAAK,MAAM,WAAWA,CAAE;AAAA,EACjC;AAAA,EAEA,MAAa,UAAUD,GAAoBI,IAAY,IAAsB;AAC3E,UAAM,KAAK,MAAM,YAAYJ,CAAK,GAC9BI,KACF,KAAK,OAAO,EAAE,MAAM,cAAA,CAAe;AAAA,EAEvC;AAAA,EAEA,MAAa,YAAYR,GAAiBK,GAA2B;AACnE,WAAO,KAAK,MAAM,YAAYL,GAASK,CAAE;AAAA,EAC3C;AAAA,EAEA,MAAa,uBAAuBL,GAAiBK,GAA8B;AACjF,WAAO,KAAK,MAAM,uBAAuBL,GAASK,CAAE;AAAA,EACtD;AAAA,EAEA,MAAa,YAAYL,GAAoC;AAC3D,UAAMS,IAA+B;AAAA,MACnC,IAAIT,EAAQ;AAAA,MACZ,SAASA,EAAQ;AAAA,MACjB,MAAMA,EAAQ;AAAA,MACd,QAAQA,EAAQ;AAAA,MAChB,QAAQA,EAAQ;AAAA,MAChB,YAAYA,EAAQ;AAAA,MACpB,SAAS,KAAK,UAAUA,EAAQ,OAAO;AAAA,MACvC,eAAe,KAAK,UAAUA,EAAQ,aAAa;AAAA,IAAA;AAErD,WAAO,KAAK,MAAM,cAAcS,CAAa;AAAA,EAC/C;AAAA,EAEA,MAAa,cAAqC;AAEhD,YADa,MAAM,KAAK,MAAM,YAAA,GAClB,IAAI,CAAAC,OAAM;AAAA,MACpB,GAAGA;AAAA,MACH,MAAMrB,EAAY;AAAA,MAClB,SAAS,KAAK,MAAMqB,EAAE,OAAO;AAAA,MAC7B,eAAe,KAAK,MAAMA,EAAE,aAAa;AAAA,IAAA,EACzC;AAAA,EACJ;AAAA,EAEA,MAAa,gBAAiC;AAC5C,WAAO,KAAK,MAAM,cAAA;AAAA,EACpB;AAAA,EAEA,MAAa,kBAAkBV,GAAiBW,GAA6B;AAC3E,WAAO,KAAK,MAAM,kBAAkBX,GAASW,CAAI;AAAA,EACnD;AAAA,EAEA,MAAa,YAAYC,GAAuC;AAC9D,WAAO,KAAK,MAAM,cAAcA,CAAO;AAAA,EACzC;AAAA,EAEA,MAAa,mBAAmBC,GAA6C;AAC3E,WAAO,KAAK,MAAM,qBAAqBA,CAAS;AAAA,EAClD;AAAA,EAEA,MAAa,cAAcC,GAAkC;AAC3D,WAAO,KAAK,MAAM,cAAcA,CAAS;AAAA,EAC3C;AAAA,EAEA,MAAa,YAAY/E,GAAoC;AAC3D,UAAMgF,IAA+B;AAAA,MACnC,SAAShF,EAAQ;AAAA,MACjB,KAAKA,EAAQ;AAAA,MACb,OAAOA,EAAQ;AAAA,MACf,QAAQA,EAAQ;AAAA,MAChB,YAAYA,EAAQ;AAAA,MACpB,MAAMA,EAAQ;AAAA,MACd,SAAS,KAAK,UAAUA,EAAQ,OAAO;AAAA,MACvC,eAAe,KAAK,UAAUA,EAAQ,aAAa;AAAA,IAAA;AAErD,WAAO,KAAK,MAAM,cAAcgF,CAAa;AAAA,EAChD;AAAA,EAEC,MAAa,sBAA6C;AAExD,YADc,MAAM,KAAK,MAAM,oBAAA,GAClB,IAAI,CAAAL,OAAM;AAAA,MACrB,GAAGA;AAAA,MACH,MAAMrB,EAAY;AAAA,MAClB,SAAS,KAAK,MAAMqB,EAAE,OAAO;AAAA,MAC7B,eAAe,KAAK,MAAMA,EAAE,aAAa;AAAA,IAAA,EACzC;AAAA,EACJ;AAAA,EAEA,MAAa,qBAA4C;AAEvD,YADc,MAAM,KAAK,MAAM,mBAAA,GAClB,IAAI,CAAAA,OAAM;AAAA,MACrB,GAAGA;AAAA,MACH,MAAMrB,EAAY;AAAA,MAClB,SAAS,KAAK,MAAMqB,EAAE,OAAO;AAAA,MAC7B,eAAe,KAAK,MAAMA,EAAE,aAAa;AAAA,IAAA,EACzC;AAAA,EACJ;AAAA,EAEA,MAAa,iBAAkC;AAC7C,WAAO,KAAK,MAAM,eAAA;AAAA,EACpB;AAAA,EAEA,MAAa,YAAiC;AAE5C,YADe,MAAM,KAAK,MAAM,UAAA,GAClB,IAAI,CAAAM,OAAM;AAAA,MACtB,GAAGA;AAAA,MACH,MAAM3B,EAAY;AAAA,MAClB,SAAS,KAAK,MAAM2B,EAAE,OAAO;AAAA,MAC7B,eAAe,KAAK,MAAMA,EAAE,aAAa;AAAA,IAAA,EACzC;AAAA,EACJ;AAAA,EAEA,MAAa,UAAUC,GAAgC;AACrD,UAAMC,IAA2B;AAAA,MAC/B,SAASD,EAAM;AAAA,MACf,KAAKA,EAAM;AAAA,MACX,OAAOA,EAAM;AAAA,MACb,QAAQA,EAAM;AAAA,MACd,YAAYA,EAAM;AAAA,MAClB,SAAS,KAAK,UAAUA,EAAM,OAAO;AAAA,MACrC,eAAe,KAAK,UAAUA,EAAM,aAAa;AAAA,IAAA;AAEnD,WAAO,KAAK,MAAM,YAAYC,CAAW;AAAA,EAC3C;AACF;ACtPO,MAAMC,GAAY;AAAA,EAEN;AAAA,EAEA,6BAAa,IAAA;AAAA,EACb,2BAAW,IAAA;AAAA,EAErB,YAAYC,GAAoB;AACrC,SAAK,WAAWA;AAAA,EAClB;AAAA,EAEO,QAAc;AACnB,SAAK,OAAO,MAAA,GACZ,KAAK,KAAK,MAAA;AAAA,EACZ;AAAA,EAEA,MAAa,aAAaf,GAA8C;AAEtE,QADAA,IAAK9C,EAAa8C,CAAE,GAChB,KAAK,OAAO,IAAIA,CAAE;AACpB,aAAO,KAAK,OAAO,IAAIA,CAAE;AAG3B,UAAM7C,IAAQ,MAAM,KAAK,SAAS,SAAS6C,CAAE;AAC7C,WAAI7C,KACF,KAAK,OAAO,IAAI6C,GAAI7C,CAAK,GAEpBA;AAAA,EACT;AAAA,EAEA,MAAa,WAAW6C,GAA4C;AAElE,QADAA,IAAK9C,EAAa8C,CAAE,GAChB,KAAK,KAAK,IAAIA,CAAE;AAClB,aAAO,KAAK,KAAK,IAAIA,CAAE;AAGzB,UAAMC,IAAM,MAAM,KAAK,SAAS,YAAYD,CAAE;AAC9C,WAAIC,KACF,KAAK,KAAK,IAAID,GAAIC,CAAG,GAEhBA;AAAA,EACT;AAAA,EAEO,YAAYD,GAAkB;AACnC,SAAK,OAAO,OAAO9C,EAAa8C,CAAE,CAAC;AAAA,EACrC;AAAA,EAEO,UAAUA,GAAkB;AACjC,SAAK,KAAK,OAAO9C,EAAa8C,CAAE,CAAC;AAAA,EACnC;AACF;AC5CO,MAAMgB,GAAe;AAAA,EAET;AAAA,EAET;AAAA,EAED,YAAYC,GAAkB;AACnC,SAAK,UAAUA;AAAA,EACjB;AAAA,EAEO,cAAuC;AAC5C,WAAO,KAAK,QAAwB,iBAAiB;AAAA,EACvD;AAAA,EAEO,cAAiC;AACtC,WAAO,KAAK,QAAkB,wBAAwB;AAAA,EACxD;AAAA,EAEO,WAAWvF,GAAmC;AACnD,WAAO,KAAK,QAAiB,kCAAkCA,GAAS,gBAAgB;AAAA,EAC1F;AAAA,EAEO,uBAAuBA,GAAiBwF,IAAa,GAA0B;AACpF,WAAO,KAAK,QAAsB,kCAAkCxF,GAAS,EAAE,aAAawF,GAAY;AAAA,EAC1G;AAAA,EAEO,YAAYxF,GAAqC;AACtD,WAAO,KAAK,QAAmB,oCAAoCA,CAAO;AAAA,EAC5E;AAAA,EAEA,MAAa,cAAcA,GAAmC;AAC5D,QAAI;AACF,YAAMyF,IAAW,MAAM,KAAK,YAAYzF,CAAO;AAC/C,aAAO,CAAC,EAAEyF,EAAS,WAAWA,EAAS,YAAY;AAAA,IACrD,SAASC,GAAG;AACV,UAAIA,aAAa,SAASA,EAAE,QAAQ,SAAS,WAAW;AACtD,eAAO;AAET,YAAMA;AAAA,IACR;AAAA,EACF;AAAA,EAEO,eAAepB,GAAYqB,IAAU,IAA6B;AACvE,WAAO,KAAK,QAAsB,8BAA8BrB,GAAIqB,CAAO;AAAA,EAC7E;AAAA,EAEO,QAAQC,GAAkC;AAC/C,WAAO,KAAK,QAAe,uBAAuBA,CAAQ;AAAA,EAC5D;AAAA,EAEO,aAAa5F,GAAgD;AAClE,WAAO,KAAK,QAA8B,kCAAkCA,GAAS,gBAAgB;AAAA,EACvG;AAAA,EAEA,MAAa,cAAcA,GAAiByB,GAAsC;AAEhF,YADoB,MAAM,KAAK,QAA2B,6BAA6BzB,GAAS,MAAMyB,CAAK,GACxF;AAAA,EACrB;AAAA,EAEA,MAAa,iBAAiBzB,GAAmD;AAC/E,UAAMmC,IAAgB,MAAM,KAAK,QAAwB,6BAA6BnC,CAAO,GACvF6F,IAAmC,CAAA;AAEzC,eAAWC,KAAU3D,EAAc;AACjC,MAAIA,EAAc,UAAU2D,CAAM,KAAK,MACrCD,EAAQC,CAAM,IAAI,EAAE,WAAW,OAAO3D,EAAc,UAAU2D,CAAM,CAAC,EAAE,YAAY,aAAa,IAAA;AAIpG,eAAWC,KAAU5D,EAAc;AACjC,MAAIA,EAAc,YAAY4D,CAAM,KAAK,MACnCF,EAAQE,CAAM,IAChBF,EAAQE,CAAM,EAAE,cAAc,OAAO5D,EAAc,YAAY4D,CAAM,CAAC,EAAE,SAAA,IAExEF,EAAQE,CAAM,IAAI,EAAE,WAAW,KAAK,aAAa,OAAO5D,EAAc,YAAY4D,CAAM,CAAC,EAAE,WAAS;AAK1G,WAAOF;AAAA,EACT;AAAA,EAEO,gBAAgBpE,GAAuC;AAC5D,WAAO,KAAK,QAAuB,sBAAsBA,CAAK;AAAA,EAChE;AAAA,EAEO,UAAUuE,GAAgC;AAC/C,WAAO,KAAK,QAAgB,oCAAoCA,CAAK;AAAA,EACvE;AAAA,EAEO,iBAAiBC,GAAoE;AAC1F,WAAO,KAAK,OAAQ,UAAU,CAACC,MAAkB;AAC/C,YAAMC,IAAO,MAAM,QAAQD,CAAQ,IAAIA,EAAS,CAAC,IAAIA,GAC/CE,IAAS,OAAOD,GAAM,UAAW,WAAWA,EAAK,SAAS;AAChE,MAAAF,EAAQG,CAAM;AAAA,IAChB,GAAG,8BAA8B;AAAA,EACnC;AAAA,EAEO,iBAAiBpG,GAAiBiG,GAAoE;AAC3G,WAAO,KAAK,OAAQ,UAAUA,GAAS,gCAAgCjG,CAAO;AAAA,EAChF;AAAA,EAEA,MAAa,aAA8B;AACzC,QAAI;AACF,YAAMqG,IAAQ,KAAK,IAAA;AAEnB,aADY,MAAM,KAAK,YAAA,IAEd,KAAK,QAAQA,IAEf;AAAA,IACT,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAa,QAAQtD,GAAuC;AAC1D,QAAI;AACF,MAAKA,MACHA,IAAS,MAAM,KAAK,mBAAA,IAGtB,KAAK,SAAS,IAAIuD,GAAe,qBAAqB,SAASvD,EAAO,MAAMA,EAAO,MAAMA,EAAO,QAAQ,KAAG,KAAM,KAAG,GAAI,GACxH,MAAM,KAAK,OAAO,QAAA;AAAA,IACpB,SAAS2C,GAAG;AACV,YAAIA,aAAa,QACf,QAAQ,KAAKA,EAAE,OAAO,IAEtB,QAAQ,MAAMA,CAAC,GAEXA;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAa,WAAWa,GAAmC;AACzD,QAAI;AACF,aAAO,MAAM,KAAK,QAAQ,WAAWA,CAAK,KAAK;AAAA,IACjD,SAASb,GAAG;AACV,qBAAQ,MAAMA,CAAC,GACR;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAc,QAAWc,MAAmBC,GAAwC;AAClF,UAAM,KAAK,kBAAA;AACX,UAAMC,IAAM,MAAM,KAAK,OAAQ,QAAQF,GAAQ,GAAGC,CAAU;AAC5D,QAAIC,aAAe;AACjB,YAAMA;AAER,WAAOA;AAAA,EACT;AAAA,EAEQ,kBAAkBC,IAAU,KAAqB;AACvD,UAAMN,IAAQ,KAAK,IAAA;AAEnB,WAAO,IAAI,QAAQ,CAACO,GAASC,MAAW;AACtC,YAAMC,IAAQ,MAAY;AACxB,YAAI,KAAK,QAAQ,oBAAoBC,GAAiB;AACpD,iBAAOH,EAAA;AAET,YAAI,KAAK,QAAQP,IAAQM;AACvB,iBAAOE,EAAO,IAAI,MAAM,4BAA4B,CAAC;AAEvD,mBAAWC,GAAO,GAAG;AAAA,MACvB;AAEA,MAAAA,EAAA;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAa,qBAA6C;AACxD,UAAM/D,IAAS,MAAM,KAAK,QAAQ,iBAAA;AAClC,WAAIA,KAGGuC,GAAe,uBAAA,EAAyB,CAAC;AAAA,EAClD;AAAA,EAEA,OAAc,yBAA0C;AACtD,WAAI3F,MACK;AAAA,MACL;AAAA,QACE,QAAQqH,EAAgB;AAAA,QACxB,MAAM;AAAA,QACN,MAAM;AAAA,QACN,OAAO;AAAA,MAAA;AAAA,IACT,IAGK;AAAA,MACL;AAAA,QACE,QAAQA,EAAgB;AAAA,QACxB,MAAM;AAAA,QACN,MAAM;AAAA,QACN,OAAO;AAAA,MAAA;AAAA,MAET;AAAA,QACE,QAAQA,EAAgB;AAAA,QACxB,MAAM;AAAA,QACN,MAAM;AAAA,QACN,OAAO;AAAA,MAAA;AAAA,IACT;AAAA,EAGN;AACF;AClNO,SAASC,EAAgBhD,GAAsBhE,GAAgBiH,GAAuB;AAC3F,SAAO,GAAGjD,CAAO,KAAKhE,CAAI,IAAIiH,CAAK;AACrC;AAEO,SAASC,GAAgBC,GAAuB;AACrD,QAAMC,IAAQD,EAAK,MAAM,GAAG;AAC5B,SAAO;AAAA,IACL,SAAS,SAASC,EAAM,CAAC,EAAE,QAAQ,KAAK,EAAE,CAAC;AAAA,IAC3C,MAAM,SAASA,EAAM,CAAC,CAAC;AAAA,IACvB,OAAO,SAASA,EAAM,CAAC,CAAC;AAAA,EAAA;AAE5B;ACRO,MAAMC,GAAW;AAAA,EAEd;AAAA,EACA;AAAA,EACA,kCAAkB,IAAA;AAAA,EAClB,iCAAiB,IAAA;AAAA,EAElB,KAAKC,GAAqC;AAC/C,SAAK,OAAO,OAAOA,KAAa,WAAWC,GAAmBD,CAAQ,IAAIA,GAC1E,KAAK,YAAYE,EAAa,SAAS,KAAK,IAAI,EAAE,YAAY,IAAI,EAAI,EAAE,YAAY,OAAO,EAAI;AAAA,EACjG;AAAA,EAEO,QAAc;AACnB,QAAI,CAAC,KAAK;AACR,YAAM,IAAI,MAAM,6BAA6B;AAE/C,SAAK,YAAYA,EAAa,SAAS,KAAK,IAAI,EAAE,YAAY,IAAI,EAAI,EAAE,YAAY,OAAO,EAAI,GAC/F,KAAK,YAAY,MAAA,GACjB,KAAK,WAAW,MAAA;AAAA,EAClB;AAAA,EAEQ,cAAcxD,GAAoC;AACxD,QAAI7B,IAAM,KAAK,YAAY,IAAI6B,CAAO;AACtC,WAAK7B,MACHA,IAAM,KAAK,UAAU,YAAY6B,GAAS,EAAI,GAC9C,KAAK,YAAY,IAAIA,GAAS7B,CAAG,IAG5BA;AAAA,EACT;AAAA,EAEO,OAAOsF,GAAyC;AACrD,UAAMN,IAAO,OAAOM,KAAY,WAC5BA,IACAT,EAAgBS,EAAQ,SAASA,EAAQ,MAAMA,EAAQ,KAAK;AAEhE,QAAItF,IAAM,KAAK,WAAW,IAAIgF,CAAI;AAClC,QAAI,CAAChF,GAAK;AACR,YAAM,EAAE,SAAA6B,GAAS,MAAAhE,GAAM,OAAAiH,EAAA,IAAU,OAAOQ,KAAY,WAChDP,GAAgBO,CAAO,IACvBA;AAEJ,MAAAtF,IADmB,KAAK,cAAc6B,CAAO,EAC5B,YAAYhE,GAAM,EAAK,EAAE,YAAYiH,GAAO,EAAK,GAClE,KAAK,WAAW,IAAIE,GAAMhF,CAAG;AAAA,IAC/B;AAEA,WAAOA;AAAA,EACT;AACF;AClDO,SAASuF,KAA6B;AAC3C,SAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,aAAa;AAAA,IACb,OAAOhI,MACH,2EACA;AAAA,IACJ,YAAYA,MACR,qEACA;AAAA,IACJ,UAAU;AAAA,EAAA;AAEd;AAEO,SAASiI,GAActD,GAAiC;AAC7D,SAAOuD,EAAWC,OAAqBxD,GAAI,KAAK;AAClD;AAEO,SAASyD,EAAgBC,GAAwB;AACtD,MAAI;AACF,UAAMC,IAAU5G,EAAiB2G,CAAK;AACtC,WAAKE,EAAW,WAAWD,CAAO,IAI3B1G,EAAY,YAAY0G,EAAQ,SAAS,GAAG,EAAE,CAAC,MAAMN,GAAA,EAAgB,aAHjE;AAAA,EAIb,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAASQ,GAAcC,GAA2B;AAGvD,SAAAA,IAAMC,EAAmBD,CAAG,GACrBP,EAAWO,GAAK,MAAM;AAC/B;AAEO,SAASE,GAAeF,GAAkC;AAG/D,SAAAA,IAAMC,EAAmBD,CAAG,GACrBP,EAAWO,GAAK,KAAK;AAC9B;AAEO,SAASG,GAAsBC,GAAcC,GAA6B;AAC/E,SAAID,KAAQ,OAAOA,KAAS,WACtBA,EAAK,WAAW,MAAM,IACjBA,EAAK,QAAQ,WAAW,UAAU,IAEvCA,EAAK,WAAW,SAAS,IACpBA,IAGF,GADK,IAAI,IAAIC,CAAW,EACjB,MAAM,GAAGD,CAAI,KAEtB;AACT;AAEO,SAASE,GAAkBvC,GAA8B;AAC9D,SAAKA,IAGEkC,EAAmBlC,CAAI,IAFrB;AAGX;AAEA,SAASkC,EAAmBD,GAAaO,IAAU,gCAAwC;AAIzF,SAAIP,GAAK,WAAW,SAAS,IACpBO,IAAUP,EAAI,UAAU,CAAC,IAE3BA;AACT;AAEA,SAASN,KAA2B;AAClC,SAAO,WAAWnI,EAAA,IAAc,aAAa,EAAE;AACjD;AAEA,eAAekI,EAAWO,GAAaQ,GAA6C;AAClF,MAAI;AACF,UAAM1C,IAAW,MAAM,MAAMkC,CAAG;AAChC,QAAI,CAAClC,EAAS;AACZ,YAAM,IAAI,MAAM,kCAAkCA,EAAS,MAAM,EAAE;AAGrE,QAAI0C,MAAiB,OAAO;AAC1B,YAAMC,IAAc,MAAM3C,EAAS,YAAA;AACnC,aAAO,IAAI,WAAW2C,CAAW;AAAA,IACnC;AACE,aAAO,MAAM3C,EAAS,KAAA;AAAA,EAE1B,SAASR,GAAG;AACV,UAAM,IAAI,MAAM,qBAAqBA,CAAC,EAAE;AAAA,EAC1C;AACF;AC3FO,MAAMoD,GAAa;AAAA,EAEP;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAYzD,GAAoB0D,GAAgCC,GAA0B;AACxF,SAAK,WAAW3D,GAChB,KAAK,iBAAiB0D,GACtB,KAAK,cAAcC;AAAA,EACrB;AAAA,EAEA,MAAa,aAAavH,GAAewH,IAAa,IAAwC;AAC5F,QAAI;AACF,UAAIA,GAAY;AACd,cAAMC,IAAc,MAAM,KAAK,YAAY,aAAazH,CAAK;AAC7D,YAAIyH;AACF,iBAAOA;AAAA,MAEX;AAEA,YAAMC,IAAU,MAAM,KAAK,eAAe,gBAAgB1H,CAAK,GACzD2H,IAAU7H,EAAY,YAAY4H,EAAQ,YAAY;AAC5D,UAAIE,IAAS,IACTC,IAAU;AAEd,UAAIH,EAAQ,gBAAgBI,EAAY,QAAQJ,EAAQ,gBAAgBI,EAAY,QAAQxB,EAAgBtG,CAAK;AAC/G;AAOF,UAJIyG,EAAW,WAAWkB,CAAO,MAC/BC,IAAS,IAAIlJ,EAAQ+H,EAAW,iBAAiBkB,CAAO,GAAGxJ,EAAS,gBAAgBM,EAAY,cAAc,EAAE,SAAA,IAG9GiJ,EAAQ;AACV,YAAI;AACF,cAAIA,EAAQ,gBAAgBI,EAAY,MAAM;AAC5C,kBAAMC,IAAY,MAAMlB,GAAea,EAAQ,YAAY,GAErDM,KADM,MAAMC,GAAM,UAAUF,CAAS,GAC1B,KAAK,WAAW;AACjC,gBAAIC,GAAM;AACR,oBAAME,IAAW,MAAMF,EAAK,MAAM,QAAQ,GACpCG,IAAW,KAAK,MAAMD,CAAQ;AACpC,cAAAL,IAAUf,GAAsBqB,EAAS,CAAC,GAAG,MAAMT,EAAQ,YAAY;AAAA,YACzE;AAAA,UACF,OAAO;AACL,kBAAMS,IAAW,MAAMzB,GAAcgB,EAAQ,YAAY;AACzD,YAAAG,IAAUf,GAAsBqB,EAAS,CAAC,GAAG,MAAMT,EAAQ,YAAY;AAAA,UACzE;AAAA,QACF,SAASzD,GAAG;AACV,kBAAQ,MAAM,2BAA2BA,CAAC;AAAA,QAC5C;AAaF,aAViC;AAAA,QAC/B,OAAOyD,EAAQ;AAAA,QACf,YAAYA,EAAQ;AAAA,QACpB,UAAUA,EAAQ,kBAAkB;AAAA,QACpC,aAAaE;AAAA,QACb,MAAMF,EAAQ,QAAQ;AAAA,QACtB,QAAQA,EAAQ,UAAU;AAAA,QAC1B,SAAAG;AAAA,MAAA;AAAA,IAIJ,SAAS5D,GAAG;AACV,cAAQ,MAAMA,CAAC;AACf;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAa,WAAWjE,GAAiC;AACvD,QAAI;AAWF,UAVIsG,EAAgBtG,CAAK,KAIL,MAAM,KAAK,YAAY,WAAWA,CAAK,MAK3C,MAAM,KAAK,eAAe,gBAAgBA,CAAK,GACnD,gBAAgB8H,EAAY;AACtC,eAAO;AAAA,IAEX,SAAS7D,GAAG;AACV,cAAQ,MAAMA,CAAC;AAAA,IACjB;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAa,aAAajE,GAA+C;AACvE,QAAI4C,IAA+B,MAAM,KAAK,aAAa5C,CAAK;AAChE,WAAK4C,KACW,MAAM,KAAK,WAAW5C,CAAK,MAEvC4C,IAAQ;AAAA,MACN,OAAO3C,GAAeD,CAAK;AAAA,MAC3B,YAAYD,EAAaC,CAAK;AAAA,MAC9B,UAAU;AAAA,IAAA,IAIT4C;AAAA,EACT;AAAA,EAEA,MAAa,iBAAiBS,GAAmB+E,GAAoBnJ,GAA6B;AAEhG,QADc,MAAM,KAAK,SAAS,WAAWmJ,CAAU,GAC5C;AACT,YAAMxF,IAAqB;AAAA,QACzB,WAAAS;AAAA,QACA,YAAA+E;AAAA,QACA,MAAMpG,EAAU;AAAA,QAChB,WAAW/C;AAAA,MAAA;AAEb,YAAM,KAAK,SAAS,UAAU2D,GAAO,EAAI;AACzC;AAAA,IACF;AAEA,UAAM8E,IAAU,MAAM,KAAK,eAAe,gBAAgBU,CAAU;AACpE,QAAIV,EAAQ,gBAAgBI,EAAY,MAAM;AAC5C,YAAMH,IAAU/H,EAAiBwI,CAAU;AAC3C,UAAI3B,EAAW,WAAWkB,CAAO,GAAG;AAClC,cAAMU,IAAgB,IAAI3J,EAAQiJ,EAAQ,SAAS,GAAG,EAAE,GAAGxJ,EAAS,gBAAgBM,EAAY,cAAc,EAAE,SAAA,GAC1G6J,IAAgB,MAAM,KAAK,eAAe,gBAAgBD,CAAa;AAC7E,QAAIC,GAAe,gBAAgBR,EAAY,QAG7C,MAAM,KAAK,QAAQzE,GAAW+E,GAAYV,EAAQ,gBAAgB,IAAIW,GAAepJ,GAAMqJ,GAAe,QAAQ,EAAE;AAAA,MAExH;AAAA,IACF,MAAA,CAAWhC,EAAgB8B,CAAU,KAEnC,MAAM,KAAK,QAAQ/E,GAAW+E,GAAY,SAASlC,KAAgB,OAAOjH,GAAM,EAAE;AAAA,EAEtF;AAAA,EAEA,MAAc,QAAQuD,GAAiB+F,GAAeC,GAAgBZ,GAAgB3I,GAAcwJ,GAAmC;AACrI,QAAKD;AAIL,UAAI;AACF,cAAM5F,IAAqB;AAAA,UACzB,WAAWJ;AAAA,UACX,YAAY+F;AAAA,UACZ,MAAMvG,EAAU;AAAA,UAChB,WAAW/C;AAAA,QAAA,GAEPyJ,IAAuB;AAAA,UAC3B,aAAad;AAAA,UACb,OAAO3H,GAAesI,CAAK;AAAA,UAC3B,YAAYA;AAAA,UACZ,QAAAC;AAAA,UACA,YAAAC;AAAA,QAAA;AAGF,cAAM,KAAK,SAAS,QAAQ7F,GAAO8F,CAAS;AAAA,MAC9C,SAASzE,GAAG;AACV,gBAAQ,MAAM,sBAAsBA,CAAC;AAAA,MACvC;AAAA,EACF;AAAA,EAEA,MAAa,mBAAmBZ,GAAmBsF,GAAuD;AACxG,eAAWlG,KAAWkG,GAAe;AACnC,YAAM3I,IAAQ,MAAM,KAAK,aAAayC,CAAO;AAC7C,MAAIzC,KACF,MAAM,KAAK,SAAS,UAAUqD,GAAWrD,CAAK;AAAA,IAElD;AAAA,EACF;AAAA,EAEA,MAAa,SAASqD,GAAmB3C,GAAuD;AAC9F,UAAMkI,IAAgB,OAAO,KAAKlI,CAAa,GACzCmI,IAAiB,MAAM,KAAK,SAAS,aAAaxF,GAAW,GAAG,GAAI,GAEpEyF,IAAkB,OAAOrG,MAAmC;AAChE,YAAM,KAAK,SAAS,UAAUY,GAAWZ,GAAS,EAAI,GACtD,KAAK,YAAY,UAAUA,CAAO;AAAA,IACpC,GAEMsG,IAAcF,GAAgB,OAAO,CAAA3F,MAAK,CAAC0F,EAAc,SAAS1F,EAAE,UAAU,CAAC,KAAK,CAAA;AAC1F,eAAWN,KAASmG;AAClB,YAAMD,EAAgBlG,EAAM,UAAU;AAGxC,eAAW,CAAC5C,GAAOoE,CAAO,KAAK,OAAO,QAAQ1D,CAAa,GAAG;AAC5D,YAAM+B,IAAU1C,EAAaC,CAAK,GAC5BgJ,IAAa5E,KAAW,OAAOA,EAAQ,SAAS,IAAI,OAAOA,EAAQ,WAAW,IAAI,IAClF6E,IAAeJ,GAAgB,KAAK,CAAA3F,MAAKA,EAAE,cAAcT,CAAO;AAMtE,MALK,CAACuG,KAAc,CAACC,KAAkBD,KAAcC,KAKjD,CADU,MAAM,KAAK,WAAWxG,CAAO,MAKvC,CAACuG,KAAcC,IACjB,MAAMH,EAAgBrG,CAAO,IAE7B,MAAM,KAAK,iBAAiBY,GAAWZ,GAAS7D,GAAkB;AAAA,IAEtE;AAAA,EACF;AACF;ACpMO,MAAMsK,GAAmB;AAAA,EAEb;AAAA,EACA;AAAA,EACA;AAAA,EAEA,qBAAqB;AAAA,EAE/B,YAAY5B,GAAgC6B,GAAyBvF,GAAoB;AAC9F,SAAK,iBAAiB0D,GACtB,KAAK,aAAa6B,GAClB,KAAK,WAAWvF;AAAA,EAClB;AAAA,EAEA,MAAa,qBAAqBW,GAAgC;AAChE,WAAO,KAAK,eAAe,UAAUA,CAAK;AAAA,EAC5C;AAAA,EAEA,MAAa,yBAAyBhG,GAAiBwF,GAAsE;AAC3H,QAAIqF,IAAYrF;AAEhB,UAAMsF,IAAmBtF,IAAa,IAAIA,IAAa,IAAI,GACrDuF,IAAY,MAAM,KAAK,eAAe,uBAAuB/K,GAAS8K,CAAgB;AAE5F,eAAWhH,KAAMiH;AACf,MAAAF,IAAY,KAAK,IAAIA,GAAW/G,EAAG,MAAM;AAG3C,WAAO,EAAC,KAAKiH,GAAW,YAAYF,EAAA;AAAA,EACtC;AAAA,EAEA,MAAa,uBAAuB7K,GAA4C;AAC9E,UAAM+K,IAAY,MAAM,KAAK,eAAe,uBAAuB/K,GAASP,EAAiB,GAEvFuL,IAA0C,CAAA;AAChD,eAAWlH,KAAMiH,GAAW;AAC1B,YAAME,IAAU,KAAK,oBAAoBnH,EAAG,SAAS,CAAC9D,CAAO,CAAC;AAC9D,MAAAgL,EAAa,KAAKC,CAAO;AAAA,IAC3B;AAEA,WAAO,QAAQ,IAAID,CAAY;AAAA,EACjC;AAAA,EAEA,MAAa,2BAA2BlG,GAAmBoG,GAAgBC,GAAsC;AAC/G,UAAMC,IAAQ,MAAM,KAAK,oBAAoBF,GAAQC,CAAW;AAChE,IAAAC,EAAM,YAAYtG;AAElB,UAAMuG,IAA8B;AAAA,MAClC,GAAGD;AAAA,MACH,eAAe,KAAK,UAAUA,EAAM,aAAa;AAAA,MACjD,WAAW,KAAK,UAAUA,EAAM,SAAS;AAAA,MACzC,UAAU,KAAK,UAAUA,EAAM,QAAQ;AAAA,IAAA,GAGnCE,wBAAqB,IAAA;AAC3B,IAAAF,EAAM,SAAS,QAAQ,CAAAG,MAAKA,EAAE,WAAWD,EAAe,IAAIC,EAAE,OAAO,CAAC,GACtEH,EAAM,UAAU,QAAQ,CAAAG,MAAKA,EAAE,WAAWD,EAAe,IAAIC,EAAE,OAAO,CAAC;AAEvE,eAAWC,KAAWF;AACpB,YAAM,KAAK,SAAS,oBAAoB;AAAA,QACtC,WAAAxG;AAAA,QACA,SAAA0G;AAAA,QACA,QAAQJ,EAAM;AAAA,QACd,MAAMA,EAAM;AAAA,MAAA,CACb;AAEH,UAAM,KAAK,SAAS,oBAAoBC,CAAQ;AAAA,EAClD;AAAA,EAEA,MAAc,oBAAoBH,GAAgBC,GAAgD;AAChG,UAAMM,IAAI,MAAM,KAAK,eAAe,eAAeP,CAAM,GAEnDQ,IAA4B,CAAA,GAC5BC,IAAgC,CAAA,GAChCC,IAA6B,CAAA,GAC7BC,IAAiC,CAAA;AAEvC,eAAWC,KAAOL,EAAE,KAAK;AACvB,YAAMM,IAA0B;AAAA,QAC9B,SAASD,EAAI,UAAU,CAAC;AAAA,QACxB,YAAYA,EAAI,cAAc,SAAA;AAAA,QAC9B,SAASA,EAAI,gBAAgB;AAAA,QAC7B,aAAanK,EAAyBmK,EAAI,aAAa;AAAA,MAAA;AAEzD,MAAIX,EAAY,SAASY,EAAS,OAAO,IACvCL,EAAS,KAAKK,CAAQ,IAEtBJ,EAAa,KAAKI,CAAQ;AAAA,IAE9B;AAEA,eAAWC,KAAQP,EAAE,MAAM;AACzB,UAAI9K,EAAcqL,EAAK,aAAa,SAAS,EAAG;AAChD,YAAMD,IAA0B;AAAA,QAC9B,SAASC,EAAK,aAAa,UAAU,CAAC;AAAA,QACtC,YAAYA,EAAK,cAAc,SAAA;AAAA,QAC/B,SAASA,EAAK,aAAa,gBAAgB;AAAA,QAC3C,aAAarK,EAAyBqK,EAAK,aAAa,aAAa;AAAA,MAAA;AAEvE,MAAIb,EAAY,SAASY,EAAS,OAAO,IACvCH,EAAU,KAAKG,CAAQ,IAEvBF,EAAc,KAAKE,CAAQ;AAAA,IAE/B;AAEA,QAAI9L;AACJ,IAAIyL,EAAS,WAAW,IACtBzL,IAAO,YACE2L,EAAU,WAAW,IAC9B3L,IAAO,SACE0L,EAAa,WAAW,KAAKE,EAAc,WAAW,IAC/D5L,IAAO,SACE0L,EAAa,WAAW,KAAKE,EAAc,SAAS,IAC7D5L,IAAO,SACE0L,EAAa,SAAS,KAAKE,EAAc,WAAW,IAC7D5L,IAAO,YAEPA,IAAO;AAGT,UAAMgM,IAAcR,EAAE,SAAS;AAc/B,WAb8B;AAAA,MAC5B,WAAW;AAAA;AAAA,MACX,MAAMA,EAAE;AAAA,MACR,QAAQA,EAAE;AAAA,MACV,MAAMQ,IAAcR,EAAE,OAAOpL,EAAA;AAAA,MAC7B,QAAQ4L,IAAcR,EAAE,SAAS;AAAA,MACjC,MAAAxL;AAAA,MACA,KAAKwL,EAAE,YAAY,SAAA;AAAA,MACnB,eAAexL,KAAQ,UAAUA,KAAQ,SAAS4L,IAAgB,CAAA;AAAA,MAClE,WAAAD;AAAA,MACA,UAAAF;AAAA,IAAA;AAAA,EAIJ;AAAA,EAEA,MAAa,gCACXQ,GACAC,GACAC,GACAxK,GACAyK,GACA5K,GACA6K,GACAnG,GACsB;AACtB,UAAMoG,IAAuB;AAAA,MAC3B,eAAAF;AAAA,IAAA,GAGIG,IAAY,KAAK,mBAAmBL,GAAQvK,GAAQH,GAAO0E,CAAI;AACrE,IAAImG,KACFE,EAAU,WAAWF,CAAU;AAGjC,QAAIG,wBAAoB,IAAA;AACxB,IAAIhL,MACFgL,IAAgB,MAAM,KAAK,6BAA6BD,GAAWN,GAAME,GAAU3K,GAAO,OAAOG,CAAM,CAAC;AAE1G,UAAM8K,IAAW,MAAM,KAAK,4BAA4BF,GAAWN,GAAME,GAAUG,CAAS;AAC5F,WAAAE,EAAc,QAAQ,CAACxH,GAAG0H,MAAMD,EAAS,IAAIC,GAAG1H,CAAC,CAAC,GAE3C,MAAM,KAAK,oBAAoBuH,GAAW,MAAM,KAAKE,EAAS,OAAA,CAAQ,CAAC;AAAA,EAChF;AAAA,EAEA,MAAa,mCAAmCR,GAAoBE,GAAkBQ,GAAqD;AACzI,UAAML,IAAuB;AAAA,MAC3B,eAAe;AAAA,MACf,cAAAK;AAAA,IAAA,GAGIJ,IAAY,IAAIK,EAAA,GAChBH,IAAW,MAAM,KAAK,4BAA4BF,GAAWN,GAAME,GAAUG,CAAS;AAE5F,WAAO,KAAK,oBAAoBC,GAAW,MAAM,KAAKE,EAAS,OAAA,CAAQ,CAAC;AAAA,EAC1E;AAAA,EAEQ,mBAAmBP,GAAgBvK,GAAgBH,GAAgB0E,GAAmC;AAC5G,QAAI,CAACpG,EAAmBoM,CAAM,KAAK,CAACpM,EAAmBoM,GAAQjM,EAAY,kBAAkB;AAC3F,YAAM,IAAI,MAAM,kBAAkB;AAEpC,QAAKuB,KAAS,OAAOG,CAAM,IAAI,MAAQ,CAACH,KAAS,SAASG,CAAM,IAAIkL,EAAY;AAC9E,YAAM,IAAI,MAAM,wBAAwB;AAE1C,QAAKrL,KAAS,OAAOG,CAAM,IAAIpC,MAAe,CAACiC,KAAS,SAASG,CAAM,IAAIkL,EAAY;AACrF,YAAM,IAAI,MAAM,yBAAyB;AAG3C,UAAMC,IAAU,IAAIF,EAAA;AAKpB,QAJI1G,KACF4G,EAAQ,QAAQ5G,CAAI,GAGlB1E,GAAO;AACT,UAAI,CAAC1B,EAAmB0B,GAAOvB,EAAY,cAAc;AACvD,cAAM,IAAI,MAAM,kBAAkB;AAEpC,UAAIC,EAAQ,cAAcgM,CAAM,MAAM;AACpC,cAAM,IAAI,MAAM,+CAA+C;AAEjE,MAAAY,EAAQ,GAAGZ,GAAQW,EAAY,aAAarL,GAAO,OAAOG,CAAM,CAAC;AAAA,IACnE;AACE,MAAAmL,EAAQ,GAAGZ,GAAQvK,CAAM;AAG3B,WAAOmL;AAAA,EACT;AAAA,EAEA,MAAc,4BAA4BP,GAA+BN,GAAoBE,GAAkBY,GAAsD;AACnK,UAAMC,IAAUf,EAAK,OAAO,CAAAS,MAAK,OAAOA,EAAE,QAAQ,SAAS,IAAI,OAAOA,EAAE,QAAQ,WAAW,IAAI,EAAE;AACjG,QAAIhM,EAAcsM,CAAO;AACvB,YAAM,IAAI,MAAM,0BAA0B;AAG5C,UAAMC,wBAAe,IAAA,GACfC,IAAaH,EAAQ,gBAAgB,IAAI,OAAOR,EAAU,YAAY,QAAQ,KAAK,CAAAY,MAAOA,EAAI,QAAQ,EAAE,EAAG,KAAK;AAEtH,eAAWhL,KAAO6K,GAAS;AACzB,YAAMI,IAAQ,MAAM,KAAK,eAAe,aAAajL,EAAI,OAAO;AAChE,iBAAWkL,KAAQD,GAAO;AACxB,cAAME,IAAc;AAAA,UAClB,UAAUD,EAAK;AAAA,UACf,SAASlL,EAAI;AAAA,UACb,UAAUkL,EAAK;AAAA,UACf,cAAcN,EAAQ;AAAA,QAAA;AAIxB,YAFAR,EAAU,KAAKe,CAAK,GAEhB,CAACL,EAAS,IAAI9K,EAAI,OAAO,GAAG;AAC9B,gBAAMoL,IAAQ,KAAK,WAAW,OAAOpL,EAAI,OAAO;AAChD,UAAA8K,EAAS,IAAI9K,EAAI,SAASoL,EAAM,UAAU;AAAA,QAC5C;AAEA,YAAIR,EAAQ;AAEV,cADAR,EAAU,OAAOJ,CAAQ,GACrBI,EAAU,YAAY,OAAO,SAAS,KAAK;AAC7C,mBAAOU;AAAA,eAEJ;AACL,gBAAMpJ,IAAK0I,EAAU;AACrB,cAAI1I,EAAG,OAAO,SAAS,KAAK;AAC1B,kBAAM,IAAI,MAAM,+EAA+E;AAGjG,gBAAM2J,IAAU3J,EAAG,gBAAA;AACnB,cAAI2J,IAAU;AACZ;AAGF,cAAIA,KAAW,MAAMT,EAAQ,eAAe;AAC1C,kBAAMU,IAAQ5J,EAAG,oBAAA;AACjB,mBAAAA,EAAG,mBAAmB,GAAGqJ,IAAaO,CAAK,GACpCR;AAAA,UACT;AAGA,cADAV,EAAU,OAAOJ,CAAQ,GACrBY,EAAQ,eAAe;AACzB,kBAAMW,IAAY7J,EAAG,gBAAA;AACrB,gBAAI4J,IAAQ5J,EAAG,oBAAA;AACf,YAAAA,EAAG,mBAAmB,GAAGqJ,IAAaO,CAAK,GAGvC,CAACC,KAAa7J,EAAG,sBACnB4J,IAAQ5J,EAAG,oBAAA,GACXA,EAAG,mBAAmB,GAAGqJ,IAAaO,CAAK;AAAA,UAE/C;AAGA,cAAI5J,EAAG,gBAAA,IAAoBA,EAAG;AAE5B;AAGF,iBAAOoJ;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAEA,QAAIF,EAAQ,eAAe;AACzB,UAAIE,EAAS,OAAO;AAClB,eAAOA;AAET,YAAM,IAAI,MAAM,0BAA0B;AAAA,IAC5C;AAEA,UAAMU,IAAM;AAAA,MACV,UAAU;AAAA,MACV,QAAQC,GAAU,WAAWrB,EAAU,YAAY,QAAQ,CAAC,EAAE,KAAK;AAAA,MACnE,KAAKqB,GAAU,WAAWrB,EAAU,YAAY,qBAAqB;AAAA,IAAA;AAGvE,UAAM,IAAI,MAAM,KAAK,UAAUoB,CAAG,CAAC;AAAA,EACrC;AAAA,EAEA,MAAc,6BAA6BpB,GAA+BN,GAAoBE,GAAkB3K,GAAeqM,GAA0D;AACvL,UAAMC,IAAWvM,EAAaC,CAAK,GAC7BwL,IAAUf,EAAK,OAAO,CAAAS,MAAK,OAAO,KAAKA,EAAE,aAAa,EAAE,SAASoB,CAAQ,CAAC;AAEhF,QAAIpN,EAAcsM,CAAO;AACvB,YAAM,IAAI,MAAM,2BAA2B;AAG7C,UAAMC,wBAAe,IAAA;AACrB,QAAIc,IAAgB;AAEpB,eAAW5L,KAAO6K,GAAS;AACzB,YAAMI,IAAQ,MAAM,KAAK,eAAe,cAAcjL,EAAI,SAASX,CAAK;AACxE,iBAAW6L,KAAQD;AACjB,YAAI,SAAOC,EAAK,YAAY,IAAI,KAYhC;AAAA,cATAd,EAAU,KAAK;AAAA,YACb,UAAUc,EAAK;AAAA,YACf,SAASlL,EAAI;AAAA,YACb,UAAUkL,EAAK;AAAA,YACf,SAASA,EAAK;AAAA,YACd,aAAa,OAAOA,EAAK,YAAY;AAAA,UAAA,CACtC,GAEDU,IAAgBA,IAAgB,OAAOV,EAAK,YAAY,GACpD,CAACJ,EAAS,IAAI9K,EAAI,OAAO,GAAG;AAC9B,kBAAMoL,IAAQ,KAAK,WAAW,OAAOpL,EAAI,OAAO;AAChD,YAAA8K,EAAS,IAAI9K,EAAI,SAASoL,EAAM,UAAU;AAAA,UAC5C;AAEA,cAAIQ,IAAgBxO;AAClB,kBAAM,IAAI,MAAM,oEAAoE;AAEtF,cAAIgN,EAAU,YAAY,OAAO,SAAS,KAAK;AAC7C,kBAAM,IAAI,MAAM,iFAAiF;AAGnG,cAAIwB,KAAiBF;AACnB,mBAAOZ;AAET,cAAIc,IAAgBF;AAElB,mBAAAtB,EAAU,GAAGJ,GAAUU,EAAY,aAAarL,GAAOuM,IAAgBF,CAAc,GAC9EZ;AAAA;AAAA,IAGb;AAEA,UAAM,IAAI,MAAM,0BAA0B;AAAA,EAC5C;AAAA,EAEA,MAAc,oBAAoBpJ,GAAwB4I,GAA8C;AACtG,UAAMuB,IAAM,MAAM,KAAK,eAAe,YAAA;AACtC,WAAOnK,EAAG,qBAAqBmK,EAAI,MAAM,EAAE,KAAKvB,CAAQ,EAAE,MAAA;AAAA,EAC5D;AAAA,EAEO,qBAAqB5I,GAAiC;AAC3D,QAAI,CAACA;AACH,aAAO;AAET,UAAMoK,IAAM;AAAA,MACV,GAAGpK,EAAG,SAAA;AAAA,MACN,KAAKA,EAAG,SAAA;AAAA,IAAS;AAEnB,WAAO,KAAK,UAAUoK,GAAK,MAAM,CAAC;AAAA,EACpC;AACF;AC7XO,SAASC,GAAoBC,IAAgB,IAAY;AAC9D,SAAOC,GAAiBC,IAAUF,MAAS,KAAK,MAAM,GAAG;AAC3D;AAEO,SAASG,GAAgBhH,GAA2B;AACzD,SAAOiH,GAAiBjH,GAAU+G,EAAQ;AAC5C;AAEA,eAAeG,GAAUC,GAAkBC,GAAuC;AAChF,QAAMtI,IAAQ,YAAY,IAAA,GACpBjE,IAAM,MAAMwM,GAAcF,GAAUC,GAAM,EAAE,GAAG,GAAG,GAAG,OAAO,GAAG,GAAG,OAAO,IAAI;AACnF,iBAAQ,IAAI,YAAY,IAAA,IAAQtI,CAAK,GAC9BjE;AACT;AAEA,eAAsByM,GAAgBC,GAAgBJ,GAAmC;AACvF,QAAMC,IAAOpN,EAAY,gBAAgB,EAAE,GACrCwN,IAAKxN,EAAY,gBAAgB,EAAE,GACnC4E,IAAO5E,EAAY,aAAauN,CAAM,GAEtC1M,IAAM,MAAMqM,GAAUC,GAAUC,CAAI,GAEpCK,IAASC,GAAI7M,GAAK2M,CAAE,EAAE,QAAQ5I,CAAI,GAClC+I,IAAS3N,EAAY,OAAO,CAACoN,GAAMI,GAAIC,CAAM,CAAC;AACpD,SAAOzN,EAAY,eAAe2N,CAAM;AAC1C;AAEA,eAAeC,GAAgBC,GAAiBV,GAAmC;AACjF,QAAMQ,IAAS3N,EAAY,eAAe6N,CAAO,GAE3CT,IAAOO,EAAO,SAAS,GAAG,EAAE,GAC5BH,IAAKG,EAAO,SAAS,IAAI,EAAE,GAC3BF,IAASE,EAAO,SAAS,EAAE,GAE3B9M,IAAM,MAAMqM,GAAUC,GAAUC,CAAI,GAEpCxI,IAAO8I,GAAI7M,GAAK2M,CAAE,EAAE,QAAQC,CAAM;AACxC,SAAOzN,EAAY,aAAa4E,CAAI;AACtC;AAEA,eAAsBkJ,GAA2BD,GAAiBV,GAA2C;AAC3G,MAAI;AACF,QAAIU,GAAS;AACX,YAAME,IAAQ,MAAMH,GAAgBC,GAASV,CAAQ;AACrD,UAAIY,KAASf,GAAgBe,CAAK;AAChC,eAAOA;AAAA,IAEX;AACA,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;ACxDA,MAAMC,KAAkB;AAAA,EACtB,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AACP,GAIaC,KAAa,OAAO,KAAKD,EAAe;AAErD,eAAsBE,KAAiD;AACrE,QAAMC,IAAgBF,GAAW,KAAK,GAAG,GAEnC9I,IAAM,MAAM,MAAM,qGAAqGgJ,CAAa,EAAE;AAC5I,MAAI,CAAChJ,EAAI;AACP,UAAM,IAAI,MAAM,uBAAuB;AAIzC,UADa,MAAMA,EAAI,KAAA,GACX,YAAY,CAAA;AAC1B;AAEO,SAASiJ,GAAkB1M,GAA4B;AAC5D,SAAOsM,GAAgBtM,CAAQ,KAAKA;AACtC;AAEO,SAAS2M,KAA0C;AACxD,QAAMC,IAAgC,CAAA;AACtC,SAAAL,GAAW,QAAQ,CAAAvM,MAAY;AAC7B,IAAA4M,EAAO5M,CAAQ,IAAI,EAAE,OAAO,GAAG,QAAQ,EAAA;AAAA,EACzC,CAAC,GACM4M;AACT;ACpCO,SAASC,KAA2B;AACzC,SAAOC,EAAO,MAAA,EACX,IAAIC,EAAO,eAAe,EAAE,IAAIA,EAAO,OAAO,EAC9C,IAAIA,EAAO,eAAe,EAAE,IAAIA,EAAO,sBAAsB,EAAE,IAAIA,EAAO,OAAO,EACjF,IAAIA,EAAO,eAAe,EAAE,IAAIA,EAAO,iBAAiB;AAC7D;AAEO,SAASC,KAAmC;AACjD,QAAMC,IAAWJ,GAAA;AACjB,SAAOK,EAAK,gBAAgBD,EAAS,SAAA,CAAU;AACjD;AAEO,SAASE,GAAwBC,GAA2B;AACjE,SAAON,EAAO,MAAA,EAAQ,IAAIM,EAAO,UAAU;AAC7C;AAEO,SAASC,GAAuBD,GAA+B;AACpE,QAAME,IAAaH,GAAwBC,CAAM;AACjD,SAAOF,EAAK,gBAAgBI,EAAW,SAAA,CAAU;AACnD;AAEO,SAASC,GAAyBC,GAAiC;AACxE,SAAOA,EAAK,IAAI,CAAA7P,MAAOA,KAAO,KAAK8P,EAAa,SAAS9P,CAAG,IAAI+P,EAAW,WAAW/P,CAAG,EAAE,mBAAmB;AAChH;AAEO,SAASgQ,GAAqBP,GAAmBI,GAAoC;AAC1F,MAAIA,EAAK,WAAW;AAClB;AAGF,QAAMI,IAAeZ,GAAA,GACfa,IAAiBR,GAAuBD,CAAM,GAC9CU,IAAcP,GAAyBC,CAAI;AAEjD,SADgBtQ,EAAQ,mBAAmB0Q,GAAcC,GAAgBC,CAAW,EACrE,SAAA;AACjB;ACjBO,MAAMC,GAAe;AAAA,EAET;AAAA,EACA;AAAA,EAEA;AAAA,EACA;AAAA,EAET;AAAA,EAEA;AAAA,EAED,YAAY3L,GAAoB4L,GAAwB;AAC7D,SAAK,WAAW5L,GAChB,KAAK,aAAa4L,GAClB,KAAK,gCAAgB,IAAA,GACrB,KAAK,+BAAe,IAAA,GACpB,KAAK,gBAAgB;AAAA,EACvB;AAAA,EAEO,SAASrN,GAAuC;AACrD,SAAK,iBAAiBA;AAAA,EACxB;AAAA,EAEQ,OAAOC,GAA2B;AACxC,SAAK,iBAAiBA,CAAK;AAAA,EAC7B;AAAA,EAEO,WAAWqN,GAA4C;AAC5D,WAAO,KAAK,SAAS,IAAIA,CAAO;AAAA,EAClC;AAAA,EAEO,IAAIjN,GAAqBkN,GAAwBC,GAAgC;AACtF,IAAK,KAAK,UAAU,IAAInN,EAAQ,EAAE,KAChC,KAAK,UAAU,IAAIA,EAAQ,IAAI,oBAAI,KAAK;AAG1C,UAAMc,IAAYqM,EAAY,QAAQ,WAChCC,IAAkB,KAAK,UAAU,IAAIpN,EAAQ,EAAE;AAErD,SAAK,iBAAiBA,GAASkN,GAAUpM,CAAS,GAClDsM,EAAgB,IAAItM,GAAWoM,CAAQ,GACvC,KAAK,OAAO,EAAE,MAAM,iBAAiB,WAAWlN,EAAQ,IAAI,aAAAmN,GAAa;AAAA,EAC3E;AAAA,EAEO,OAAOtM,GAAmBC,GAAyB;AACxD,UAAMuM,IAAa,KAAK,UAAU,IAAIxM,CAAS;AAC/C,QAAIwM,GAAY;AACd,YAAMH,IAAWG,EAAW,IAAIvM,CAAS;AACzC,MAAIoM,MACFA,EAAS,WAAA,GACTG,EAAW,OAAOvM,CAAS,IAEzBuM,EAAW,SAAS,KACtB,KAAK,UAAU,OAAOxM,CAAS;AAAA,IAEnC;AACA,SAAK,OAAO,EAAE,MAAM,mBAAmB,WAAAA,GAAW,WAAAC,GAAW;AAAA,EAC/D;AAAA,EAEA,MAAa,OAAOwM,GAAkD;AACpE,eAAWtN,KAAWsN,EAAS,UAAU;AACvC,UAAItN,EAAQ,MAAM1E;AAChB;AAEF,YAAMiS,IAAiB,MAAM,KAAK,SAAS,mBAAmBvN,EAAQ,EAAE,GAClEwN,IAAkB,KAAK,UAAU,IAAIxN,EAAQ,EAAE,GAE/CyN,IAAiBF,EAAe,IAAI,OAAO3M,MAAY;AAC3D,YAAI4M,GAAiB,IAAI5M,EAAQ,SAAS;AACxC;AAGF,YAAIsM;AACJ,YAAI;AACF,UAAAA,IAAW,IAAIQ,GAAa9M,EAAQ,GAAG;AACvC,gBAAM+M,IAAUT,EAAS,eAAA;AACzB,gBAAMA,EAAS,QAAQ,GAAI;AAC3B,gBAAMU,IAAU,MAAMV,EAAS,WAAW,GAAI;AAC9C,gBAAMA,EAAS,YAAYlN,EAAQ,SAAS,GAAI;AAChD,gBAAM6N,IAAW,MAAMX,EAAS,qBAAA;AAChC,qBAAWY,KAAOD;AAChB,iBAAK,OAAO;AAAA,cACV,MAAM;AAAA,cACN,cAAc;AAAA,gBACZ,IAAI,OAAO,WAAA;AAAA,gBACX,WAAWC,EAAI;AAAA,gBACf,MAAM;AAAA,gBACN,OAAO;AAAA,gBACP,SAAS,qBAAqBF,EAAQ,IAAI,gDAAgD5N,EAAQ,IAAI;AAAA,gBACtG,QAAQ;AAAA,kBACN,MAAM;AAAA,kBACN,SAASA,EAAQ;AAAA,kBACjB,WAAW2N,EAAQ;AAAA,kBACnB,SAASG,EAAI;AAAA,gBAAA;AAAA,cACf;AAAA,YACF,CACD;AAEH,iBAAO,EAAE,SAAA9N,GAAkB,UAAAkN,GAAU,UAAU,EAAE,SAAAS,GAAS,SAAAC,IAAQ;AAAA,QACpE,SAAS9N,GAAO;AACd,kBAAQ,MAAM,4BAA4Bc,EAAQ,SAAS,IAAId,CAAK,GACpEoN,GAAU,WAAA,GACV,MAAM,KAAK,SAAS,cAActM,EAAQ,SAAS;AAAA,QACrD;AAAA,MACF,CAAC,GAEKmN,IAAS,MAAM,QAAQ,WAAWN,CAAc;AACtD,iBAAWO,KAAUD;AACnB,QAAIC,EAAO,WAAW,eAAeA,EAAO,SAC1C,KAAK,IAAIA,EAAO,MAAM,SAASA,EAAO,MAAM,UAAUA,EAAO,MAAM,QAAQ;AAAA,IAGjF;AAAA,EACF;AAAA,EAEO,QAAc;AACnB,QAAI;AACF,WAAK,gBAAgB;AACrB,iBAAW,CAACnN,GAAWoN,CAAQ,KAAK,KAAK,WAAW;AAClD,mBAAW,CAAA,EAAEf,CAAQ,KAAKe;AACxB,UAAAf,EAAS,WAAA;AAEX,QAAAe,EAAS,MAAA,GACT,KAAK,OAAO,EAAE,MAAM,oBAAoB,WAAApN,GAAW;AAAA,MACrD;AACA,WAAK,UAAU,MAAA;AAAA,IACjB,UAAA;AACE,WAAK,gBAAgB;AAAA,IACvB;AAAA,EACF;AAAA,EAEA,MAAa,OAAOA,GAAmBC,GAAkC;AACvE,UAAMuM,IAAa,KAAK,UAAU,IAAIxM,CAAS;AAC/C,QAAIwM,GAAY;AACd,YAAMH,IAAWG,EAAW,IAAIvM,CAAS;AACzC,MAAIoM,KACF,MAAMA,EAAS,cAAA;AAAA,IAEnB;AAAA,EACF;AAAA,EAEA,MAAa,cAAcrM,GAAmBC,GAAmBoN,GAAgC;AAC/F,UAAMb,IAAa,KAAK,UAAU,IAAIxM,CAAS;AAC/C,QAAIwM,GAAY;AACd,YAAMH,IAAWG,EAAW,IAAIvM,CAAS;AACzC,MAAIoM,KACF,MAAMA,EAAS,cAAcgB,CAAO;AAAA,IAExC;AAAA,EACF;AAAA,EAEQ,iBAAiBlO,GAAqBkN,GAAwBpM,GAAyB;AAC7F,IAAAoM,EAAS,gBAAgB,MAChB,KAAK,SAAS,cAAcpM,CAAS,CAC7C,GAEDoM,EAAS,QAAQ,MAAY;AAC3B,MAAI,KAAK,iBACP,KAAK,OAAOlN,EAAQ,IAAIc,CAAS;AAAA,IAErC,CAAC;AAED,UAAMqN,IAAgB,CAAInS,GAA0BiR,MAC3C,IAAI,QAAW,CAACtK,GAASC,MAAW;AACzC,WAAK,SAAS,IAAI5G,GAAM,EAAE,SAAA2G,GAAS,QAAAC,GAAQ,GAC3C,KAAK,OAAO,EAAE,MAAM,eAAe,SAAS,EAAE,MAAA5G,GAAM,WAAWgE,EAAQ,IAAI,WAAAc,GAAW,SAAAmM,EAAA,GAAW;AAAA,IACnG,CAAC;AAGH,IAAAC,EAAS,cAAc,CAAAkB,MACdD,EAAc5O,EAAmB,aAAa6O,CAAU,CAChE,GAEDlB,EAAS,WAAW,CAAAmB,MACXF,EAAc5O,EAAmB,UAAU8O,CAAW,CAC9D,GAEDnB,EAAS,kBAAkB,CAAAoB,MAClBH,EAAc5O,EAAmB,iBAAiB+O,CAAkB,CAC5E,GAEDpB,EAAS,kBAAkB,CAAAqB,MAClBJ,EAAc5O,EAAmB,iBAAiBgP,CAAkB,CAC5E,GAEDrB,EAAS,aAAa,MAAM;AAC1B,YAAM/J,IAAgB,EAAE,SAAS9D,EAAY,MAAM,MAAMC,EAAS,SAAS,OAAOU,EAAQ,GAAA;AAC1F,aAAO;AAAA,QACL,MAAMA,EAAQ;AAAA,QACd,SAASA,EAAQ;AAAA,QACjB,QAAQ,KAAK,WAAW,OAAOmD,CAAI,EAAE,UAAU,SAAA;AAAA,QAC/C,YAAY;AAAA,QACZ,SAASxH,EAAS,eAAe;AAAA,QACjC,cAAc;AAAA,UACZ,UAAU;AAAA,UACV,iBAAiB;AAAA,UACjB,aAAa;AAAA,UACb,iBAAiB;AAAA,QAAA;AAAA,MACnB;AAAA,IAEJ,CAAC;AAAA,EACH;AACF;AC5MO,MAAM6S,GAAuB;AAAA,EAEjB;AAAA,EACA;AAAA,EACA;AAAA,EAEV,YAAY1J,GAAgCkI,GAAwByB,GAA4B;AACrG,SAAK,iBAAiB3J,GACtB,KAAK,aAAakI,GAClB,KAAK,eAAeyB;AAAA,EACtB;AAAA,EAEA,MAAa,wBAAwBC,GAAaC,GAAqD;AACrG,UAAMC,IAAU,KAAK,cAAcF,GAAKC,CAAU;AAElD,iBAAM,KAAK,cAAcC,CAAO,GAChC,KAAK,eAAeA,CAAO,GAC3B,KAAK,WAAWA,CAAO,GACvB,MAAM,KAAK,sBAAsBA,CAAO,GAEjCA,EAAQ;AAAA,EACjB;AAAA,EAEQ,cAAcF,GAAaC,GAA4C;AAC7E,QAAI;AACF,aAAO;AAAA,QACL,SAASA,EAAW;AAAA,QACpB,YAAY,KAAK,WAAW,OAAOA,EAAW,OAAO,EAAE;AAAA,QACvD,WAAW;AAAA,UACT,IAAI,IAAI9F,EAAY6F,CAAG;AAAA,UACvB,MAAM,CAAA;AAAA,UACN,SAAS,CAAA;AAAA,QAAC;AAAA,QAEZ,8BAAc,IAAA;AAAA,QACd,+BAAe,IAAA;AAAA,QACf,oCAAoB,IAAA;AAAA,QACpB,kCAAkB,IAAA;AAAA,QAClB,oCAAoB,IAAA;AAAA,QACpB,qBAAqB;AAAA,MAAA;AAAA,IAEzB,QAAQ;AACN,YAAM,IAAI,MAAM,6BAA6B;AAAA,IAC/C;AAAA,EACF;AAAA,EAEA,MAAc,cAAcE,GAA4C;AACtE,UAAMC,IAAW,CAAA;AACjB,aAASC,IAAI,GAAGA,IAAIF,EAAQ,UAAU,GAAG,OAAO,QAAQE,KAAK;AAC3D,YAAMC,IAAI,KAAK,aAAaH,GAASE,CAAC;AACtC,MAAAD,EAAS,KAAKE,CAAC;AAAA,IACjB;AACA,UAAM,QAAQ,IAAIF,CAAQ;AAAA,EAC5B;AAAA,EAEA,MAAc,aAAaD,GAA6B3L,GAA8B;AACpF,UAAMqG,IAAQsF,EAAQ,UAAU,GAAG,OAAO3L,CAAK,GACzCoG,IAAO,MAAM,KAAK,eAAe,QAAQ/L,EAAY,YAAYgM,EAAM,QAAQ,CAAC;AACtF,QAAID,EAAK,UAAU;AACjB,YAAM,IAAI,MAAM,8BAA8B;AAIhD,QADAC,EAAM,SAAS,IAAI0F,GAAO3F,EAAK,QAAQA,EAAK,YAAY,GACpDC,EAAM,OAAO,WAAWsF,EAAQ,SAAS;AAC3C,YAAMrH,IAAU8B,EAAK,gBAAgB;AACrC,MAAAuF,EAAQ,SAAS,IAAI3L,GAAO;AAAA,QAC1B,SAAS2L,EAAQ;AAAA,QACjB,YAAYvF,EAAK,OAAO,SAAA;AAAA,QACxB,SAAA9B;AAAA,QACA,aAAa7J,EAAyB2L,EAAK,cAAc,KAAKA,EAAK,OAAO,SAAA;AAAA,MAAS,CACpF,GACDuF,EAAQ,eAAe,IAAIrH,CAAO,GAE9B+B,EAAM,UAAU,aAClBsF,EAAQ,aAAa,IAAI3L,CAAK;AAAA,IAElC;AAEA,IAAIqG,EAAM,UAAU,gBAAA,IAAoB,KACtCsF,EAAQ,aAAa,IAAI3L,CAAK;AAAA,EAElC;AAAA,EAEQ,eAAe2L,GAAmC;AACxD,aAASE,IAAI,GAAGA,IAAIF,EAAQ,UAAU,GAAG,QAAQ,QAAQE,KAAK;AAC5D,YAAMG,IAASL,EAAQ,UAAU,GAAG,QAAQE,CAAC,EAAE,SAAA;AAC/C,UAAIG,EAAO,YAAYL,EAAQ;AAC7B;AAGF,YAAMrH,IAAU0H,EAAO,UAAU1R,EAAa0R,EAAO,OAAO,IAAI,QAC1DnH,IAAW;AAAA,QACf,SAASmH,EAAO;AAAA,QAChB,YAAYA,EAAO,MAAM,SAAA;AAAA,QACzB,SAAA1H;AAAA,QACA,aAAa7J,EAAyBuR,EAAO,WAAW,KAAKA,EAAO,MAAM,SAAA;AAAA,MAAS;AAGrF,MAAAL,EAAQ,eAAe,IAAIrH,CAAO,GAClCqH,EAAQ,UAAU,IAAIE,GAAGhH,CAAQ;AAAA,IACnC;AAAA,EACF;AAAA,EAEQ,WAAW8G,GAAmC;AACpD,QAAIA,EAAQ,aAAa,QAAQ;AAC/B,YAAM,IAAI,MAAM,oBAAoB;AAGtC,eAAW3L,KAAS2L,EAAQ,cAAc;AACxC,YAAMtF,IAAQsF,EAAQ,UAAU,GAAG,OAAO3L,CAAK,GACzCiM,IAAY,KAAK,wBAAwB5F,CAAK;AAEpD,UAAIA,EAAM,UAAU,WAAW;AAC7B,QAAAsF,EAAQ,sBAAsB;AAC9B,cAAMO,IAAQC,GAAS,KAAKR,EAAQ,UAAU,IAAI3L,GAAOoM,GAAY,KAAKH,GAAWN,EAAQ,UAAU,EAAE,WAAA,GACnGtC,IAAaR,EAAO,QAAQ,IAAI8C,EAAQ,WAAW,UAAU,UAAU;AAC7E,QAAAtF,EAAM,YAAYgG,GAAc,sBAAsB,QAAWhD,GAAYR,EAAO,MAAA,EAAQ,IAAIqD,CAAK,CAAC;AAAA,MACxG,OAAO;AACL,cAAMI,IAAmBjG,EAAM,UAAU,gBAAA,GAEnCkG,IADclG,EAAM,UAAU,OAAOiG,CAAgB,EAC5B,IAAK,SAAS,EAAE,GACzCE,IAAcJ,GAAY,WAAWG,CAAU;AACrD,aAAK,yBAAyBZ,GAASa,CAAW;AAElD,cAAMN,IAAQC,GAAS,KAAKR,EAAQ,UAAU,IAAI3L,GAAOwM,GAAaP,GAAWN,EAAQ,UAAU,EAAE,WAAWY,CAAU;AAC1H,QAAAlG,EAAM,UAAU,aAAaiG,GAAkBzD,EAAO,QAAQ,IAAIqD,CAAK,CAAC;AAAA,MAC1E;AAAA,IACF;AAEA,QAAI,CAACP,EAAQ;AACX,YAAM,IAAI,MAAM,2DAA2D;AAAA,EAE/E;AAAA,EAEQ,wBAAwBtF,GAAsB;AACpD,QAAIA,EAAM,OAAQ,aAAa,uBAAA,GAA0B;AACvD,UAAIA,EAAM,UAAU,QAAA,KAAaA,EAAM,UAAU;AAC/C,eAAOwC,EAAO,QAAQ,IAAIC,EAAO,eAAe,EAAE,IAAIA,EAAO,iBAAiB;AAEhF,YAAM,IAAI,MAAM,4BAA4B;AAAA,IAC9C;AAEA,QAAIzC,EAAM,OAAQ,aAAa,oBAAA,GAAuB;AACpD,UAAI,CAACA,EAAM,UAAU;AACnB,cAAM,IAAI,MAAM,gCAAgC;AAGlD,YAAMsD,IAAetD,EAAM,OAAQ,aAAa,gBAAA,GAC1CoG,IAAcpG,EAAM,UAAU,OAAO,CAAC,EAAE;AAC9C,UAAIhM,EAAY,OAAOsP,GAAcV,EAAK,gBAAgBwD,CAAW,CAAC,KAAKpS,EAAY,OAAOsP,GAAcV,EAAK,aAAawD,CAAW,CAAC;AACxI,eAAO5D,EAAO,WAAW4D,CAAW;AAGtC,YAAM,IAAI,MAAM,gCAAgC;AAAA,IAClD;AAEA,UAAM,IAAI,MAAM,kCAAkC;AAAA,EACpD;AAAA,EAEQ,yBAAyBd,GAA6Ba,GAAgC;AAC5F,QAAI,CAAAb,EAAQ;AAIZ,UAAIa,EAAY,WAAWE,GAAkB;AAC3C,QAAAf,EAAQ,eAAe,IAAIa,EAAY,QAAQ,CAAC,CAAC,GACjDb,EAAQ,eAAe,IAAIa,EAAY,QAAQ,CAAC,CAAC,GACjD,KAAK,uBAAuBb,CAAO;AAAA,eAC1Ba,EAAY,WAAWE,GAAkB,QAAQ;AAC1D,cAAMC,IAAIH,EAAY,QAAQ,CAAC;AAC/B,iBAASX,IAAI,GAAGA,IAAIc,GAAGd;AACrB,UAAAF,EAAQ,eAAe,IAAIE,CAAC;AAE9B,aAAK,uBAAuBF,CAAO;AAAA,MACrC;AACE,QAAAA,EAAQ,sBAAsB;AAAA,EAElC;AAAA,EAEQ,uBAAuBA,GAAmC;AAChE,QAAI,CAAAA,EAAQ,qBAIZ;AAAA,iBAAWE,KAAKF,EAAQ,UAAU,KAAA;AAChC,YAAI,CAACA,EAAQ,eAAe,IAAIE,CAAC;AAC/B;AAGJ,MAAAF,EAAQ,sBAAsB;AAAA;AAAA,EAChC;AAAA,EAEA,MAAc,sBAAsBA,GAA4C;AAC9E,UAAMnH,IAAW,MAAM,KAAKmH,EAAQ,SAAS,QAAQ,GAC/CjH,IAAY,MAAM,KAAKiH,EAAQ,UAAU,QAAQ,GAEjDC,IAAW,CAAA;AACjB,eAAWtH,KAAWqH,EAAQ,gBAAgB;AAC5C,YAAMG,IAAI,KAAK,qBAAqBH,GAASrH,GAASE,GAAUE,CAAS;AACzE,MAAAkH,EAAS,KAAKE,CAAC;AAAA,IACjB;AACA,UAAM,QAAQ,IAAIF,CAAQ;AAAA,EAC5B;AAAA,EAEA,MAAc,qBAAqBD,GAA6BrH,GAAiBE,GAA2BE,GAA2C;AACrJ,UAAMkI,IAAapI,EAChB,OAAO,CAACqI,GAAKxI,MAAMA,EAAE,YAAYC,IAAUuI,IAAM,OAAOxI,EAAE,WAAW,IAAIwI,GAAK,EAAE,GAE7EC,IAAiBpI,EACpB,OAAO,CAACmI,GAAKxI,MAAMA,EAAE,YAAYC,IAAUuI,IAAM,OAAOxI,EAAE,WAAW,IAAIwI,GAAK,EAAE;AAEnF,QAAID,IAAa,MAAME,IAAiB,IAAI;AAC1C,YAAMjI,IAA4B,EAAE,QAAQiI,IAAiBF,EAAA;AAC7D,MAAItI,MAAY,WACdO,EAAS,QAAQ,MAAM,KAAK,aAAa,aAAaP,CAAO,IAG3DO,EAAS,SAAS,KACpB8G,EAAQ,UAAU,QAAQ,KAAK9G,CAAQ,IAC9BA,EAAS,SAAS,MAC3B8G,EAAQ,UAAU,KAAK,KAAK9G,CAAQ;AAAA,IAExC;AAAA,EACF;AACF;AC7OA,MAAMkI,KAAmB,QACnBC,KAAsB;AAErB,MAAMC,GAAuB;AAAA,EAEjB;AAAA,EACA;AAAA,EAEV,YAAYpL,GAAgCkI,GAAwB;AACzE,SAAK,iBAAiBlI,GACtB,KAAK,aAAakI;AAAA,EACpB;AAAA,EAEA,MAAa,oBAAoBhR,GAAmBmU,GAAqC;AACvF,QAAIlN,IAAQ,GAAGmN,IAAO,IAAOC,IAAY;AAEzC,OAAG;AACD,MAAAD,IAAO;AACP,eAAStB,IAAIuB,GAAWvB,IAAIuB,IAAU,IAAIvB,KAAK;AAC7C,cAAMrL,IAAU,EAAE,SAASzH,GAAM,MAAMmU,GAAU,OAAOrB,EAAA,GAClDwB,IAAQ,KAAK,WAAW,OAAO7M,CAAO,EAAE,WAAW,UAAA,EAAY,SAAA;AAErE,QADe,MAAM,KAAK,eAAe,cAAc6M,CAAK,MAE1DrN,IAAQ6L,GACRsB,IAAO;AAAA,MAEX;AACA,MAAAC,KAAa;AAAA,IACf,SAAS,CAACD;AAEV,WAAOnN;AAAA,EACT;AAAA,EAEA,MAAa,eAAesN,GAAqD;AAC/E,UAAMC,IAAyC,CAAA;AAC/C,eAAWzU,KAAWwU,GAAW;AAC/B,YAAMxB,IAAI,KAAK,sBAAsBhT,CAAO;AAC5C,MAAAyU,EAAe,KAAKzB,CAAC;AAAA,IACvB;AAEA,UAAMtM,IAAM,MAAM,QAAQ,IAAI+N,CAAc,GACtCC,wBAAa,IAAA;AAEnB,WAAAhO,EAAI,QAAQ,CAAAiO,MAAO;AACjB,MAAAA,EAAI,QAAQ,CAAAhC,MAAO;AACjB,cAAMzN,IAAQ,KAAK,kBAAkByN,CAAG;AACxC,QAAIzN,KACFwP,EAAO,IAAIxP,EAAM,SAASA,CAAK;AAAA,MAEnC,CAAC;AAAA,IACH,CAAC,GAEMwP;AAAA,EACT;AAAA,EAEA,MAAc,sBAAsB1U,GAAuC;AACzE,UAAM0U,wBAAa,IAAA,GAEbE,IAAU,MAAM,KAAK,eAAe,uBAAuB5U,GAASiU,EAAgB;AAC1F,eAAWlJ,KAAa6J,GAAS;AAE/B,YAAMC,KADK,MAAM,KAAK,eAAe,eAAe9J,EAAU,OAAO,GACpD,KAAK,OAAO,CAAAqC,MAAOA,EAAI,aAAa,IAAI,WAAW8G,EAAkB,CAAC;AACvF,iBAAWY,KAAQD;AACjB,QAAAH,EAAO,IAAII,EAAK,aAAa,GAAG;AAAA,IAEpC;AAEA,WAAOJ;AAAA,EACT;AAAA,EAEQ,kBAAkB/B,GAAmC;AAC3D,UAAMoC,IAAiBhF,EAAO,QAAQ4C,CAAG,GACnCqC,IAAM,IAAIC,KAAe,kBAAkBF,EAAe,SAAA,CAAU,EAAE,SAAA,GACtEG,IAAgB,IAAI/U,EAAQ6U,CAAG,EAAE,SAAA,GAEjCvE,IAAOsE,EAAe,eAAA,GAEtBI,IAAQxE,EAAW,oBAAoBF,EAAK,OAAO,CAAC,EAAE,GAAI,EAAE,SAAA,GAC5DvJ,IAAQwJ,EAAa,aAAaD,EAAK,OAAO,CAAC,EAAE,SAAS,IAChDC,EAAa,WAAWD,EAAK,OAAO,CAAC,EAAE,SAAS,IAChDE,EAAW,oBAAoBF,EAAK,OAAO,CAAC,EAAE,GAAI,EAAE,SAAA,GAE9DM,IAAc,CAACoE,GAAOjO,CAAK,GAC3B9E,IAAM,KAAK,WAAW,OAAO,EAAE,SAASkB,EAAY,OAAO,MAAMC,EAAS,SAAS,OAAA2D,EAAA,CAAc,GACjGkO,IAAkBxE,GAAqBxO,EAAI,WAAW2O,CAAW;AAEvE,WAAImE,KAAiBE,IACnB,SAGoB;AAAA,MACpB,SAASF;AAAA,MACT,OAAAC;AAAA,MACA,KAAKjO;AAAA,MACL,YAAY;AAAA,MACZ,SAAS,EAAE,WAAW,KAAK,aAAa,IAAA;AAAA,MACxC,eAAe,CAAA;AAAA,MACf,QAAQ;AAAA,MACR,MAAM5D,EAAY;AAAA,IAAA;AAAA,EAItB;AACF;AC1EO,MAAM+R,EAAc;AAAA,EAsBlB,YACYpE,GACA1L,GACAF,GACA0D,GACA2J,GACA4C,GACAC,GACjB;AAPiB,SAAA,aAAAtE,GACA,KAAA,UAAA1L,GACA,KAAA,WAAAF,GACA,KAAA,iBAAA0D,GACA,KAAA,eAAA2J,GACA,KAAA,qBAAA4C,GACA,KAAA,iBAAAC,GAEjB,KAAK,mBAAmB,IAAIpB,GAAuB,KAAK,gBAAgB,KAAK,UAAU,GACvF,KAAK,+BAAe,IAAA,GACpB,KAAK,0CAA0B,IAAA,GAC/B,KAAK,mBAAmB,CAAA,GACxB,KAAK,kBAAkB,CAAA,GACvB,KAAK,6BAAa,IAAA,GAClB,KAAK,qCAAqB,IAAA,GAC1B,KAAK,uCAAuB,IAAA;AAAA,EAC9B;AAAA,EArCA,OAAwB,YAAY;AAAA,EACpC,OAAwB,cAAc;AAAA,EAE9B;AAAA,EAED;AAAA,EACA;AAAA,EAEA;AAAA,EACA;AAAA,EAEA;AAAA,EAEC;AAAA,EACA;AAAA,EAEA;AAAA,EAES;AAAA,EAqBV,SAASvQ,GAAsC;AACpD,SAAK,iBAAiBA;AAAA,EACxB;AAAA,EAEQ,OAAOC,GAA0B;AACvC,SAAK,iBAAiBA,CAAK;AAAA,EAC7B;AAAA,EAEQ,kBAAmC;AACzC,WAAO,CAAC,GAAG,KAAK,kBAAkB,GAAG,KAAK,iBAAiB,GAAG,KAAK,SAAS,UAAU,GAAG,KAAK,OAAO,QAAQ;AAAA,EAC/G;AAAA,EAEO,mBAAiC;AACtC,WAAO,CAAC,GAAG,KAAK,kBAAkB,GAAG,KAAK,eAAe;AAAA,EAC3D;AAAA,EAEO,oBAA4B;AACjC,WAAO,KAAK,iBAAiB,KAAK,OAAQ,CAAC2R,EAAK,IAAI,EAAG;AAAA,EACzD;AAAA,EAEO,iBAAiB1Q,IAAYvF,GAAwB;AAC1D,WAAIuF,KAAavF,IACR,KAAK,SAAS,IAAIuF,CAAS,EAAG,UAEhC,KAAK,gBAAgB,KAAK,OAAQ,CAAC0Q,EAAK,IAAI,EAAG;AAAA,EACxD;AAAA,EAEO,mBAAmB1Q,IAAYvF,GAA8B;AAClE,QAAIuF,KAAavF,GAAgB;AAC/B,YAAM0E,IAAU,KAAK,SAAS,IAAIa,CAAS;AAC3C,aAAO,CAAC;AAAA,QACN,SAASb,EAAQ;AAAA,QACjB,SAASgD,EAAgB3D,EAAY,MAAM,GAAGW,EAAQ,EAAE;AAAA,QACxD,SAASA,EAAQ;AAAA,QACjB,eAAeA,EAAQ;AAAA,MAAA,CACxB;AAAA,IACH;AAEA,WAAO,KAAK,mBAAmB,OAAO,OAAQuR,EAAK,IAAI,EAAE,IAAI,CAAAA,OAAS;AAAA,MACpE,SAASA,EAAK;AAAA,MACd,SAASvO,EAAgB3D,EAAY,MAAMkS,EAAK,OAAOA,EAAK,GAAG;AAAA,MAC/D,SAASA,EAAK;AAAA,MACd,eAAeA,EAAK;AAAA,IAAA,EACpB;AAAA,EACJ;AAAA,EAEA,MAAa,cAAczS,GAAsC;AAC/D,UAAM,KAAK,QAAQ,kBAAkBA,CAAM,GAC3C,MAAM,KAAK,eAAe,WAAW,EAAI,GACzC,MAAM,KAAK,YAAA,GACX,MAAM,KAAK,mBAAmB,KAAK,gBAAA,CAAiB;AAAA,EACtD;AAAA,EAEA,MAAa,cAA6B;AACxC,UAAM,KAAK,eAAe,QAAA,GAC1B,MAAM,KAAK,eAAe,iBAAiB,CAAAkL,MAAO,KAAK,OAAO,EAAE,MAAM,WAAW,KAAAA,EAAA,CAAK,CAAC;AAAA,EACzF;AAAA,EAEA,MAAa,aAA4B;AACvC,UAAM,KAAK,YAAA,GAEK,MAAM,KAAK,SAAS,eAAA,IAElC,MAAM,KAAK,WAAA,IAEX,MAAM,KAAK,eAAA;AAAA,EAEf;AAAA,EAEA,MAAc,iBAAgC;AAC5C,SAAK,OAAO,EAAE,MAAM,mBAAmB,SAAS,IAAM;AAEtD,UAAMwH,IAAgB,KAAK,iBAAiB,oBAAoBnS,EAAY,MAAMC,EAAS,OAAO,GAC5FmS,IAAgB,KAAK,iBAAiB,oBAAoBpS,EAAY,MAAMC,EAAS,MAAM,GAC3FoS,IAAkB,KAAK,iBAAiB,oBAAoBrS,EAAY,MAAMC,EAAS,OAAO,GAE9F,CAACqS,GAAQC,GAAQC,CAAS,IAAI,MAAM,QAAQ,IAAI,CAACL,GAAeC,GAAeC,CAAe,CAAC;AAErG,SAAK,mBAAmB,KAAK,gBAAgBpS,EAAS,SAAS,GAAGqS,IAASP,EAAc,SAAS,GAClG,KAAK,kBAAkB,KAAK,gBAAgB9R,EAAS,QAAQ,GAAGsS,IAASR,EAAc,SAAS,GAChG,KAAK,WAAW,KAAK,eAAe,GAAGS,IAAY,CAAC,GACpD,KAAK,SAAS,QAAQ,CAAAC,MAAS,KAAK,oBAAoB,IAAIA,EAAM,SAASA,EAAM,EAAE,CAAC,GAEpF,MAAM,KAAK,cAAc,KAAK,gBAAgB,GAC9C,MAAM,KAAK,cAAc,KAAK,eAAe,GAC7C,MAAM,KAAK,aAAa,KAAK,QAAQ,GAErC,KAAK,UAAA,GAEL,MAAM,KAAK,YAAA,GAEX,KAAK,OAAO,EAAE,MAAM,mBAAmB,SAAS,IAAO,GACvD,KAAK,OAAO,EAAE,MAAM,eAAe,SAAS,IAAO,GAEnD,MAAM,KAAK,aAAA;AAAA,EACb;AAAA,EAEA,MAAc,aAA4B;AACxC,SAAK,mBAAmB,MAAM,KAAK,SAAS,oBAAA,GAC5C,KAAK,kBAAkB,MAAM,KAAK,SAAS,mBAAA;AAE3C,UAAMC,IAAO,MAAM,KAAK,SAAS,YAAA;AACjC,SAAK,WAAW,IAAI,IAAIA,EAAK,IAAI,CAAArR,MAAK,CAACA,EAAE,IAAIA,CAAC,CAAC,CAAC,GAChD,KAAK,sBAAsB,IAAI,IAAIqR,EAAK,IAAI,CAAArR,MAAK,CAACA,EAAE,SAASA,EAAE,EAAE,CAAC,CAAC;AAEnE,UAAM+P,IAAS,MAAM,KAAK,SAAS,UAAA;AACnC,SAAK,SAAS,IAAI,IAAIA,EAAO,IAAI,CAAAzP,MAAK,CAACA,EAAE,SAASA,CAAC,CAAC,CAAC,GAErD,KAAK,UAAA,GAEL,KAAK,OAAO,EAAE,MAAM,eAAe,SAAS,IAAO,GAEnD,MAAM,KAAK,cAAA;AAAA,EACb;AAAA,EAEA,MAAc,cAA6B;AACzC,UAAM,KAAK,mBAAmB,KAAK,gBAAA,GAAmB,EAAI;AAE1D,UAAMgR,IAAsC,CAAA;AAC5C,IAAAA,EAAmB,KAAK,KAAK,aAAa,mBAAmB1W,GAAgB2C,EAAiB,KAAK,iBAAA,EAAmB,IAAI,CAAAyC,MAAKA,EAAE,aAAa,CAAC,CAAC,CAAC;AACjJ,eAAWV,KAAW,KAAK,SAAS,OAAA;AAClC,MAAAgS,EAAmB,KAAK,KAAK,aAAa,mBAAmBhS,EAAQ,IAAIA,EAAQ,aAAa,CAAC;AAGjG,UAAM,QAAQ,IAAIgS,CAAkB;AAAA,EACtC;AAAA,EAEA,MAAa,gBAA+B;AAC1C,UAAM,QAAQ,IAAI;AAAA,MAChB,KAAK,eAAe,OAAO,KAAK,QAAQ;AAAA,MACxC,KAAK,mBAAmB,KAAK,gBAAA,CAAiB;AAAA,IAAA,CAC/C;AAAA,EACH;AAAA,EAEQ,YAAkB;AACxB,UAAMC,IAAmB,KAAK,iBAAA;AAE9B,SAAK,OAAO;AAAA,MACV,MAAM;AAAA,MACN,SAAS;AAAA,QACP,IAAI3W;AAAA,QACJ,MAAM;AAAA,QACN,SAAS,KAAK,kBAAA;AAAA,QACd,SAASsC,GAAWqU,EAAgB,IAAI,CAAAvR,MAAKA,EAAE,OAAO,CAAC;AAAA,QACvD,eAAezC,EAAiBgU,EAAgB,IAAI,CAAAvR,MAAKA,EAAE,aAAa,CAAC;AAAA,QACzE,QAAQ,CAAA;AAAA,QACR,UAAU,CAAA;AAAA,MAAC;AAAA,IACb,CACD;AAED,eAAWV,KAAW,KAAK,SAAS,OAAA;AAClC,WAAK,OAAO;AAAA,QACV,MAAM;AAAA,QACN,SAAS;AAAA,UACP,IAAIA,EAAQ;AAAA,UACZ,MAAMA,EAAQ;AAAA,UACd,SAASA,EAAQ;AAAA,UACjB,SAASA,EAAQ;AAAA,UACjB,eAAeA,EAAQ;AAAA,UACvB,QAAQ,CAAA;AAAA,UACR,UAAU,CAAA;AAAA,QAAC;AAAA,MACb,CACD;AAGH,eAAWiB,KAAS,KAAK,OAAO,OAAA;AAC9B,WAAK,OAAO;AAAA,QACV,MAAM;AAAA,QACN,OAAO;AAAA,UACL,SAASA,EAAM;AAAA,UACf,SAASA,EAAM;AAAA,UACf,OAAOA,EAAM;AAAA,UACb,OAAOA,EAAM;AAAA,QAAA;AAAA,MACf,CACD;AAAA,EAEL;AAAA,EAEQ,gBAAgBiR,GAAiBC,GAAoBC,GAA6B;AACxF,UAAMC,IAA6B,CAAA;AACnC,aAAS,IAAIF,GAAY,IAAIA,IAAaC,GAAO,KAAK;AACpD,YAAMjP,IAAOH,EAAgB3D,EAAY,MAAM6S,GAAO,CAAC,GAGjDI,IAAyB;AAAA,QAC7B,SAHc,KAAK,WAAW,OAAOnP,CAAI,EAAE,WAAW,UAAA,EAAY,SAAA;AAAA,QAIlE,OAAA+O;AAAA,QACA,KAAK;AAAA,QACL,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,YAAY;AAAA,QACZ,SAAS,EAAE,WAAW,KAAK,aAAa,IAAA;AAAA,QACxC,eAAe,CAAA;AAAA,QACf,MAAM7S,EAAY;AAAA,MAAA;AAGpB,MAAAgT,EAAa,KAAKC,CAAU;AAAA,IAC9B;AAEA,WAAOD;AAAA,EACT;AAAA,EAEQ,eAAeF,GAAoBC,GAAwC;AACjF,UAAMG,wBAAkB,IAAA;AACxB,aAASzD,IAAIqD,GAAYrD,IAAIqD,IAAaC,GAAOtD,KAAK;AACpD,YAAM3L,IAAOH,EAAgB3D,EAAY,MAAM,GAAGyP,CAAC,GAC7C/S,IAAU,KAAK,WAAW,OAAOoH,CAAI,EAAE,WAAW,UAAA,EAAY,SAAA,GAE9DnD,IAAsB;AAAA,QAC1B,IAAI8O;AAAA,QACJ,MAAM,WAAWA,IAAI,CAAC;AAAA,QACtB,SAAA/S;AAAA,QACA,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,YAAY;AAAA,QACZ,SAAS,EAAE,WAAW,KAAK,aAAa,IAAA;AAAA,QACxC,eAAe,CAAA;AAAA,QACf,MAAMsD,EAAY;AAAA,MAAA;AAGpB,MAAAkT,EAAY,IAAIvS,EAAQ,IAAIA,CAAO;AAAA,IACrC;AAEA,WAAOuS;AAAA,EACT;AAAA,EAEA,MAAc,cAAchC,GAAwC;AAClE,eAAWgB,KAAQhB;AACjB,YAAM,KAAK,SAAS,YAAYgB,CAAI;AAAA,EAExC;AAAA,EAEA,MAAc,aAAajE,GAAkD;AAC3E,eAAWkF,KAAOlF,EAAS;AACzB,YAAM,KAAK,SAAS,YAAYkF,CAAG;AAAA,EAEvC;AAAA,EAEA,MAAc,mBAAmBjC,GAA4BkC,IAAS,IAAsB;AAC1F,UAAMC,IAAuBnC,EAAU,IAAI,OAAMgB,MAAQ;AACvD,YAAMvD,IAAS,MAAM,KAAK,eAAe,iBAAiBuD,EAAK,SAAS,KAAK,gBAAgB;AAC7F,aAAO,EAAE,MAAAA,GAAM,QAAAvD,EAAA;AAAA,IACjB,CAAC,GAEK2E,IAAgC,CAAA,GAChCC,IAAsB,MAAM,QAAQ,IAAIF,CAAoB;AAElE,eAAW,EAAE,MAAAnB,GAAM,QAAAvD,EAAA,KAAY4E;AAC7B,UAAI5E,KAAU,OAAOA,KAAW,YAAYuD,EAAK,cAAcvD,GAAQ;AACrE,YAAIyE,GAAQ;AACV,gBAAM1D,IAAI,IAAI,QAAc,CAACpM,MAAY;AACvC,iBAAK,iBAAiB,IAAI4O,EAAK,SAAS5O,CAAO;AAAA,UACjD,CAAC;AACD,UAAAgQ,EAAa,KAAK5D,CAAC;AAAA,QACrB;AACA,aAAK,eAAe,EAAC,SAASwC,GAAM,QAAAvD,GAAO;AAAA,MAC7C;AAGF,UAAM,QAAQ,IAAI2E,CAAY;AAAA,EAChC;AAAA,EAEQ,mBAAmB,CAACzQ,MAAwB;AAClD,QAAI,CAAC,MAAM,QAAQA,CAAI,KAAKA,EAAK,SAAS;AACxC;AAGF,UAAM,CAACnG,GAASF,CAAI,IAAIqG,GAElB2Q,IADe,KAAK,gBAAA,EACG,KAAK,CAAAnS,MAAKA,EAAE,YAAY3E,CAAO;AAE5D,IAAI8W,KAAWA,EAAQ,eAAehX,KACpC,KAAK,eAAe,EAAC,SAASgX,GAAS,QAAQhX,GAAK;AAAA,EAExD;AAAA,EAEQ,eAAeiX,GAA8B;AACnD,SAAK,eAAe,IAAIA,EAAW,QAAQ,SAASA,CAAU,GAE9D,aAAa,KAAK,WAAW,GAC7B,KAAK,cAAc,WAAW,MAAM;AAClC,WAAK,sBAAA;AAAA,IACP,GAAG1B,EAAc,WAAW;AAAA,EAC9B;AAAA,EAEA,MAAc,wBAAuC;AACnD,QAAI,KAAK,eAAe,SAAS;AAIjC,UAAI;AACF,aAAK,OAAO,EAAE,MAAM,eAAe,SAAS,IAAM,GAClD,QAAQ,IAAI,cAAc,KAAK,eAAe,IAAI,qBAAqB;AAEvE,cAAM2B,IAAU,MAAM,KAAK,KAAK,cAAc;AAC9C,aAAK,eAAe,MAAA;AAEpB,cAAMC,IAAqD,CAAA,GACrDC,IAAmD,CAAA,GACnDC,IAAmD,CAAA;AACzD,mBAAW,CAAA,EAAGC,CAAM,KAAKJ;AACvB,cAAI,KAAK,iBAAiBI,EAAO,OAAO,GAAG;AACzC,kBAAMpE,IAAI,KAAK,sBAAsBoE,EAAO,SAASA,EAAO,MAAM;AAClE,YAAAH,EAAwB,KAAKjE,CAAC;AAAA,UAChC,WAAW,KAAK,eAAeoE,EAAO,OAAO,GAAG;AAC9C,kBAAMpE,IAAI,KAAK,oBAAoBoE,EAAO,SAASA,EAAO,MAAM;AAChE,YAAAF,EAAsB,KAAKlE,CAAC;AAAA,UAC9B,OAAO;AACL,kBAAMA,IAAI,KAAK,sBAAsBoE,EAAO,SAASA,EAAO,MAAM;AAClE,YAAAD,EAAsB,KAAKnE,CAAC;AAAA,UAC9B;AAGF,cAAMqE,IAAc,MAAM,QAAQ,IAAIJ,CAAuB;AAC7D,cAAM,QAAQ,IAAIC,CAAqB;AACvC,cAAMI,IAAY,MAAM,QAAQ,IAAIH,CAAqB;AAEzD,YAAI,KAAK,iBAAiB,OAAO;AAC/B,qBAAW,CAACnX,CAAQ,KAAKgX,GAAS;AAChC,kBAAMO,IAAW,KAAK,iBAAiB,IAAIvX,CAAO;AAClD,YAAIuX,MACFA,EAAA,GACA,KAAK,iBAAiB,OAAOvX,CAAO;AAAA,UAExC;AAGF,cAAM,QAAQ,IAAI,CAAC,KAAK,wBAAwBsX,CAAS,GAAG,KAAK,yBAAyBD,CAAW,CAAC,CAAC;AAAA,MACzG,SAAS,GAAG;AACV,gBAAQ,MAAM,qCAAqC,CAAC;AAAA,MACtD,UAAA;AACE,aAAK,OAAO,EAAE,MAAM,eAAe,SAAS,IAAO;AAAA,MACrD;AAAA,EACF;AAAA,EAEA,MAAc,wBAAwBzC,GAA0C;AAC9E,QAAIA,EAAQ,WAAW;AACrB;AAGF,UAAM4C,wBAAmB,IAAA;AACzB,eAAW,EAAE,KAAAC,EAAA,KAAS7C;AACpB,iBAAW9Q,KAAM2T;AACf,QAAAD,EAAa,IAAI1T,EAAG,SAASA,CAAE;AAInC,UAAM,KAAK,cAAcP,EAAS,OAAO,GACzC,MAAM,KAAK,cAAcA,EAAS,MAAM;AAExC,UAAM2S,IAAmB,KAAK,iBAAA,GACxBwB,IAAgB7V,GAAWqU,EAAgB,IAAI,CAAAvR,MAAKA,EAAE,OAAO,CAAC,GAC9DgT,IAAsBzV,EAAiBgU,EAAgB,IAAI,CAAAvR,MAAKA,EAAE,aAAa,CAAC;AAEtF,SAAK,OAAO,EAAE,MAAM,2BAA2B,WAAWpF,GAAgB,SAASmY,GAAe,eAAeC,EAAA,CAAqB,GACtI,KAAK,OAAO,EAAE,MAAM,wBAAwB,SAAS,KAAK,kBAAA,GAAqB;AAE/E,UAAMC,IAAa,KAAK,aAAa,SAASrY,GAAgBoY,CAAmB;AACjF,eAAW7T,KAAM0T,EAAa;AAC5B,YAAM,KAAK,mBAAmB,2BAA2BjY,GAAgBuE,EAAG,SAASoS,EAAgB,IAAI,CAAAvR,MAAKA,EAAE,OAAO,CAAC;AAE1H,UAAMiT;AAAA,EACR;AAAA,EAEA,MAAc,yBAAyBhD,GAA0C;AAC/E,QAAIA,EAAQ,WAAW;AAIvB,iBAAW,EAAE,SAAA5U,GAAS,KAAAyX,EAAA,KAAS7C,GAAS;AACtC,cAAM3Q,IAAUjE;AAEhB,aAAK,OAAO,EAAE,MAAM,2BAA2B,WAAWiE,EAAQ,IAAI,SAASA,EAAQ,SAAS,eAAeA,EAAQ,eAAe;AAEtI,cAAM2T,IAAa,KAAK,aAAa,SAAS3T,EAAQ,IAAIA,EAAQ,aAAa;AAC/E,mBAAWH,KAAM2T;AACf,gBAAM,KAAK,mBAAmB,2BAA2BxT,EAAQ,IAAIH,EAAG,SAAS,CAACG,EAAQ,OAAO,CAAC;AAEpG,cAAM2T;AAAA,MACR;AAAA,EACF;AAAA,EAEA,MAAc,sBAAsBd,GAAqBhX,GAAuC;AAC9F,IAAAgX,EAAQ,aAAahX,GACrBgX,EAAQ,UAAU,MAAM,KAAK,eAAe,WAAWA,EAAQ,OAAO,GACtEA,EAAQ,gBAAgB,MAAM,KAAK,eAAe,iBAAiBA,EAAQ,OAAO;AAElF,UAAMlC,IAAU,MAAM,KAAK,mBAAmB,yBAAyBkC,EAAQ,SAASA,EAAQ,MAAM;AACtG,WAAAA,EAAQ,SAASlC,EAAQ,YACpBkC,EAAQ,SACXA,EAAQ,OAAOlC,EAAQ,IAAI,SAAS,IAGtC,MAAM,KAAK,SAAS,YAAYkC,CAAO,GAEhC,EAAE,SAASA,GAAS,KAAKlC,EAAQ,IAAA;AAAA,EAC1C;AAAA,EAEA,MAAc,sBAAsB3Q,GAAqBnE,GAAuC;AAC9F,IAAAmE,EAAQ,aAAanE,GACrBmE,EAAQ,UAAU,MAAM,KAAK,eAAe,WAAWA,EAAQ,OAAO,GACtEA,EAAQ,gBAAgB,MAAM,KAAK,eAAe,iBAAiBA,EAAQ,OAAO;AAElF,UAAM2Q,IAAU,MAAM,KAAK,mBAAmB,yBAAyB3Q,EAAQ,SAASA,EAAQ,MAAM;AACtG,WAAAA,EAAQ,SAAS2Q,EAAQ,YAEzB,MAAM,KAAK,SAAS,YAAY3Q,CAAO,GAEhC,EAAE,SAASA,GAAS,KAAK2Q,EAAQ,IAAA;AAAA,EAC1C;AAAA,EAEA,MAAc,oBAAoB1P,GAAiBpF,GAAuC;AACxF,IAAAoF,EAAM,aAAapF,GACnBoF,EAAM,UAAU,MAAM,KAAK,eAAe,WAAWA,EAAM,OAAO;AAElE,UAAM0P,IAAU,MAAM,KAAK,mBAAmB,yBAAyB1P,EAAM,SAASA,EAAM,MAAM;AAClG,WAAAA,EAAM,SAAS0P,EAAQ,YAEvB,MAAM,KAAK,SAAS,UAAU1P,CAAK,GACnC,KAAK,OAAO,EAAE,MAAM,yBAAyB,SAASA,EAAM,SAAS,SAASA,EAAM,QAAA,CAAS,GAEtF,EAAE,SAASA,GAAO,KAAK0P,EAAQ,IAAA;AAAA,EACxC;AAAA,EAEA,MAAc,cAAcR,GAAmC;AAC7D,UAAMI,IAAYJ,MAAa7Q,EAAS,UACpC,KAAK,mBACL,KAAK,iBAEHsU,IAAYzD,MAAa7Q,EAAS,UAAU,YAAY,UACxDuU,IAAStD,EAAU,OAAO,OAAK,CAAC7P,EAAE,IAAI,EAAE;AAE9C,QAAImT,IAASzC,EAAc,WAAW;AACpC,YAAM0C,IAAS1C,EAAc,YAAYyC,GACnCE,IAAYxD,EAAUA,EAAU,SAAS,CAAC,EAAE;AAElD,cAAQ,IAAI,YAAYuD,CAAM,SAASF,CAAS,eAAe;AAE/D,YAAMvB,IAAe,KAAK,gBAAgBlC,GAAU4D,IAAY,GAAGD,CAAM;AAEzE,MAAI3D,MAAa7Q,EAAS,UACxB,KAAK,iBAAiB,KAAK,GAAG+S,CAAY,IAE1C,KAAK,gBAAgB,KAAK,GAAGA,CAAY,GAG3C,MAAM,KAAK,cAAcA,CAAY,GACrC,MAAM,KAAK,mBAAmBA,CAAY;AAAA,IAC5C;AAAA,EACF;AAAA,EAEA,MAAa,cAAchS,GAAYM,GAA6B;AAClE,UAAMwC,IAAOH,EAAgB3D,EAAY,MAAM,GAAGgB,CAAE,GAC9CtE,IAAU,KAAK,WAAW,OAAOoH,CAAI,EAAE,WAAW,UAAA,EAAY,SAAA,GAE9DnD,IAAsB;AAAA,MAC1B,IAAAK;AAAA,MACA,MAAAM;AAAA,MACA,SAAA5E;AAAA,MACA,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,SAAS,EAAE,WAAW,KAAK,aAAa,IAAA;AAAA,MACxC,eAAe,CAAA;AAAA,MACf,MAAMsD,EAAY;AAAA,IAAA;AAGpB,SAAK,SAAS,IAAIgB,GAAIL,CAAO,GAC7B,KAAK,oBAAoB,IAAIjE,GAASsE,CAAE,GACxC,MAAM,KAAK,SAAS,YAAYL,CAAO,GACvC,MAAM,KAAK,mBAAmB,CAACA,CAAO,CAAC,GAEvC,KAAK,OAAO;AAAA,MACV,MAAM;AAAA,MACN,SAAS;AAAA,QACP,IAAIA,EAAQ;AAAA,QACZ,MAAMA,EAAQ;AAAA,QACd,SAASA,EAAQ;AAAA,QACjB,SAASA,EAAQ;AAAA,QACjB,eAAeA,EAAQ;AAAA,QACvB,QAAQ,CAAA;AAAA,QACR,UAAU,CAAA;AAAA,MAAC;AAAA,IACb,CACD;AAAA,EACH;AAAA,EAEA,MAAa,kBAAkBK,GAAYM,GAA6B;AACtE,QAAI,CAACA;AACH;AAGF,UAAMX,IAAU,KAAK,SAAS,IAAIK,CAAE;AACpC,IAAAL,EAAQ,OAAOW,GAEf,MAAM,KAAK,SAAS,kBAAkBN,GAAIM,CAAI;AAAA,EAChD;AAAA,EAEO,cAAcN,GAAkB;AACrC,QAAIA,KAAM/E,GAAgB;AACxB,YAAM0Y,IAAQ,KAAK,iBAAA;AACnB,iBAAWzC,KAAQyC;AACjB,QAAAzC,EAAK,SAAS,GACd,KAAK,eAAe,EAAC,SAASA,GAAM,QAAQA,EAAK,YAAW;AAAA,IAEhE,OAAO;AACL,YAAMvR,IAAU,KAAK,SAAS,IAAIK,CAAE;AACpC,MAAAL,EAAQ,SAAS,GACjB,KAAK,eAAe,EAAC,SAASA,GAAS,QAAQA,EAAQ,YAAW;AAAA,IACpE;AAAA,EACF;AAAA,EAEO,oBAA4B;AACjC,WAAI,KAAK,OAAO,QAAQ,IACf,IAEF,KAAK,IAAI,GAAG,MAAM,KAAK,KAAK,OAAO,OAAA,GAAU,CAAAgB,MAAKA,EAAE,GAAG,CAAC,IAAI;AAAA,EACrE;AAAA,EAEA,MAAa,YAAYjF,GAAiBmV,GAAejO,GAA8B;AACrF,UAAMhC,IAAkB;AAAA,MACtB,SAAAlF;AAAA,MACA,OAAAmV;AAAA,MACA,KAAKjO;AAAA,MACL,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,SAAS,EAAE,WAAW,KAAK,aAAa,IAAA;AAAA,MACxC,eAAe,CAAA;AAAA,MACf,MAAM5D,EAAY;AAAA,IAAA;AAEpB,UAAM,KAAK,SAAS4B,CAAK;AAAA,EAC3B;AAAA,EAEA,MAAc,SAASA,GAAgC;AACrD,SAAK,OAAO,IAAIA,EAAM,SAASA,CAAK,GACpC,MAAM,KAAK,SAAS,UAAUA,CAAK,GACnC,MAAM,KAAK,mBAAmB,CAACA,CAAK,CAAC,GAErC,KAAK,OAAO;AAAA,MACV,MAAM;AAAA,MACN,OAAO;AAAA,QACL,SAASA,EAAM;AAAA,QACf,SAASA,EAAM;AAAA,QACf,OAAOA,EAAM;AAAA,QACb,OAAOA,EAAM;AAAA,MAAA;AAAA,IACf,CACD;AAAA,EACH;AAAA,EAEA,MAAa,eAAiC;AAC5C,QAAIgT,IAAQ;AACZ,UAAMxD,IAAS,MAAM,KAAK,iBAAiB,eAAe,KAAK,iBAAA,EAAmB,IAAI,CAAA/P,MAAKA,EAAE,OAAO,CAAC,GAC/FmO,IAA4B,CAAA;AAClC,eAAW,CAAC9S,GAASkF,CAAK,KAAKwP;AAC7B,MAAK,KAAK,OAAO,IAAI1U,CAAO,MAC1BkY,IAAQ,IACRpF,EAAS,KAAK,KAAK,SAAS5N,CAAK,CAAC;AAGtC,iBAAM,QAAQ,IAAI4N,CAAQ,GACnBoF;AAAA,EACT;AAAA,EAEQ,eAAelY,GAAkE;AACvF,WAAOA,EAAQ,QAAQsD,EAAY;AAAA,EACrC;AAAA,EAEQ,iBAAiBtD,GAAoE;AAC3F,WAAOA,EAAQ,QAAQsD,EAAY;AAAA,EACrC;AAAA,EAEQ,cAActD,GAAoE;AACxF,WAAOA,EAAQ,QAAQsD,EAAY;AAAA,EACrC;AACF;ACjoBA,MAAM6U,KAA0B;AAAA,EAC9B,eAAe;AAAA,EACf,cAAc;AAChB,GAEMC,KAAYC,EAAY;AAAA,EAC5B,MAAM;AAAA,EAAA,cACNF;AAAAA,EACA,UAAU;AAAA,IACR,gBAAgB,CAACG,GAAOC,MAAmC;AACzD,MAAAD,EAAM,gBAAgBC,EAAO;AAAA,IAC/B;AAAA,IACA,eAAe,CAACD,GAAOC,MAAmC;AACxD,MAAAD,EAAM,eAAeC,EAAO;AAAA,IAC9B;AAAA,EAAA;AAEJ,CAAC,GAEYC,KAAcJ,GAAU,SACxBK,KAAcL,GAAU,SCjB/BD,KAA+B;AAAA,EACnC,WAAW;AAAA,EACX,gBAAgB;AAClB,GAEMO,KAAiBL,EAAY;AAAA,EACjC,MAAM;AAAA,EAAA,cACNF;AAAAA,EACA,UAAU;AAAA,IACR,YAAYG,GAAOC,GAAuC;AACxD,MAAAD,EAAM,YAAYC,EAAO,QAAQ,MACjCD,EAAM,iBAAiBC,EAAO;AAAA,IAChC;AAAA,IACA,MAAMD,GAAO;AACX,MAAAA,EAAM,YAAY,MAClBA,EAAM,iBAAiB;AAAA,IACzB;AAAA,EAAA;AAEJ,CAAC,GAEYK,KAAmBD,GAAe,SAClCE,KAAmBF,GAAe,SCtBzCG,KAAyB;AAAA,EAC7B,SAAS;AAAA,EACT,SAAS;AACX,GAEMC,KAAcT,EAAY;AAAA,EAC9B,MAAM;AAAA,EACN,cAAcQ;AAAA,EACd,UAAU;AAAA,IACR,WAAW,CAACP,GAAOC,MAAwD;AACzE,YAAMQ,IAAUR,EAAO,QAAQ,UAC3BD,EAAM,UAAU,IAChB,KAAK,IAAI,GAAGA,EAAM,UAAU,CAAC;AACjC,MAAAA,EAAM,UAAUS,GAChBT,EAAM,UAAUS,IAAU,GAC1BT,EAAM,OAAOC,EAAO,QAAQ;AAAA,IAC9B;AAAA,EAAA;AAEJ,CAAC,GAEYS,KAAgBF,GAAY,SAC5BG,KAAgBH,GAAY,SCrBnCX,KAAmC;AAAA,EACvC,QAAQ,CAAA;AAAA,EACR,MAAM,CAAA;AACR,GAEMe,KAAqBb,EAAY;AAAA,EACrC,MAAM;AAAA,EAAA,cACNF;AAAAA,EACA,UAAU;AAAA,IACR,iBAAiB,CAACG,GAAOC,MAA2C;AAClE,MAAIA,EAAO,QAAQ,QAAQ,WACzBD,EAAM,OAAOC,EAAO,QAAQ,EAAE,IAAIA,EAAO,UAChCA,EAAO,QAAQ,QAAQ,WAChCD,EAAM,KAAKC,EAAO,QAAQ,EAAE,IAAIA,EAAO;AAAA,IAE3C;AAAA,IACA,oBAAoB,CAACD,GAAOC,MAAkC;AAC5D,aAAOD,EAAM,OAAOC,EAAO,OAAO,GAClC,OAAOD,EAAM,KAAKC,EAAO,OAAO;AAAA,IAClC;AAAA,IACA,UAAU,CAACD,GAAOC,MAAqD;AACrE,MAAIA,EAAO,YAAY,WACrBD,EAAM,SAAS,CAAA,IACNC,EAAO,YAAY,SAC5BD,EAAM,OAAO,CAAA,IACJC,EAAO,YAAY,UAC5BD,EAAM,SAAS,CAAA,GACfA,EAAM,OAAO,CAAA;AAAA,IAEjB;AAAA,EAAA;AAEJ,CAAC,GAEYa,KAAuBD,GAAmB,SAC1CE,KAAuBF,GAAmB,SC9BjDf,KAA4B;AAAA,EAChC,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,OAAOvI,GAAA;AAAA,EACP,YAAY;AAAA,EACZ,aAAa;AACf,GAEayJ,KAAaC,GAAiB,qBAAqB,YAAY;AAC1E,QAAMzJ,IAASD,GAAA;AACf,MAAI;AACF,UAAMoD,IAAI,MAAMvD,GAAA;AAChB,WAAO,KAAKuD,CAAC,EAAE,QAAQ,CAAA/P,MAAY;AACjC,MAAA4M,EAAO5M,CAAQ,IAAI;AAAA,QACjB,OAAO+P,EAAE/P,CAAQ;AAAA,QACjB,QAAQ+P,EAAE,GAAG/P,CAAQ,aAAa;AAAA,MAAA;AAAA,IAEtC,CAAC;AAAA,EACH,QAAQ;AAAA,EAER;AACA,SAAO4M;AACT,CAAC,GAEK0J,KAAclB,EAAY;AAAA,EAC9B,MAAM;AAAA,EAAA,cACNF;AAAAA,EACA,UAAU;AAAA,IACR,WAAW,CAACG,GAAOC,MAAkC;AACnD,MAAIA,EAAO,UAAU,MACnBD,EAAM,SAAS,WAEjBA,EAAM,SAASC,EAAO;AAAA,IACxB;AAAA,IACA,YAAY,CAACD,MAAU;AACrB,MAAAA,EAAM,SAAS;AAAA,IACjB;AAAA,IACA,eAAe,CAACA,GAAOC,MAAmC;AACxD,MAAAD,EAAM,aAAaC,EAAO;AAAA,IAC5B;AAAA,IACA,gBAAgB,CAACD,GAAOC,MAAmC;AACzD,MAAAD,EAAM,cAAcC,EAAO;AAAA,IAC7B;AAAA,EAAA;AAAA,EAEF,eAAe,CAACxL,MAAY;AAC1B,IAAAA,EACG,QAAQsM,GAAW,WAAW,CAACf,GAAOC,MAAW;AAChD,MAAAD,EAAM,QAAQC,EAAO;AAAA,IACvB,CAAC,EACA,QAAQc,GAAW,UAAU,CAACG,GAAGjB,MAAW;AAC3C,cAAQ,MAAMA,EAAO,MAAM,OAAO;AAAA,IACpC,CAAC;AAAA,EACL;AACF,CAAC,GAEYkB,KAAgBF,GAAY,SAC5BG,KAAgBH,GAAY,SC3CnCpB,KAA4B;AAAA,EAChC,cAAc;AAAA,EACd,iBAAiB5Y;AAAA,EACjB,UAAU;AAAA,IACR,MAAM;AAAA,MACJ,IAAIA;AAAA,MACJ,MAAM;AAAA,MACN,SAAS;AAAA,MACT,SAAS,EAAC,WAAW,KAAK,aAAa,IAAA;AAAA,MACvC,eAAe,CAAA;AAAA,MACf,QAAQ,CAAA;AAAA,MACR,UAAU,CAAA;AAAA,IAAC;AAAA,EACb;AAAA,EAEF,QAAQ,CAAA;AAAA,EACR,MAAM;AAAA,EACN,UAAU;AAAA,EACV,iBAAiB;AAAA,EACjB,mBAAmB;AACrB,GAEMoa,KAActB,EAAY;AAAA,EAC9B,MAAM;AAAA,EACN,cAAAF;AAAA,EACA,UAAU;AAAA,IACR,aAAa,CAACG,GAAOC,MAAmC;AACtD,MAAAD,EAAM,WAAWC,EAAO;AAAA,IAC1B;AAAA,IACA,oBAAoB,CAACD,GAAOC,MAAkC;AAC5D,MAAAD,EAAM,kBAAkBC,EAAO;AAAA,IACjC;AAAA,IACA,SAAS,CAACD,GAAOC,MAAmC;AAClD,MAAAD,EAAM,OAAOC,EAAO;AAAA,IACtB;AAAA,IACA,UAAU,CAACD,GAAOC,MAAqC;AACrD,MAAAD,EAAM,OAAOC,EAAO,QAAQ,OAAO,IAAIA,EAAO;AAAA,IAChD;AAAA,IACA,iBAAiB,CAACD,GAAOC,MAAiE;AACxF,MAAAD,EAAM,OAAOC,EAAO,QAAQ,OAAO,EAAE,UAAUA,EAAO,QAAQ;AAAA,IAChE;AAAA,IACA,YAAY,CAACD,GAAOC,MAAmC;AACrD,MAAAD,EAAM,SAASC,EAAO,QAAQ,EAAE,IAAIA,EAAO;AAAA,IAC7C;AAAA,IACA,gBAAgB,CAACD,GAAOC,MAAkC;AACxD,MAAAD,EAAM,SAAS/Y,CAAc,EAAE,UAAUgZ,EAAO;AAAA,IAClD;AAAA,IACA,mBAAmB,CAACD,GAAOC,MAAoG;AAC7H,MAAAD,EAAM,SAASC,EAAO,QAAQ,EAAE,EAAE,UAAUA,EAAO,QAAQ,SAC3DD,EAAM,SAASC,EAAO,QAAQ,EAAE,EAAE,gBAAgBA,EAAO,QAAQ;AAAA,IACnE;AAAA,IACA,gBAAgB,CAACD,GAAOC,MAAwD;AAC9E,MAAAD,EAAM,SAASC,EAAO,QAAQ,EAAE,EAAE,OAAOA,EAAO,QAAQ;AAAA,IAC1D;AAAA,IACA,WAAW,CAACD,GAAOC,MAAiE;AAClF,MAAAD,EAAM,SAASC,EAAO,QAAQ,EAAE,EAAE,SAASA,EAAO,QAAQ;AAAA,IAC5D;AAAA,IACA,UAAU,CAACD,GAAOC,MAA8D;AAC9E,MAAAD,EAAM,SAASC,EAAO,QAAQ,EAAE,EAAE,OAAO,QAAQA,EAAO,QAAQ,KAAK;AAAA,IACvE;AAAA,IACA,aAAa,CAACD,GAAOC,MAA2D;AAC9E,MAAAD,EAAM,SAASC,EAAO,QAAQ,EAAE,EAAE,SAASD,EAAM,SAASC,EAAO,QAAQ,EAAE,EAAE,OAAO,OAAO,CAAA1E,MAAKA,EAAE,eAAe0E,EAAO,QAAQ,OAAO;AAAA,IACzI;AAAA,IACA,YAAY,CAACD,MAAU;AACrB,MAAAA,EAAM;AAAA,IACR;AAAA,IACA,aAAa,CAACA,MAAU;AACtB,MAAAA,EAAM;AAAA,IACR;AAAA,IACA,WAAWA,GAAOC,GAA0C;AAC1D,YAAM,EAAE,WAAAzT,GAAW,aAAAsM,EAAA,IAAgBmH,EAAO;AAC1C,MAAAD,EAAM,SAASxT,CAAS,EAAE,SAASsM,EAAY,QAAQ,SAAS,IAAIA;AAAA,IACtE;AAAA,IACA,cAAckH,GAAOC,GAA6C;AAChE,YAAM,EAAE,WAAAzT,GAAW,WAAAC,EAAA,IAAcwT,EAAO;AACxC,MAAID,EAAM,SAASxT,CAAS,EAAE,SAASC,CAAS,KAC9C,OAAOuT,EAAM,SAASxT,CAAS,EAAE,SAASC,CAAS;AAAA,IAEvD;AAAA,IACA,cAAcuT,GAAOC,GAA8C;AACjE,MAAAD,EAAM,SAASC,EAAO,QAAQ,SAAS,EAAE,WAAW,CAAA;AAAA,IACtD;AAAA,EAAA;AAEJ,CAAC,GAEYqB,KAAgBD,GAAY,SAC5BE,KAAgBF,GAAY,SCxG5BG,KAAiB;AAAA,EAC5B,QAAQb;AAAA,EACR,MAAML;AAAA,EACN,QAAQc;AAAA,EACR,QAAQG;AAAA,EACR,MAAMpB;AAAA,EACN,eAAeW;AACjB,GCRMW,IAAoBC,GAAY,UAAA,GAEzBC,KAAU,MAAiBF,EAAkB,CAAAzB,MAASA,EAAM,IAAI,GAEhE4B,KAAiB,MAAcH,EAAkB,CAAAzB,MAASA,EAAM,OAAO,MAAM,GAE7E6B,KAAa,CAAC7V,MAAwByV,EAAkB,OAASzB,EAAM,OAAO,SAAShU,CAAE,CAAC,GAC1F8V,KAAqB,MAAcL,EAAkB,CAAAzB,MAASA,EAAM,OAAO,eAAe,GAC1F+B,KAAmB,MAAcN,EAAkB,CAAAzB,MAAS,KAAK,IAAI,GAAG,OAAO,KAAKA,EAAM,OAAO,QAAQ,EAAE,IAAI,MAAM,CAAC,CAAC,GAEvHgC,KAAwB,CAACrW,MAA4B8V,EAAkB,CAAAzB,MAASA,EAAM,OAAO,SAASrU,CAAO,EAAE,OAAO,GAEtHsW,KAAmB,CAACtW,MAA6B8V,EAAkB,CAAAzB,MAASA,EAAM,OAAO,SAASrU,CAAO,EAAE,OAAO,GAClHuW,KAAkB,CAACvW,GAAiB4F,MAC/CkQ,EAAkB,CAAAzB,MAASA,EAAM,OAAO,SAASrU,CAAO,EAAE,cAAc4F,CAAU,CAAC,GAExE4Q,KAAiB,CAACxW,GAAiBY,MAC9CkV,EAAkB,CAAAzB,MAASA,EAAM,OAAO,SAASrU,CAAO,EAAE,SAASY,CAAO,CAAC,GAEhE6V,KAAY,MAAiCX,EAAkB,CAAAzB,MAASA,EAAM,OAAO,MAAM,GAElGqC,KAAiCC;AAAA,EACrC,CAAC,CAACtC,MAAuBA,EAAM,cAAc,MAAM;AAAA,EACnD,CAACuC,MAAW,OAAO,OAAOA,CAAM,EAAE,KAAK,CAAClW,GAAG1C,MAAMA,EAAE,YAAY0C,EAAE,SAAS;AAC5E,GAEMmW,KAA+BF;AAAA,EACnC,CAAC,CAACtC,MAAuBA,EAAM,cAAc,IAAI;AAAA,EACjD,CAACyC,MAAS,OAAO,OAAOA,CAAI,EAAE,KAAK,CAACpW,GAAG1C,MAAMA,EAAE,YAAY0C,EAAE,SAAS;AACxE,GAEMqW,KAA8BJ;AAAA,EAClC,CAACD,IAAgCG,EAA4B;AAAA,EAC7D,CAACD,GAAQE,MAAS,CAAC,GAAGF,GAAQ,GAAGE,CAAI,EAAE,KAAK,CAACpW,GAAG1C,MAAMA,EAAE,YAAY0C,EAAE,SAAS;AACjF,GAEasW,KAAyB,MAAyBlB,EAAkBY,EAA8B,GAClGO,KAAuB,MAAyBnB,EAAkBe,EAA4B,GAC9FK,KAAsB,MAAyBpB,EAAkBiB,EAA2B;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@otoplo/wallet-common",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "description": "Shared common library for internal use in Otoplo wallet",
5
5
  "license": "MIT",
6
6
  "author": "vgrunner",
package/src/utils/seed.ts CHANGED
@@ -12,8 +12,11 @@ export function isMnemonicValid(mnemonic: string): boolean {
12
12
  return validateMnemonic(mnemonic, wordlist);
13
13
  }
14
14
 
15
- function deriveKey(password: string, salt: Uint8Array): Promise<Uint8Array> {
16
- return argon2idAsync(password, salt, { t: 2, m: 19456, p: 1, dkLen: 32 });
15
+ async function deriveKey(password: string, salt: Uint8Array): Promise<Uint8Array> {
16
+ const start = performance.now();
17
+ const key = await argon2idAsync(password, salt, { t: 2, m: 19456, p: 1, dkLen: 32 });
18
+ console.log(performance.now() - start);
19
+ return key;
17
20
  }
18
21
 
19
22
  export async function encryptMnemonic(phrase: string, password: string): Promise<string> {