Files
solace-bg-dubai/frontend/lib/api/client.ts
defiQUG a03417be98
All checks were successful
CI / lint-and-test (push) Successful in 9m52s
chore: consolidate local WIP (repo cleanup 20260707)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-07 09:41:38 -07:00

134 lines
3.7 KiB
TypeScript

/** Same-origin in production (nginx /api/ → backend). Local dev uses localhost:3001. */
function apiUrl(path: string): string {
const normalized = path.startsWith("/") ? path : `/${path}`;
const configured = (process.env.NEXT_PUBLIC_API_URL ?? "").trim();
if (typeof window !== "undefined") {
// Ignore localhost baked in at build time — browser must hit same-origin /api/.
if (configured && !/^https?:\/\/(localhost|127\.0\.0\.1)(:\d+)?/i.test(configured)) {
return `${configured.replace(/\/$/, "")}${normalized}`;
}
return normalized;
}
if (configured) {
return `${configured.replace(/\/$/, "")}${normalized}`;
}
if (process.env.NODE_ENV === "production") {
return normalized;
}
return `http://localhost:3001${normalized}`;
}
export interface TreasuryRecord {
id: string;
organizationId: string;
chainId: number;
mainWallet: string;
label: string | null;
createdAt: string;
updatedAt: string;
}
export interface TransactionRecord {
id: string;
treasuryId: string;
proposalId: number;
walletAddress: string;
to: string;
value: string;
token: string | null;
data: string | null;
status: string;
proposer: string;
createdAt: string;
executedAt: string | null;
approvalCount?: number;
}
export interface SubAccountRecord {
id: string;
treasuryId: string;
address: string;
label: string | null;
metadataHash: string | null;
createdAt: string;
}
export interface LedgerEntry {
id: string;
kind: "deposit" | "transfer_out";
txHash: string;
from: string;
to: string;
value: string;
token: string | null;
tokenSymbol: string | null;
timestamp: string;
blockNumber: number;
}
async function apiFetch<T>(path: string): Promise<T> {
const res = await fetch(apiUrl(path), { cache: "no-store" });
if (!res.ok) {
throw new Error(`API ${path} failed: ${res.status}`);
}
return res.json() as Promise<T>;
}
export async function fetchTreasury(wallet: string): Promise<TreasuryRecord | null> {
const data = await apiFetch<{ treasury: TreasuryRecord | null }>(
`/api/treasury?wallet=${encodeURIComponent(wallet)}`
);
return data.treasury;
}
export async function fetchTransactions(
treasuryId: string,
status?: string
): Promise<TransactionRecord[]> {
const query = status ? `?status=${encodeURIComponent(status)}` : "";
const data = await apiFetch<{ proposals: TransactionRecord[] }>(
`/api/transactions/${treasuryId}${query}`
);
return data.proposals;
}
export async function fetchPendingProposals(treasuryId: string): Promise<TransactionRecord[]> {
const data = await apiFetch<{ proposals: TransactionRecord[] }>(
`/api/proposals/${treasuryId}?status=pending&includeApprovals=1`
);
return data.proposals;
}
export async function fetchSubAccounts(treasuryId: string): Promise<SubAccountRecord[]> {
const data = await apiFetch<{ subAccounts: SubAccountRecord[] }>(
`/api/treasury/${treasuryId}/sub-accounts`
);
return data.subAccounts;
}
export async function fetchLedger(treasuryId: string): Promise<LedgerEntry[]> {
const data = await apiFetch<{ ledger: LedgerEntry[] }>(
`/api/treasury/${treasuryId}/ledger`
);
return data.ledger;
}
export async function fetchLedgerByWallet(wallet: string): Promise<LedgerEntry[]> {
const data = await apiFetch<{ ledger: LedgerEntry[] }>(
`/api/ledger?wallet=${encodeURIComponent(wallet)}`
);
return data.ledger;
}
export async function exportTransactionsCsv(treasuryId: string): Promise<string> {
const res = await fetch(
apiUrl(`/api/transactions/export?treasuryId=${encodeURIComponent(treasuryId)}&format=csv`)
);
if (!res.ok) {
throw new Error(`CSV export failed: ${res.status}`);
}
return res.text();
}