import axios, { AxiosInstance } from 'axios'; export interface Payment { id: string; amount: number; currency: string; status: 'pending' | 'completed' | 'failed' | 'refunded'; paymentMethod: string; createdAt: string; description?: string; } export interface LedgerEntry { id: string; accountId: string; amount: number; currency: string; type: 'debit' | 'credit'; description: string; timestamp: string; reference?: string; } export interface BasketAllocation { symbol: string; targetWeightBps: number; routeHint?: string; } export interface BasketMandate { id: string; clientId: string; mandateName: string; chain138VaultAddress: string; baseAssetSymbol: string; status: 'draft' | 'active' | 'rebalancing' | 'closed'; allocations: BasketAllocation[]; createdAt: string; updatedAt: string; } export interface BtcDeposit { id: string; clientId: string; basketId: string; chain138VaultAddress: string; depositAddress: string; expectedAmountSats?: number; confirmationsRequired: number; currentConfirmations: number; status: | 'instruction_created' | 'pending_confirmations' | 'confirmed' | 'minted' | 'frozen'; observedTxId?: string; freezeReason?: string; createdAt: string; updatedAt: string; } export interface Holding { clientId: string; basketId: string; symbol: string; allocationWeightBps: number; bookValueSats: number; status: 'pending_funding' | 'funded'; updatedAt: string; } export interface Rebalance { id: string; clientId: string; basketId: string; sourceSymbol: string; targetSymbols: string[]; reason: string; status: 'planned' | 'queued' | 'executed' | 'failed'; createdAt: string; updatedAt: string; } export interface BridgeWithdrawal { id: string; clientId: string; basketId: string; sourceSymbol: string; destinationSymbol: string; destinationChainId: number; destinationAddress: string; amount: string; status: 'pending' | 'approved' | 'submitted' | 'failed'; createdAt: string; updatedAt: string; } export class FinanceClient { protected client: AxiosInstance; constructor(baseURL?: string) { const apiBaseURL = baseURL || (typeof window !== 'undefined' ? process.env.NEXT_PUBLIC_FINANCE_SERVICE_URL || 'http://localhost:4003' : 'http://localhost:4003'); this.client = axios.create({ baseURL: apiBaseURL, headers: { 'Content-Type': 'application/json', }, }); this.client.interceptors.request.use( (config) => { const token = this.getAuthToken(); if (token) { config.headers.Authorization = `Bearer ${token}`; } return config; }, (error) => Promise.reject(error), ); } private getAuthToken(): string | null { if (typeof window === 'undefined') return null; return localStorage.getItem('auth_token'); } setAuthToken(token: string): void { if (typeof window !== 'undefined') { localStorage.setItem('auth_token', token); } } clearAuthToken(): void { if (typeof window !== 'undefined') { localStorage.removeItem('auth_token'); } } async createPayment(data: { amount: number; currency: string; paymentMethod: string; description?: string; }): Promise { const response = await this.client.post<{ payment: Payment }>('/api/v1/payments', data); return response.data.payment; } async getPayment(paymentId: string): Promise { const response = await this.client.get(`/api/v1/payments/${paymentId}`); return response.data; } async listPayments(filters?: { status?: string; page?: number; pageSize?: number; }): Promise<{ payments: Payment[]; total: number }> { const response = await this.client.get<{ payments: Payment[]; total: number }>('/api/v1/payments', { params: filters, }); return response.data; } async getLedgerEntries(filters?: { accountId?: string; type?: 'debit' | 'credit'; startDate?: string; endDate?: string; page?: number; pageSize?: number; }): Promise<{ entries: LedgerEntry[]; total: number }> { const response = await this.client.get<{ entries: LedgerEntry[]; total: number }>( '/api/v1/ledger', { params: filters }, ); return response.data; } async createBasket(data: { clientId: string; mandateName: string; chain138VaultAddress: string; allocations: BasketAllocation[]; baseAssetSymbol?: string; }): Promise { const response = await this.client.post<{ basket: BasketMandate }>('/api/v1/baskets', data); return response.data.basket; } async createBtcDeposit(data: { clientId: string; basketId?: string; mandateName?: string; chain138VaultAddress: string; allocations?: BasketAllocation[]; expectedAmountSats?: number; clientReference?: string; }): Promise<{ deposit: BtcDeposit; basket: BasketMandate; createdBasket: boolean }> { const response = await this.client.post<{ deposit: BtcDeposit; basket: BasketMandate; createdBasket: boolean; }>('/api/v1/btc-deposits', data); return response.data; } async getBtcDeposit(id: string): Promise { const response = await this.client.get<{ deposit: BtcDeposit }>(`/api/v1/btc-deposits/${id}`); return response.data.deposit; } async getHoldings(filters?: { clientId?: string; basketId?: string }): Promise { const response = await this.client.get<{ holdings: Holding[] }>('/api/v1/holdings', { params: filters, }); return response.data.holdings; } async getRebalances(filters?: { clientId?: string; basketId?: string }): Promise { const response = await this.client.get<{ rebalances: Rebalance[] }>('/api/v1/rebalances', { params: filters, }); return response.data.rebalances; } async requestBridgeWithdrawal(data: { clientId: string; basketId: string; sourceSymbol?: string; destinationSymbol?: string; destinationChainId: number; destinationAddress: string; amount: string; }): Promise { const response = await this.client.post<{ withdrawal: BridgeWithdrawal }>( '/api/v1/withdrawals/bridge', data, ); return response.data.withdrawal; } }