Files
frontend/src/features/wallet/api/walletApi.ts
2026-05-14 16:32:13 +03:00

112 lines
2.8 KiB
TypeScript

import { getCsrfToken } from '@shared/api/csrf'
import { tokenStore, refreshAccessToken } from '@shared/api/tokenStore'
const WALLET_API_URL = 'https://app.cryptowallet.elcsa.ru'
export type Chain = 'ETH' | 'BSC' | 'BTC' | 'TRX' | 'SOL'
export interface FormattedAmount {
raw: string
formatted: string
decimals: number
usdPrice: number
usdValue: number
}
export interface WalletBalanceData {
chain: Chain
address: string
native: FormattedAmount
tokens: Record<string, FormattedAmount>
}
export interface PriceEntry {
usd: number
}
export interface SendWalletPayload {
to: string
amount: string
token?: string
feeTier?: 'slow' | 'normal' | 'fast'
}
export interface SendWalletResponse {
data: { txid: string; chain: Chain }
}
export const CHAINS: Chain[] = ['ETH', 'BSC', 'BTC', 'TRX', 'SOL']
async function walletGet<T>(path: string, allowRetry: boolean = true): Promise<T> {
const csrf = await getCsrfToken()
const bearer = tokenStore.get()
const res = await fetch(`${WALLET_API_URL}${path}`, {
credentials: 'include',
headers: {
'X-CSRF-Token': csrf,
...(bearer ? { Authorization: `Bearer ${bearer}` } : {}),
},
})
if (res.status === 401 && allowRetry) {
try {
await refreshAccessToken()
return walletGet<T>(path, false)
} catch {
tokenStore.clear()
throw new Error('Unauthorized')
}
}
const data = await res.json()
if (!res.ok) throw data
return data as T
}
async function walletPost<T>(path: string, body: unknown, allowRetry: boolean = true): Promise<T> {
const csrf = await getCsrfToken()
const bearer = tokenStore.get()
const res = await fetch(`${WALLET_API_URL}${path}`, {
method: 'POST',
credentials: 'include',
headers: {
'Content-Type': 'application/json',
'X-CSRF-Token': csrf,
...(bearer ? { Authorization: `Bearer ${bearer}` } : {}),
},
body: JSON.stringify(body),
})
if (res.status === 401 && allowRetry) {
try {
await refreshAccessToken()
return walletPost<T>(path, body, false)
} catch {
tokenStore.clear()
throw new Error('Unauthorized')
}
}
const data = await res.json()
if (!res.ok) throw data
return data as T
}
export async function getWalletBalance(chain: Chain): Promise<WalletBalanceData> {
const res = await walletGet<{ success: boolean; data: WalletBalanceData }>(`/api/wallets/${chain}/balance`)
return res.data
}
export async function getPrices(symbols: string[]): Promise<Record<string, PriceEntry>> {
const res = await walletGet<{ success: boolean; data: Record<string, PriceEntry> }>(
`/api/prices?symbols=${symbols.join(',')}`
)
return res.data
}
export async function sendWallet(chain: Chain, payload: SendWalletPayload): Promise<SendWalletResponse> {
return walletPost<SendWalletResponse>(`/api/wallets/${chain}/send`, payload)
}