-
Recent Transfers
+
+ Recent Transfers
+
{loadingTransfers ? (
) : transfers.length === 0 ? (
-
+
) : (
{transfers.map((t: TransferItem) => (
-
-
Transfer
{formatDate(t.created_at)}
+
+
+
+ Transfer
+
+
+ {formatDate(t.created_at)}
+
+
-
ACBU {formatAmount(t.amount_acbu)}
-
- {t.status === 'completed' && }
- {t.status === 'pending' && }
+
+ ACBU {formatAmount(t.amount_acbu)}
+
+
+ {t.status === "completed" && (
+
+ )}
+ {t.status === "pending" && (
+
+ )}
{t.status.charAt(0).toUpperCase() + t.status.slice(1)}
@@ -352,7 +328,9 @@ const getStatusColor = (status: string) => {
/>
{exceedsBalance &&
Insufficient balance.
}
-
Available: ACBU {formatAmount(BALANCE_PLACEHOLDER)}
+
+ Available: ACBU {balanceLoading ? '...' : formatAmount(balance)}
+
diff --git a/hooks/use-balance.ts b/hooks/use-balance.ts
new file mode 100644
index 0000000..c731052
--- /dev/null
+++ b/hooks/use-balance.ts
@@ -0,0 +1,55 @@
+'use client';
+
+import { useState, useEffect, useCallback } from 'react';
+import { useApiOpts } from '@/hooks/use-api';
+import * as userApi from '@/lib/api/user';
+
+interface UseBalanceReturn {
+ balance: number | null;
+ loading: boolean;
+ error: string;
+ refetch: () => void;
+}
+
+/**
+ * Fetches the authenticated user's ACBU wallet balance from GET /users/me/balance.
+ * Returns a numeric balance (null while unknown), loading flag, error string, and refetch fn.
+ */
+export function useBalance(): UseBalanceReturn {
+ const opts = useApiOpts();
+ const [balance, setBalance] = useState(null);
+ const [loading, setLoading] = useState(true);
+ const [error, setError] = useState('');
+ const [tick, setTick] = useState(0);
+
+ const refetch = useCallback(() => setTick((t) => t + 1), []);
+
+ useEffect(() => {
+ let cancelled = false;
+ setLoading(true);
+ setError('');
+
+ userApi
+ .getBalance(opts)
+ .then((data) => {
+ if (cancelled) return;
+ const raw = data.balance;
+ const num = typeof raw === 'number' ? raw : parseFloat(raw);
+ setBalance(Number.isNaN(num) ? null : num);
+ })
+ .catch((e) => {
+ if (cancelled) return;
+ setBalance(null);
+ setError(e instanceof Error ? e.message : 'Failed to load balance');
+ })
+ .finally(() => {
+ if (!cancelled) setLoading(false);
+ });
+
+ return () => {
+ cancelled = true;
+ };
+ }, [opts.token, tick]);
+
+ return { balance, loading, error, refetch };
+}
diff --git a/lib/api/user.ts b/lib/api/user.ts
index 52cd00f..f1fa41d 100644
--- a/lib/api/user.ts
+++ b/lib/api/user.ts
@@ -1,6 +1,6 @@
import { get, post, patch, del } from './client';
import type { RequestOptions } from './client';
-import type { UserMe, PatchMeBody, ReceiveResponse, ContactItem, GuardianItem } from '@/types/api';
+import type { UserMe, PatchMeBody, ReceiveResponse, BalanceResponse, ContactItem, GuardianItem } from '@/types/api';
export async function getMe(opts?: RequestOptions): Promise {
return get('/users/me', opts);
@@ -10,6 +10,10 @@ export async function patchMe(data: PatchMeBody, opts?: RequestOptions): Promise
return patch('/users/me', data, opts);
}
+export async function getBalance(opts?: RequestOptions): Promise {
+ return get('/users/me/balance', opts);
+}
+
export async function getReceive(opts?: RequestOptions): Promise {
return get('/users/me/receive', opts);
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 9fafb0d..71917ad 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -122,6 +122,9 @@ importers:
next:
specifier: 16.0.10
version: 16.0.10(react-dom@19.2.0(react@19.2.0))(react@19.2.0)
+ next-intl:
+ specifier: ^4.8.3
+ version: 4.8.3(next@16.0.10(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react@19.2.0)(typescript@5.9.3)
next-themes:
specifier: ^0.4.6
version: 0.4.6(react-dom@19.2.0(react@19.2.0))(react@19.2.0)
@@ -215,6 +218,24 @@ packages:
'@floating-ui/utils@0.2.10':
resolution: {integrity: sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==}
+ '@formatjs/bigdecimal@0.2.0':
+ resolution: {integrity: sha512-GeaxHZbUoYvHL9tC5eltHLs+1zU70aPw0s7LwqgktIzF5oMhNY4o4deEtusJMsq7WFJF3Ye2zQEzdG8beVk73w==}
+
+ '@formatjs/ecma402-abstract@3.2.0':
+ resolution: {integrity: sha512-dHnqHgBo6GXYGRsepaE1wmsC2etaivOWd5VaJstZd+HI2zR3DCUjbDVZRtoPGkkXZmyHvBwrdEUuqfvzhF/DtQ==}
+
+ '@formatjs/fast-memoize@3.1.1':
+ resolution: {integrity: sha512-CbNbf+tlJn1baRnPkNePnBqTLxGliG6DDgNa/UtV66abwIjwsliPMOt0172tzxABYzSuxZBZfcp//qI8AvBWPg==}
+
+ '@formatjs/icu-messageformat-parser@3.5.3':
+ resolution: {integrity: sha512-HJWZ9S6JWey6iY5+YXE3Kd0ofWU1sC2KTTp56e1168g/xxWvVvr8k9G4fexIgwYV9wbtjY7kGYK5FjoWB3B2OQ==}
+
+ '@formatjs/icu-skeleton-parser@2.1.3':
+ resolution: {integrity: sha512-9mFp8TJ166ZM2pcjKwsBWXrDnOJGT7vMEScVgLygUODPOsE8S6f/FHoacvrlHK1B4dYZk8vSCNruyPU64AfgJQ==}
+
+ '@formatjs/intl-localematcher@0.8.2':
+ resolution: {integrity: sha512-q05KMYGJLyqFNFtIb8NhWLF5X3aK/k0wYt7dnRFuy6aLQL+vUwQ1cg5cO4qawEiINybeCPXAWlprY2mSBjSXAQ==}
+
'@hookform/resolvers@3.10.0':
resolution: {integrity: sha512-79Dv+3mDF7i+2ajj7SkypSKHhl1cbln1OGavqrsF7p6mbUv11xpqpacPsGDCTRvCSjEEIez2ef1NveSVL3b0Ag==}
peerDependencies:
@@ -424,6 +445,88 @@ packages:
cpu: [x64]
os: [win32]
+ '@parcel/watcher-android-arm64@2.5.6':
+ resolution: {integrity: sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==}
+ engines: {node: '>= 10.0.0'}
+ cpu: [arm64]
+ os: [android]
+
+ '@parcel/watcher-darwin-arm64@2.5.6':
+ resolution: {integrity: sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==}
+ engines: {node: '>= 10.0.0'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@parcel/watcher-darwin-x64@2.5.6':
+ resolution: {integrity: sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==}
+ engines: {node: '>= 10.0.0'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@parcel/watcher-freebsd-x64@2.5.6':
+ resolution: {integrity: sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==}
+ engines: {node: '>= 10.0.0'}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@parcel/watcher-linux-arm-glibc@2.5.6':
+ resolution: {integrity: sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==}
+ engines: {node: '>= 10.0.0'}
+ cpu: [arm]
+ os: [linux]
+
+ '@parcel/watcher-linux-arm-musl@2.5.6':
+ resolution: {integrity: sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==}
+ engines: {node: '>= 10.0.0'}
+ cpu: [arm]
+ os: [linux]
+
+ '@parcel/watcher-linux-arm64-glibc@2.5.6':
+ resolution: {integrity: sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==}
+ engines: {node: '>= 10.0.0'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@parcel/watcher-linux-arm64-musl@2.5.6':
+ resolution: {integrity: sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==}
+ engines: {node: '>= 10.0.0'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@parcel/watcher-linux-x64-glibc@2.5.6':
+ resolution: {integrity: sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==}
+ engines: {node: '>= 10.0.0'}
+ cpu: [x64]
+ os: [linux]
+
+ '@parcel/watcher-linux-x64-musl@2.5.6':
+ resolution: {integrity: sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==}
+ engines: {node: '>= 10.0.0'}
+ cpu: [x64]
+ os: [linux]
+
+ '@parcel/watcher-win32-arm64@2.5.6':
+ resolution: {integrity: sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==}
+ engines: {node: '>= 10.0.0'}
+ cpu: [arm64]
+ os: [win32]
+
+ '@parcel/watcher-win32-ia32@2.5.6':
+ resolution: {integrity: sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==}
+ engines: {node: '>= 10.0.0'}
+ cpu: [ia32]
+ os: [win32]
+
+ '@parcel/watcher-win32-x64@2.5.6':
+ resolution: {integrity: sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==}
+ engines: {node: '>= 10.0.0'}
+ cpu: [x64]
+ os: [win32]
+
+ '@parcel/watcher@2.5.6':
+ resolution: {integrity: sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==}
+ engines: {node: '>= 10.0.0'}
+
'@radix-ui/number@1.1.0':
resolution: {integrity: sha512-V3gRzhVNU1ldS5XhAPTom1fOIo4ccrjjJgmE+LI2h/WaFpHmx0MQApT+KZHnx8abG6Avtfcz4WoEciMnpFT3HQ==}
@@ -1080,9 +1183,99 @@ packages:
'@radix-ui/rect@1.1.0':
resolution: {integrity: sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg==}
+ '@schummar/icu-type-parser@1.21.5':
+ resolution: {integrity: sha512-bXHSaW5jRTmke9Vd0h5P7BtWZG9Znqb8gSDxZnxaGSJnGwPLDPfS+3g0BKzeWqzgZPsIVZkM7m2tbo18cm5HBw==}
+
+ '@swc/core-darwin-arm64@1.15.21':
+ resolution: {integrity: sha512-SA8SFg9dp0qKRH8goWsax6bptFE2EdmPf2YRAQW9WoHGf3XKM1bX0nd5UdwxmC5hXsBUZAYf7xSciCler6/oyA==}
+ engines: {node: '>=10'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@swc/core-darwin-x64@1.15.21':
+ resolution: {integrity: sha512-//fOVntgowz9+V90lVsNCtyyrtbHp3jWH6Rch7MXHXbcvbLmbCTmssl5DeedUWLLGiAAW1wksBdqdGYOTjaNLw==}
+ engines: {node: '>=10'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@swc/core-linux-arm-gnueabihf@1.15.21':
+ resolution: {integrity: sha512-meNI4Sh6h9h8DvIfEc0l5URabYMSuNvyisLmG6vnoYAS43s8ON3NJR8sDHvdP7NJTrLe0q/x2XCn6yL/BeHcZg==}
+ engines: {node: '>=10'}
+ cpu: [arm]
+ os: [linux]
+
+ '@swc/core-linux-arm64-gnu@1.15.21':
+ resolution: {integrity: sha512-QrXlNQnHeXqU2EzLlnsPoWEh8/GtNJLvfMiPsDhk+ht6Xv8+vhvZ5YZ/BokNWSIZiWPKLAqR0M7T92YF5tmD3g==}
+ engines: {node: '>=10'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@swc/core-linux-arm64-musl@1.15.21':
+ resolution: {integrity: sha512-8/yGCMO333ultDaMQivE5CjO6oXDPeeg1IV4sphojPkb0Pv0i6zvcRIkgp60xDB+UxLr6VgHgt+BBgqS959E9g==}
+ engines: {node: '>=10'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@swc/core-linux-ppc64-gnu@1.15.21':
+ resolution: {integrity: sha512-ucW0HzPx0s1dgRvcvuLSPSA/2Kk/VYTv9st8qe1Kc22Gu0Q0rH9+6TcBTmMuNIp0Xs4BPr1uBttmbO1wEGI49Q==}
+ engines: {node: '>=10'}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@swc/core-linux-s390x-gnu@1.15.21':
+ resolution: {integrity: sha512-ulTnOGc5I7YRObE/9NreAhQg94QkiR5qNhhcUZ1iFAYjzg/JGAi1ch+s/Ixe61pMIr8bfVrF0NOaB0f8wjaAfA==}
+ engines: {node: '>=10'}
+ cpu: [s390x]
+ os: [linux]
+
+ '@swc/core-linux-x64-gnu@1.15.21':
+ resolution: {integrity: sha512-D0RokxtM+cPvSqJIKR6uja4hbD+scI9ezo95mBhfSyLUs9wnPPl26sLp1ZPR/EXRdYm3F3S6RUtVi+8QXhT24Q==}
+ engines: {node: '>=10'}
+ cpu: [x64]
+ os: [linux]
+
+ '@swc/core-linux-x64-musl@1.15.21':
+ resolution: {integrity: sha512-nER8u7VeRfmU6fMDzl1NQAbbB/G7O2avmvCOwIul1uGkZ2/acbPH+DCL9h5+0yd/coNcxMBTL6NGepIew+7C2w==}
+ engines: {node: '>=10'}
+ cpu: [x64]
+ os: [linux]
+
+ '@swc/core-win32-arm64-msvc@1.15.21':
+ resolution: {integrity: sha512-+/AgNBnjYugUA8C0Do4YzymgvnGbztv7j8HKSQLvR/DQgZPoXQ2B3PqB2mTtGh/X5DhlJWiqnunN35JUgWcAeQ==}
+ engines: {node: '>=10'}
+ cpu: [arm64]
+ os: [win32]
+
+ '@swc/core-win32-ia32-msvc@1.15.21':
+ resolution: {integrity: sha512-IkSZj8PX/N4HcaFhMQtzmkV8YSnuNoJ0E6OvMwFiOfejPhiKXvl7CdDsn1f4/emYEIDO3fpgZW9DTaCRMDxaDA==}
+ engines: {node: '>=10'}
+ cpu: [ia32]
+ os: [win32]
+
+ '@swc/core-win32-x64-msvc@1.15.21':
+ resolution: {integrity: sha512-zUyWso7OOENB6e1N1hNuNn8vbvLsTdKQ5WKLgt/JcBNfJhKy/6jmBmqI3GXk/MyvQKd5SLvP7A0F36p7TeDqvw==}
+ engines: {node: '>=10'}
+ cpu: [x64]
+ os: [win32]
+
+ '@swc/core@1.15.21':
+ resolution: {integrity: sha512-fkk7NJcBscrR3/F8jiqlMptRHP650NxqDnspBMrRe5d8xOoCy9MLL5kOBLFXjFLfMo3KQQHhk+/jUULOMlR1uQ==}
+ engines: {node: '>=10'}
+ peerDependencies:
+ '@swc/helpers': '>=0.5.17'
+ peerDependenciesMeta:
+ '@swc/helpers':
+ optional: true
+
+ '@swc/counter@0.1.3':
+ resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==}
+
'@swc/helpers@0.5.15':
resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==}
+ '@swc/types@0.1.26':
+ resolution: {integrity: sha512-lyMwd7WGgG79RS7EERZV3T8wMdmPq3xwyg+1nmAM64kIhx5yl+juO2PYIHb7vTiPgPCj8LYjsNV2T5wiQHUEaw==}
+
'@tailwindcss/node@4.1.18':
resolution: {integrity: sha512-DoR7U1P7iYhw16qJ49fgXUlry1t4CpXeErJHnQ44JgTSKMaZUdf17cfn5mHchfJ4KRBZRFA/Coo+MUF5+gOaCQ==}
@@ -1366,6 +1559,9 @@ packages:
graceful-fs@4.2.11:
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
+ icu-minify@4.8.3:
+ resolution: {integrity: sha512-65Av7FLosNk7bPbmQx5z5XG2Y3T2GFppcjiXh4z1idHeVgQxlDpAmkGoYI0eFzAvrOnjpWTL5FmPDhsdfRMPEA==}
+
input-otp@1.4.1:
resolution: {integrity: sha512-+yvpmKYKHi9jIGngxagY9oWiiblPB7+nEO75F2l2o4vs+6vpPZZmUl4tBNYuTCvQjhvEIbdNeJu70bhfYP2nbw==}
peerDependencies:
@@ -1376,6 +1572,17 @@ packages:
resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==}
engines: {node: '>=12'}
+ intl-messageformat@11.2.0:
+ resolution: {integrity: sha512-IhghAA8n4KSlXuWKzYsWyWb82JoYTzShfyvdSF85oJPnNOjvv4kAo7S7Jtkm3/vJ53C7dQNRO+Gpnj3iWgTjBQ==}
+
+ is-extglob@2.1.1:
+ resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
+ engines: {node: '>=0.10.0'}
+
+ is-glob@4.0.3:
+ resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
+ engines: {node: '>=0.10.0'}
+
jiti@2.6.1:
resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==}
hasBin: true
@@ -1473,6 +1680,23 @@ packages:
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
hasBin: true
+ negotiator@1.0.0:
+ resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==}
+ engines: {node: '>= 0.6'}
+
+ next-intl-swc-plugin-extractor@4.8.3:
+ resolution: {integrity: sha512-YcaT+R9z69XkGhpDarVFWUprrCMbxgIQYPUaXoE6LGVnLjGdo8hu3gL6bramDVjNKViYY8a/pXPy7Bna0mXORg==}
+
+ next-intl@4.8.3:
+ resolution: {integrity: sha512-PvdBDWg+Leh7BR7GJUQbCDVVaBRn37GwDBWc9sv0rVQOJDQ5JU1rVzx9EEGuOGYo0DHAl70++9LQ7HxTawdL7w==}
+ peerDependencies:
+ next: ^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0
+ typescript: ^5.0.0
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
next-themes@0.4.6:
resolution: {integrity: sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA==}
peerDependencies:
@@ -1500,6 +1724,9 @@ packages:
sass:
optional: true
+ node-addon-api@7.1.1:
+ resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==}
+
node-releases@2.0.27:
resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==}
@@ -1510,6 +1737,13 @@ packages:
picocolors@1.1.1:
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
+ picomatch@4.0.4:
+ resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==}
+ engines: {node: '>=12'}
+
+ po-parser@2.1.1:
+ resolution: {integrity: sha512-ECF4zHLbUItpUgE3OTtLKlPjeBN+fKEczj2zYjDfCGOzicNs0GK3Vg2IoAYwx7LH/XYw43fZQP6xnZ4TkNxSLQ==}
+
postcss-value-parser@4.2.0:
resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==}
@@ -1695,6 +1929,11 @@ packages:
'@types/react':
optional: true
+ use-intl@4.8.3:
+ resolution: {integrity: sha512-nLxlC/RH+le6g3amA508Itnn/00mE+J22ui21QhOWo5V9hCEC43+WtnRAITbJW0ztVZphev5X9gvOf2/Dk9PLA==}
+ peerDependencies:
+ react: ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0
+
use-sidecar@1.1.3:
resolution: {integrity: sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==}
engines: {node: '>=10'}
@@ -1752,6 +1991,29 @@ snapshots:
'@floating-ui/utils@0.2.10': {}
+ '@formatjs/bigdecimal@0.2.0': {}
+
+ '@formatjs/ecma402-abstract@3.2.0':
+ dependencies:
+ '@formatjs/bigdecimal': 0.2.0
+ '@formatjs/fast-memoize': 3.1.1
+ '@formatjs/intl-localematcher': 0.8.2
+
+ '@formatjs/fast-memoize@3.1.1': {}
+
+ '@formatjs/icu-messageformat-parser@3.5.3':
+ dependencies:
+ '@formatjs/ecma402-abstract': 3.2.0
+ '@formatjs/icu-skeleton-parser': 2.1.3
+
+ '@formatjs/icu-skeleton-parser@2.1.3':
+ dependencies:
+ '@formatjs/ecma402-abstract': 3.2.0
+
+ '@formatjs/intl-localematcher@0.8.2':
+ dependencies:
+ '@formatjs/fast-memoize': 3.1.1
+
'@hookform/resolvers@3.10.0(react-hook-form@7.71.1(react@19.2.0))':
dependencies:
react-hook-form: 7.71.1(react@19.2.0)
@@ -1898,6 +2160,66 @@ snapshots:
'@next/swc-win32-x64-msvc@16.0.10':
optional: true
+ '@parcel/watcher-android-arm64@2.5.6':
+ optional: true
+
+ '@parcel/watcher-darwin-arm64@2.5.6':
+ optional: true
+
+ '@parcel/watcher-darwin-x64@2.5.6':
+ optional: true
+
+ '@parcel/watcher-freebsd-x64@2.5.6':
+ optional: true
+
+ '@parcel/watcher-linux-arm-glibc@2.5.6':
+ optional: true
+
+ '@parcel/watcher-linux-arm-musl@2.5.6':
+ optional: true
+
+ '@parcel/watcher-linux-arm64-glibc@2.5.6':
+ optional: true
+
+ '@parcel/watcher-linux-arm64-musl@2.5.6':
+ optional: true
+
+ '@parcel/watcher-linux-x64-glibc@2.5.6':
+ optional: true
+
+ '@parcel/watcher-linux-x64-musl@2.5.6':
+ optional: true
+
+ '@parcel/watcher-win32-arm64@2.5.6':
+ optional: true
+
+ '@parcel/watcher-win32-ia32@2.5.6':
+ optional: true
+
+ '@parcel/watcher-win32-x64@2.5.6':
+ optional: true
+
+ '@parcel/watcher@2.5.6':
+ dependencies:
+ detect-libc: 2.1.2
+ is-glob: 4.0.3
+ node-addon-api: 7.1.1
+ picomatch: 4.0.4
+ optionalDependencies:
+ '@parcel/watcher-android-arm64': 2.5.6
+ '@parcel/watcher-darwin-arm64': 2.5.6
+ '@parcel/watcher-darwin-x64': 2.5.6
+ '@parcel/watcher-freebsd-x64': 2.5.6
+ '@parcel/watcher-linux-arm-glibc': 2.5.6
+ '@parcel/watcher-linux-arm-musl': 2.5.6
+ '@parcel/watcher-linux-arm64-glibc': 2.5.6
+ '@parcel/watcher-linux-arm64-musl': 2.5.6
+ '@parcel/watcher-linux-x64-glibc': 2.5.6
+ '@parcel/watcher-linux-x64-musl': 2.5.6
+ '@parcel/watcher-win32-arm64': 2.5.6
+ '@parcel/watcher-win32-ia32': 2.5.6
+ '@parcel/watcher-win32-x64': 2.5.6
+
'@radix-ui/number@1.1.0': {}
'@radix-ui/primitive@1.1.1': {}
@@ -2590,10 +2912,72 @@ snapshots:
'@radix-ui/rect@1.1.0': {}
+ '@schummar/icu-type-parser@1.21.5': {}
+
+ '@swc/core-darwin-arm64@1.15.21':
+ optional: true
+
+ '@swc/core-darwin-x64@1.15.21':
+ optional: true
+
+ '@swc/core-linux-arm-gnueabihf@1.15.21':
+ optional: true
+
+ '@swc/core-linux-arm64-gnu@1.15.21':
+ optional: true
+
+ '@swc/core-linux-arm64-musl@1.15.21':
+ optional: true
+
+ '@swc/core-linux-ppc64-gnu@1.15.21':
+ optional: true
+
+ '@swc/core-linux-s390x-gnu@1.15.21':
+ optional: true
+
+ '@swc/core-linux-x64-gnu@1.15.21':
+ optional: true
+
+ '@swc/core-linux-x64-musl@1.15.21':
+ optional: true
+
+ '@swc/core-win32-arm64-msvc@1.15.21':
+ optional: true
+
+ '@swc/core-win32-ia32-msvc@1.15.21':
+ optional: true
+
+ '@swc/core-win32-x64-msvc@1.15.21':
+ optional: true
+
+ '@swc/core@1.15.21':
+ dependencies:
+ '@swc/counter': 0.1.3
+ '@swc/types': 0.1.26
+ optionalDependencies:
+ '@swc/core-darwin-arm64': 1.15.21
+ '@swc/core-darwin-x64': 1.15.21
+ '@swc/core-linux-arm-gnueabihf': 1.15.21
+ '@swc/core-linux-arm64-gnu': 1.15.21
+ '@swc/core-linux-arm64-musl': 1.15.21
+ '@swc/core-linux-ppc64-gnu': 1.15.21
+ '@swc/core-linux-s390x-gnu': 1.15.21
+ '@swc/core-linux-x64-gnu': 1.15.21
+ '@swc/core-linux-x64-musl': 1.15.21
+ '@swc/core-win32-arm64-msvc': 1.15.21
+ '@swc/core-win32-ia32-msvc': 1.15.21
+ '@swc/core-win32-x64-msvc': 1.15.21
+
+ '@swc/counter@0.1.3': {}
+
'@swc/helpers@0.5.15':
dependencies:
tslib: 2.8.1
+ '@swc/types@0.1.26':
+ dependencies:
+ '@swc/counter': 0.1.3
+
'@tailwindcss/node@4.1.18':
dependencies:
'@jridgewell/remapping': 2.3.5
@@ -2837,6 +3221,10 @@ snapshots:
graceful-fs@4.2.11: {}
+ icu-minify@4.8.3:
+ dependencies:
+ '@formatjs/icu-messageformat-parser': 3.5.3
+
input-otp@1.4.1(react-dom@19.2.0(react@19.2.0))(react@19.2.0):
dependencies:
react: 19.2.0
@@ -2844,6 +3232,18 @@ snapshots:
internmap@2.0.3: {}
+ intl-messageformat@11.2.0:
+ dependencies:
+ '@formatjs/ecma402-abstract': 3.2.0
+ '@formatjs/fast-memoize': 3.1.1
+ '@formatjs/icu-messageformat-parser': 3.5.3
+
+ is-extglob@2.1.1: {}
+
+ is-glob@4.0.3:
+ dependencies:
+ is-extglob: 2.1.1
+
jiti@2.6.1: {}
js-tokens@4.0.0: {}
@@ -2913,6 +3313,27 @@ snapshots:
nanoid@3.3.11: {}
+ negotiator@1.0.0: {}
+
+ next-intl-swc-plugin-extractor@4.8.3: {}
+
+ next-intl@4.8.3(next@16.0.10(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react@19.2.0)(typescript@5.9.3):
+ dependencies:
+ '@formatjs/intl-localematcher': 0.8.2
+ '@parcel/watcher': 2.5.6
+ '@swc/core': 1.15.21
+ icu-minify: 4.8.3
+ negotiator: 1.0.0
+ next: 16.0.10(react-dom@19.2.0(react@19.2.0))(react@19.2.0)
+ next-intl-swc-plugin-extractor: 4.8.3
+ po-parser: 2.1.1
+ react: 19.2.0
+ use-intl: 4.8.3(react@19.2.0)
+ optionalDependencies:
+ typescript: 5.9.3
+ transitivePeerDependencies:
+ - '@swc/helpers'
+
next-themes@0.4.6(react-dom@19.2.0(react@19.2.0))(react@19.2.0):
dependencies:
react: 19.2.0
@@ -2941,12 +3362,18 @@ snapshots:
- '@babel/core'
- babel-plugin-macros
+ node-addon-api@7.1.1: {}
+
node-releases@2.0.27: {}
object-assign@4.1.1: {}
picocolors@1.1.1: {}
+ picomatch@4.0.4: {}
+
+ po-parser@2.1.1: {}
+
postcss-value-parser@4.2.0: {}
postcss@8.4.31:
@@ -3139,6 +3566,14 @@ snapshots:
optionalDependencies:
'@types/react': 19.2.10
+ use-intl@4.8.3(react@19.2.0):
+ dependencies:
+ '@formatjs/fast-memoize': 3.1.1
+ '@schummar/icu-type-parser': 1.21.5
+ icu-minify: 4.8.3
+ intl-messageformat: 11.2.0
+ react: 19.2.0
+
use-sidecar@1.1.3(@types/react@19.2.10)(react@19.2.0):
dependencies:
detect-node-es: 1.1.0
diff --git a/types/api.ts b/types/api.ts
index 9a790f8..31459cd 100644
--- a/types/api.ts
+++ b/types/api.ts
@@ -44,6 +44,12 @@ export interface ReceiveResponse {
[key: string]: unknown;
}
+// Balance
+export interface BalanceResponse {
+ balance: string | number;
+ currency?: string;
+}
+
// Contacts & guardians
export interface ContactItem {
id: string;