diff --git a/apps/desktop/src/bun/index.ts b/apps/desktop/src/bun/index.ts index 134ae69..52865df 100644 --- a/apps/desktop/src/bun/index.ts +++ b/apps/desktop/src/bun/index.ts @@ -64,11 +64,15 @@ type TxEntry = { from: string to: string value: string + input?: string isError?: string tokenSymbol?: string tokenName?: string tokenDecimal?: string contractAddress?: string + pairedValue?: string + pairedSymbol?: string + pairedDecimals?: string } type RPC = { @@ -182,27 +186,91 @@ const rpc = BrowserView.defineRPC({ ), ]) - const combined: TxEntry[] = [ - ...nativeTxs.map((t: any) => ({ - hash: t.hash, - timeStamp: t.timeStamp, - from: t.from, - to: t.to, - value: t.value, - isError: t.isError, - })), - ...tokenTxs.map((t: any) => ({ - hash: t.hash, - timeStamp: t.timeStamp, - from: t.from, - to: t.to, - value: t.value, - tokenSymbol: t.tokenSymbol, - tokenName: t.tokenName, - tokenDecimal: t.tokenDecimal, - contractAddress: t.contractAddress, - })), - ] + const addrLower = address.toLowerCase() + const byHash = new Map< + string, + { native?: any; token: any[] } + >() + for (const t of nativeTxs) { + const h = t.hash + if (!byHash.has(h)) byHash.set(h, { token: [] }) + byHash.get(h)!.native = t + } + for (const t of tokenTxs) { + const h = t.hash + if (!byHash.has(h)) byHash.set(h, { token: [] }) + byHash.get(h)!.token.push(t) + } + + const combined: TxEntry[] = [] + + for (const [, group] of byHash) { + const { native, token } = group + + const incoming = token.filter( + (t: any) => t.to.toLowerCase() === addrLower, + ) + const outgoing = token.filter( + (t: any) => t.from.toLowerCase() === addrLower, + ) + + if (native && incoming.length > 0) { + combined.push({ + hash: native.hash, + timeStamp: native.timeStamp, + from: native.from, + to: native.to, + value: native.value, + input: native.input, + isError: native.isError, + tokenSymbol: incoming[0].tokenSymbol, + tokenDecimal: incoming[0].tokenDecimal, + contractAddress: incoming[0].contractAddress, + pairedValue: incoming[0].value, + pairedSymbol: incoming[0].tokenSymbol, + pairedDecimals: incoming[0].tokenDecimal, + }) + } else if (native) { + combined.push({ + hash: native.hash, + timeStamp: native.timeStamp, + from: native.from, + to: native.to, + value: native.value, + input: native.input, + isError: native.isError, + }) + } else if (incoming.length > 0 && outgoing.length > 0) { + combined.push({ + hash: incoming[0].hash, + timeStamp: incoming[0].timeStamp, + from: incoming[0].from, + to: incoming[0].to, + value: outgoing[0].value, + tokenSymbol: outgoing[0].tokenSymbol, + tokenDecimal: outgoing[0].tokenDecimal, + contractAddress: outgoing[0].contractAddress, + pairedValue: incoming[0].value, + pairedSymbol: incoming[0].tokenSymbol, + pairedDecimals: incoming[0].tokenDecimal, + }) + } else { + for (const t of token) { + const isIn = t.to.toLowerCase() === addrLower + combined.push({ + hash: t.hash, + timeStamp: t.timeStamp, + from: t.from, + to: t.to, + value: t.value, + tokenSymbol: t.tokenSymbol, + tokenDecimal: t.tokenDecimal, + contractAddress: t.contractAddress, + ...(isIn ? {} : { isError: '0' }), + }) + } + } + } combined.sort( (a, b) => Number(b.timeStamp) - Number(a.timeStamp), diff --git a/apps/desktop/src/lib/electrobun.ts b/apps/desktop/src/lib/electrobun.ts index 5ef6e2f..ac3930f 100644 --- a/apps/desktop/src/lib/electrobun.ts +++ b/apps/desktop/src/lib/electrobun.ts @@ -6,11 +6,15 @@ export type TxEntry = { from: string to: string value: string + input?: string isError?: string tokenSymbol?: string tokenName?: string tokenDecimal?: string contractAddress?: string + pairedValue?: string + pairedSymbol?: string + pairedDecimals?: string } type RPC = { diff --git a/apps/desktop/src/lib/states/wallet.svelte.ts b/apps/desktop/src/lib/states/wallet.svelte.ts index 22ff2e7..ca8abbb 100644 --- a/apps/desktop/src/lib/states/wallet.svelte.ts +++ b/apps/desktop/src/lib/states/wallet.svelte.ts @@ -177,35 +177,40 @@ export const Wallet = () => { const wallet = HDNodeWallet.fromPhrase(seed) address = wallet.address const provider = new JsonRpcProvider(net().rpc) - const [nativeBal, ...tokenBals] = await Promise.all([ - provider.getBalance(wallet.address), - ...net().tokens.map(async (t) => { - try { - const c = new Contract(t.address, ERC20_ABI, provider) - const bal = await c.balanceOf(wallet.address) - return { - symbol: t.symbol, - balance: formatUnits(bal, t.decimals), - } - } catch { - return { symbol: t.symbol, balance: '0' } - } - }), - ...discoveredTokens.map(async (t) => { - try { - const c = new Contract(t.address, ERC20_ABI, provider) - const bal = await c.balanceOf(wallet.address) - return { - symbol: t.symbol, - balance: formatUnits(bal, t.decimals), - } - } catch { - return { symbol: t.symbol, balance: '0' } - } - }), - ]) + const nativeBal = await provider.getBalance(wallet.address) balance = formatEther(nativeBal) - tokenBalances = tokenBals + + const [hardcodedBals, discoveredBals] = await Promise.all([ + Promise.all( + net().tokens.map(async (t) => { + try { + const c = new Contract(t.address, ERC20_ABI, provider) + const bal = await c.balanceOf(wallet.address) + return { + symbol: t.symbol, + balance: formatUnits(bal, t.decimals), + } + } catch { + return { symbol: t.symbol, balance: '0' } + } + }), + ), + Promise.all( + discoveredTokens.map(async (t) => { + try { + const c = new Contract(t.address, ERC20_ABI, provider) + const bal = await c.balanceOf(wallet.address) + return { + symbol: t.symbol, + balance: formatUnits(bal, t.decimals), + } + } catch { + return { symbol: t.symbol, balance: '0' } + } + }), + ), + ]) + tokenBalances = [...hardcodedBals, ...discoveredBals] fetchTxHistory() } catch (e) { error = diff --git a/apps/desktop/src/routes/index.svelte b/apps/desktop/src/routes/index.svelte index cbdac3c..3925ac9 100644 --- a/apps/desktop/src/routes/index.svelte +++ b/apps/desktop/src/routes/index.svelte @@ -1,5 +1,5 @@