move transaction history to alchemy lib

This commit is contained in:
2026-05-14 01:50:53 +08:00
parent f47491ad86
commit 90a3086d52
7 changed files with 170 additions and 86 deletions
+16 -46
View File
@@ -10,6 +10,7 @@ import {
import { inspect } from 'util'
import { getTokenMetadata, getTokensBalances } from './lib/alchemy'
import { tryCatch } from '@koins/utils'
import { getTransactionHistory } from './lib/alchemy/get-transaction-history'
const DEV_SERVER_PORT = 5173
const DEV_SERVER_URL = `http://localhost:${DEV_SERVER_PORT}`
@@ -94,7 +95,7 @@ type RPC = {
service: string
name: string
}
response: Promise<string | null>
response: string | null
}
setSecret: {
params: {
@@ -102,27 +103,27 @@ type RPC = {
name: string
value: string
}
response: Promise<void>
response: void
}
fetchTxHistory: {
params: {
address: string
chainid: string
}
response: Promise<TxEntry[]>
response: TxEntry[]
}
fetchTokenBalances: {
params: {
address: string
chainid: string
}
response: Promise<TokenBalanceResult[]>
response: TokenBalanceResult[]
}
openExternal: {
params: {
url: string
}
response: Promise<void>
response: void
}
}
messages: {}
@@ -138,47 +139,16 @@ async function fetchAlchemyTransfers(
chainid: string,
address: string,
): Promise<any[]> {
const network = ALCHEMY_NETWORKS[chainid]
if (!network) return []
const url = `https://${network}.g.alchemy.com/v2/${key}`
const transactions = await getTransactionHistory(
key,
chainid,
address,
{ maxCount: 10 },
)
const body = (fromAddress?: string, toAddress?: string) => ({
jsonrpc: '2.0',
id: 0,
method: 'alchemy_getAssetTransfers',
params: [
{
...(fromAddress ? { fromAddress } : {}),
...(toAddress ? { toAddress } : {}),
category: ['external', 'erc20'],
withMetadata: true,
maxCount: '0x3E8',
},
],
})
if (!transactions) return []
const [outRes, inRes] = await Promise.all([
fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body(address, undefined)),
}).then((r) => r.json()),
fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body(undefined, address)),
}).then((r) => r.json()),
])
const outgoing: any[] = outRes.result?.transfers ?? []
const incoming: any[] = inRes.result?.transfers ?? []
const seen = new Set<string>()
return [...outgoing, ...incoming].filter((t) => {
if (seen.has(t.hash)) return false
seen.add(t.hash)
return true
})
return transactions
}
function formatUnits(balance: string, decimals: number): string {
@@ -261,7 +231,7 @@ function mapTransfer(t: any): TxEntry {
}
const rpc = BrowserView.defineRPC<RPC>({
maxRequestTime: 200000,
maxRequestTime: 10000,
handlers: {
requests: {
getSecret: async ({ name, service }) => {
@@ -389,4 +359,4 @@ const win = new BrowserWindow({
},
})
console.log('Svelte app started!')
console.log('Koins app started!')
+3 -2
View File
@@ -1,5 +1,7 @@
import { tryCatch } from '@koins/utils'
const TIMEOUT = 15_000
export const post = async <T>(
url: string,
body: any,
@@ -9,6 +11,7 @@ export const post = async <T>(
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
signal: AbortSignal.timeout(TIMEOUT),
}),
)
@@ -17,8 +20,6 @@ export const post = async <T>(
throw error
}
console.log('data', await response.text())
const [data, dataError] = await tryCatch(response.json())
if (dataError) {
@@ -28,7 +28,7 @@ export const getTokensBalances = async (
params: [address, 'erc20'],
})
console.log(inspect(balRes, { depth: null, colors: true }))
// console.log(inspect(balRes, { depth: null, colors: true }))
return balRes
}
@@ -0,0 +1,59 @@
import { post } from './call'
import { getChainID, getURL } from './network'
import { inspect } from 'util'
import type { Transaction } from './types'
import { numberToHex } from 'viem'
export const getTransactionHistory = async (
key: string,
chainid: string,
address: string,
{ maxCount = 20 }: { maxCount: number },
) => {
const chainId = getChainID(chainid)
if (!chainId) return
const url = getURL({
chainId,
key,
})
const body = (fromAddress?: string, toAddress?: string) => ({
jsonrpc: '2.0',
id: 0,
method: 'alchemy_getAssetTransfers',
params: [
{
...(fromAddress ? { fromAddress } : {}),
...(toAddress ? { toAddress } : {}),
category: ['external', 'internal', 'erc20'],
withMetadata: true,
maxCount: numberToHex(maxCount),
},
],
})
const outRequest = post<{
transfers: Transaction[]
}>(url, body(address, undefined))
const inRequest = post<{
transfers: Transaction[]
}>(url, body(address, undefined))
const outRes = await outRequest
const inRes = await inRequest
console.log(inspect(outRes, { colors: true, depth: null }))
const outgoing = outRes.result?.transfers ?? []
const incoming = inRes.result?.transfers ?? []
const seen = new Set<string>()
return [...outgoing, ...incoming].filter((t) => {
if (!t.hash) return false
if (seen.has(t.hash)) return false
seen.add(t.hash)
return true
})
}
+32
View File
@@ -1,3 +1,35 @@
export type Token = {}
export type TokenBalance = {}
export type Transaction = {
category?:
| 'external'
| 'internal'
| 'token'
| 'erc20'
| 'erc721'
| 'erc1155'
| 'specialnft'
blockNum?: string
from?: string
to?: string
value?: number
erc721TokenId?: string
erc1155Metadata?: {
tokenId: string
value: string
}[]
tokenId?: string
asset?: string
uniqueId?: string
hash?: string
rawContract?: {
value?: string
address?: string
decimal?: string
}
metadata?: {
blockTimestamp?: string
}
}