add token icon
This commit is contained in:
@@ -12,10 +12,12 @@
|
||||
"build:stable": "vite build && electrobun build --env=stable"
|
||||
},
|
||||
"dependencies": {
|
||||
"@alchemy/wallet-apis": "^5.0.0-beta.28",
|
||||
"electrobun": "^1.18.1",
|
||||
"ethers": "^6.16.0",
|
||||
"mode-watcher": "^1.1.0",
|
||||
"sv-router": "latest"
|
||||
"sv-router": "latest",
|
||||
"viem": "^2.48.11"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@fontsource-variable/geist-mono": "^5.2.7",
|
||||
|
||||
@@ -137,7 +137,6 @@ async function fetchEtherscan(
|
||||
})
|
||||
const res = await fetch(`${ETHERSCAN_API}?${params}`)
|
||||
const data = await res.json()
|
||||
console.log(data)
|
||||
if (data.status !== '1') return []
|
||||
return data.result
|
||||
}
|
||||
@@ -205,7 +204,9 @@ const rpc = BrowserView.defineRPC<RPC>({
|
||||
const combined: TxEntry[] = []
|
||||
|
||||
for (const [, group] of byHash) {
|
||||
console.log(group)
|
||||
const { native, token } = group
|
||||
const nv = native?.value ?? '0'
|
||||
|
||||
const incoming = token.filter(
|
||||
(t: any) => t.to.toLowerCase() === addrLower,
|
||||
@@ -214,7 +215,7 @@ const rpc = BrowserView.defineRPC<RPC>({
|
||||
(t: any) => t.from.toLowerCase() === addrLower,
|
||||
)
|
||||
|
||||
if (native && incoming.length > 0) {
|
||||
if (native && nv !== '0' && incoming.length > 0) {
|
||||
combined.push({
|
||||
hash: native.hash,
|
||||
timeStamp: native.timeStamp,
|
||||
@@ -230,7 +231,7 @@ const rpc = BrowserView.defineRPC<RPC>({
|
||||
pairedSymbol: incoming[0].tokenSymbol,
|
||||
pairedDecimals: incoming[0].tokenDecimal,
|
||||
})
|
||||
} else if (native) {
|
||||
} else if (native && nv !== '0') {
|
||||
combined.push({
|
||||
hash: native.hash,
|
||||
timeStamp: native.timeStamp,
|
||||
@@ -254,21 +255,39 @@ const rpc = BrowserView.defineRPC<RPC>({
|
||||
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' }),
|
||||
})
|
||||
}
|
||||
} else if (outgoing.length > 0) {
|
||||
combined.push({
|
||||
hash: outgoing[0].hash,
|
||||
timeStamp: outgoing[0].timeStamp,
|
||||
from: outgoing[0].from,
|
||||
to: outgoing[0].to,
|
||||
value: outgoing[0].value,
|
||||
tokenSymbol: outgoing[0].tokenSymbol,
|
||||
tokenDecimal: outgoing[0].tokenDecimal,
|
||||
contractAddress: outgoing[0].contractAddress,
|
||||
isError: '0',
|
||||
})
|
||||
} else if (incoming.length > 0) {
|
||||
combined.push({
|
||||
hash: incoming[0].hash,
|
||||
timeStamp: incoming[0].timeStamp,
|
||||
from: incoming[0].from,
|
||||
to: incoming[0].to,
|
||||
value: incoming[0].value,
|
||||
tokenSymbol: incoming[0].tokenSymbol,
|
||||
tokenDecimal: incoming[0].tokenDecimal,
|
||||
contractAddress: incoming[0].contractAddress,
|
||||
})
|
||||
} 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,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -89,7 +89,11 @@ export const networks = [
|
||||
|
||||
export type NetworkId = (typeof networks)[number]['id']
|
||||
|
||||
export type TokenBalance = { symbol: string; balance: string }
|
||||
export type TokenBalance = {
|
||||
symbol: string
|
||||
balance: string
|
||||
address?: string
|
||||
}
|
||||
|
||||
export const Wallet = () => {
|
||||
let seed = $state('')
|
||||
@@ -189,9 +193,10 @@ export const Wallet = () => {
|
||||
return {
|
||||
symbol: t.symbol,
|
||||
balance: formatUnits(bal, t.decimals),
|
||||
address: t.address,
|
||||
}
|
||||
} catch {
|
||||
return { symbol: t.symbol, balance: '0' }
|
||||
return { symbol: t.symbol, balance: '0', address: t.address }
|
||||
}
|
||||
}),
|
||||
),
|
||||
@@ -203,9 +208,10 @@ export const Wallet = () => {
|
||||
return {
|
||||
symbol: t.symbol,
|
||||
balance: formatUnits(bal, t.decimals),
|
||||
address: t.address,
|
||||
}
|
||||
} catch {
|
||||
return { symbol: t.symbol, balance: '0' }
|
||||
return { symbol: t.symbol, balance: '0', address: t.address }
|
||||
}
|
||||
}),
|
||||
),
|
||||
@@ -294,9 +300,10 @@ export const Wallet = () => {
|
||||
return {
|
||||
symbol: t.symbol,
|
||||
balance: formatUnits(bal, t.decimals),
|
||||
address: t.address,
|
||||
}
|
||||
} catch {
|
||||
return { symbol: t.symbol, balance: '0' }
|
||||
return { symbol: t.symbol, balance: '0', address: t.address }
|
||||
}
|
||||
}),
|
||||
)
|
||||
|
||||
@@ -12,6 +12,23 @@
|
||||
} from '$lib/components/ui/card/index.js'
|
||||
import { formatEther, formatUnits } from 'ethers'
|
||||
|
||||
const CDN = 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains'
|
||||
|
||||
const chainDir: Record<string, string> = {
|
||||
eth: 'ethereum',
|
||||
bsc: 'smartchain',
|
||||
polygon: 'polygon',
|
||||
}
|
||||
|
||||
function nativeIcon(id: string) {
|
||||
return `${CDN}/${chainDir[id]}/info/logo.png`
|
||||
}
|
||||
|
||||
function tokenIcon(id: string, address?: string) {
|
||||
if (!address) return ''
|
||||
return `${CDN}/${chainDir[id]}/assets/${address}/logo.png`
|
||||
}
|
||||
|
||||
const SELECTORS: Record<string, string> = {
|
||||
'0x': 'Send',
|
||||
'0xa9059cbb': 'Transfer',
|
||||
@@ -110,12 +127,24 @@
|
||||
<p class="mt-2 font-medium text-xs">
|
||||
{w.symbol} Balance
|
||||
</p>
|
||||
<p class="font-mono text-lg">{w.balance} {w.symbol}</p>
|
||||
<p class="flex items-center gap-1.5 font-mono text-lg">
|
||||
<img
|
||||
src={nativeIcon(w.network)}
|
||||
alt=""
|
||||
class="size-4 rounded-full"
|
||||
onerror={(e) => (e.target as HTMLElement).style.display = 'none'} />
|
||||
{w.balance} {w.symbol}
|
||||
</p>
|
||||
</div>
|
||||
<div class="mb-4 space-y-1">
|
||||
<p class="font-medium text-xs">Tokens</p>
|
||||
{#each w.tokenBalances as t}
|
||||
<p class="font-mono text-sm">
|
||||
<p class="flex items-center gap-1.5 font-mono text-sm">
|
||||
<img
|
||||
src={tokenIcon(w.network, t.address)}
|
||||
alt=""
|
||||
class="size-4 rounded-full"
|
||||
onerror={(e) => (e.target as HTMLElement).style.display = 'none'} />
|
||||
{Number(t.balance) < 0.0001 && Number(t.balance) > 0
|
||||
? '<0.0001'
|
||||
: Number(t.balance).toFixed(4)}
|
||||
@@ -175,14 +204,18 @@
|
||||
{txAction(tx, w.address)}
|
||||
</button>
|
||||
</p>
|
||||
<p class="text-muted-foreground font-mono">
|
||||
<p class="flex items-center gap-1 text-muted-foreground font-mono">
|
||||
{#if tx.pairedValue}
|
||||
<img src={nativeIcon(w.network)} alt="" class="size-3.5 rounded-full" onerror={(e) => (e.target as HTMLElement).style.display = 'none'} />
|
||||
{Number(formatEther(tx.value)).toFixed(4)} {w.symbol}
|
||||
<span class="mx-1">→</span>
|
||||
<span class="mx-0.5">→</span>
|
||||
<img src={tokenIcon(w.network, tx.contractAddress)} alt="" class="size-3.5 rounded-full" onerror={(e) => (e.target as HTMLElement).style.display = 'none'} />
|
||||
{Number(formatUnits(tx.pairedValue, Number(tx.pairedDecimals ?? 18))).toFixed(4)} {tx.pairedSymbol}
|
||||
{:else if tx.tokenSymbol}
|
||||
<img src={tokenIcon(w.network, tx.contractAddress)} alt="" class="size-3.5 rounded-full" onerror={(e) => (e.target as HTMLElement).style.display = 'none'} />
|
||||
{Number(formatUnits(tx.value, Number(tx.tokenDecimal ?? 18))).toFixed(4)} {tx.tokenSymbol}
|
||||
{:else}
|
||||
<img src={nativeIcon(w.network)} alt="" class="size-3.5 rounded-full" onerror={(e) => (e.target as HTMLElement).style.display = 'none'} />
|
||||
{Number(formatEther(tx.value)).toFixed(4)} {w.symbol}
|
||||
{/if}
|
||||
</p>
|
||||
|
||||
Reference in New Issue
Block a user