@liberfi.io/ui-trade 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,243 @@
1
+ # @liberfi.io/ui-trade
2
+
3
+ Trade hooks for the Liberfi React SDK. This package provides chain-agnostic swap logic that works across Solana, Ethereum, and BSC. It is a pure-logic layer — no UI components, no toasts, no i18n — leaving side-effect control entirely to the consumer.
4
+
5
+ ## Design Philosophy
6
+
7
+ - **IoC (Inversion of Control)** — Side-effects (toast, analytics, navigation) are injected via `onSubmitted` / `onError` callbacks. The hook never hardcodes any feedback mechanism.
8
+ - **Chain-agnostic** — Works across Solana (Jupiter) and EVM chains (KyberSwap). Chain-specific differences (dex selection, tx format) are handled by the underlying `@liberfi.io/client` and `WalletAdapter` abstractions.
9
+ - **Wallet-flexible** — The `WalletAdapter` is passed per-call, not coupled to a specific wallet provider or context.
10
+ - **Layered architecture** — Builds on `@liberfi.io/react` (data layer) and `@liberfi.io/wallet-connector` (signing layer) without duplicating their logic.
11
+
12
+ ## Installation
13
+
14
+ ```bash
15
+ pnpm add @liberfi.io/ui-trade
16
+ ```
17
+
18
+ Peer dependencies the consumer must provide:
19
+
20
+ - `react` (>=18)
21
+ - `react-dom` (>=18)
22
+ - `@liberfi.io/react` (provides `DexClientProvider` and `useDexClient`)
23
+ - `@liberfi.io/wallet-connector` (provides `WalletAdapter` type)
24
+
25
+ ## API Reference
26
+
27
+ ### Hooks
28
+
29
+ #### `useSwap(options?: UseSwapOptions)`
30
+
31
+ Orchestrates the full swap flow: **route -> sign -> send**.
32
+
33
+ **Parameters:**
34
+
35
+ | Name | Type | Description |
36
+ | --------------------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------- |
37
+ | `options.onSubmitted` | `(result: SwapResult) => void` | Called when the transaction is successfully submitted on-chain. |
38
+ | `options.onError` | `(error: Error, phase: SwapPhase) => void` | Called when an error occurs. `phase` indicates where it failed: `"route"`, `"sign"`, or `"send"`. |
39
+
40
+ **Returns:** `{ swap, isSwapping }`
41
+
42
+ | Name | Type | Description |
43
+ | ------------ | ------------------------------------------- | ---------------------------------------------------------------------------- |
44
+ | `swap` | `(input: SwapInput) => Promise<SwapResult>` | Executes the swap. Resolves with `SwapResult` on success, throws on failure. |
45
+ | `isSwapping` | `boolean` | Whether a swap is currently in progress. |
46
+
47
+ #### `useTxConfirmation(options?: UseTxConfirmationOptions)`
48
+
49
+ Tracks transaction confirmation via backend SSE. Designed to compose with `useSwap`.
50
+
51
+ **Parameters:**
52
+
53
+ | Name | Type | Description |
54
+ | --------------------- | ---------------------------------------- | -------------------------------------------------------- |
55
+ | `options.onConfirmed` | `(txHash: string) => void` | Called when a tracked transaction is confirmed on-chain. |
56
+ | `options.onFailed` | `(txHash: string, error: Error) => void` | Called when confirmation fails or times out. |
57
+ | `options.timeout` | `number` | SSE timeout in milliseconds. Defaults to 60000. |
58
+
59
+ **Returns:** `{ track, clear, clearAll, transactions }`
60
+
61
+ | Name | Type | Description |
62
+ | -------------- | ---------------------------------------- | --------------------------------------------------- |
63
+ | `track` | `(chain: Chain, txHash: string) => void` | Start tracking a transaction's confirmation. |
64
+ | `clear` | `(txHash: string) => void` | Remove a single transaction from tracking. |
65
+ | `clearAll` | `() => void` | Remove all tracked transactions. |
66
+ | `transactions` | `Map<string, TrackedTx>` | All tracked transactions with their current status. |
67
+
68
+ ### Types
69
+
70
+ #### `SwapInput`
71
+
72
+ ```typescript
73
+ interface SwapInput {
74
+ chain: Chain;
75
+ wallet: WalletAdapter;
76
+ input: string; // input token address
77
+ output: string; // output token address
78
+ amount: string; // amount in smallest unit (lamports / wei)
79
+ mode?: SwapMode; // default: EXACT_IN
80
+ slippage?: number; // 0-100, default: 1
81
+ // Solana-specific
82
+ priorityFee?: string;
83
+ tipFee?: string;
84
+ isAntiMev?: boolean;
85
+ // EVM-specific
86
+ permit?: string;
87
+ deadline?: number;
88
+ }
89
+ ```
90
+
91
+ #### `SwapResult`
92
+
93
+ ```typescript
94
+ interface SwapResult {
95
+ txHash: string;
96
+ extra?: Record<string, unknown>;
97
+ }
98
+ ```
99
+
100
+ #### `SwapPhase`
101
+
102
+ ```typescript
103
+ type SwapPhase = "route" | "sign" | "send";
104
+ ```
105
+
106
+ #### `UseSwapOptions`
107
+
108
+ ```typescript
109
+ interface UseSwapOptions {
110
+ onSubmitted?: (result: SwapResult) => void;
111
+ onError?: (error: Error, phase: SwapPhase) => void;
112
+ }
113
+ ```
114
+
115
+ #### `TxConfirmationStatus`
116
+
117
+ ```typescript
118
+ type TxConfirmationStatus = "idle" | "pending" | "confirmed" | "failed";
119
+ ```
120
+
121
+ #### `UseTxConfirmationOptions`
122
+
123
+ ```typescript
124
+ interface UseTxConfirmationOptions {
125
+ onConfirmed?: (txHash: string) => void;
126
+ onFailed?: (txHash: string, error: Error) => void;
127
+ timeout?: number; // default: 60000
128
+ }
129
+ ```
130
+
131
+ ### Constants
132
+
133
+ #### `version`
134
+
135
+ ```typescript
136
+ const version: string; // e.g. "0.1.0"
137
+ ```
138
+
139
+ ## Usage Examples
140
+
141
+ ### Swap with Confirmation Tracking
142
+
143
+ ```tsx
144
+ import { Chain } from "@liberfi.io/types";
145
+ import { useSwap, useTxConfirmation } from "@liberfi.io/ui-trade";
146
+ import { useWallets } from "@liberfi.io/wallet-connector";
147
+
148
+ function SwapWithConfirmation() {
149
+ const wallets = useWallets();
150
+ const solWallet = wallets.find((w) => w.chainNamespace === "SOL");
151
+
152
+ const { track, transactions } = useTxConfirmation({
153
+ onConfirmed: (txHash) => {
154
+ toast.success(`Transaction confirmed: ${txHash}`);
155
+ },
156
+ onFailed: (txHash, error) => {
157
+ toast.error(`Transaction failed: ${error.message}`);
158
+ },
159
+ });
160
+
161
+ const { swap, isSwapping } = useSwap({
162
+ onSubmitted: (result) => {
163
+ toast.info(`Transaction submitted: ${result.txHash}`);
164
+ track(Chain.SOLANA, result.txHash);
165
+ },
166
+ onError: (error, phase) => {
167
+ toast.error(`Swap failed at ${phase}: ${error.message}`);
168
+ },
169
+ });
170
+
171
+ const handleSwap = async () => {
172
+ if (!solWallet) return;
173
+ await swap({
174
+ chain: Chain.SOLANA,
175
+ wallet: solWallet,
176
+ input: "So11111111111111111111111111111111111111112",
177
+ output: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
178
+ amount: "1000000000",
179
+ slippage: 1,
180
+ });
181
+ };
182
+
183
+ const pendingCount = [...transactions.values()].filter(
184
+ (tx) => tx.status === "pending",
185
+ ).length;
186
+
187
+ return (
188
+ <div>
189
+ <button onClick={handleSwap} disabled={isSwapping || !solWallet}>
190
+ {isSwapping ? "Swapping..." : "Swap SOL -> USDC"}
191
+ </button>
192
+ {pendingCount > 0 && <span>Confirming {pendingCount} tx...</span>}
193
+ </div>
194
+ );
195
+ }
196
+ ```
197
+
198
+ ### EVM Swap (ETH/BSC)
199
+
200
+ ```tsx
201
+ import { Chain } from "@liberfi.io/types";
202
+ import { useSwap, useTxConfirmation } from "@liberfi.io/ui-trade";
203
+ import { useWallets } from "@liberfi.io/wallet-connector";
204
+
205
+ function EvmSwapButton() {
206
+ const wallets = useWallets();
207
+ const evmWallet = wallets.find((w) => w.chainNamespace === "EVM");
208
+
209
+ const { track } = useTxConfirmation({
210
+ onConfirmed: (txHash) => console.log("Confirmed:", txHash),
211
+ onFailed: (txHash, err) => console.error("Failed:", txHash, err),
212
+ });
213
+
214
+ const { swap, isSwapping } = useSwap({
215
+ onSubmitted: (result) => track(Chain.ETHEREUM, result.txHash),
216
+ onError: (error, phase) => console.error(`Failed at ${phase}:`, error),
217
+ });
218
+
219
+ const handleSwap = async () => {
220
+ if (!evmWallet) return;
221
+ await swap({
222
+ chain: Chain.ETHEREUM,
223
+ wallet: evmWallet,
224
+ input: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
225
+ output: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
226
+ amount: "1000000000000000000",
227
+ slippage: 1,
228
+ });
229
+ };
230
+
231
+ return (
232
+ <button onClick={handleSwap} disabled={isSwapping || !evmWallet}>
233
+ {isSwapping ? "Swapping..." : "Swap ETH -> USDC"}
234
+ </button>
235
+ );
236
+ }
237
+ ```
238
+
239
+ ## Future Improvements
240
+
241
+ - Add `useSwapQuote` hook for fetching quotes without executing (read-only route info).
242
+ - Add ERC20 approval detection and `useTokenApproval` hook for EVM chains that don't support permit.
243
+ - Support `ExactOut` swap mode with output amount estimation.
@@ -0,0 +1,116 @@
1
+ import { Chain, API } from '@liberfi.io/types';
2
+ import { WalletAdapter } from '@liberfi.io/wallet-connector';
3
+
4
+ /**
5
+ * Input parameters for the `swap()` function returned by {@link useSwap}.
6
+ *
7
+ * The caller provides chain, wallet, token addresses, amount and optional
8
+ * chain-specific settings. The hook handles route fetching, signing and
9
+ * transaction submission internally.
10
+ */
11
+ interface SwapInput {
12
+ /** Target chain */
13
+ chain: Chain;
14
+ /** Wallet adapter used to sign the transaction */
15
+ wallet: WalletAdapter;
16
+ /** Input token address */
17
+ input: string;
18
+ /** Output token address */
19
+ output: string;
20
+ /** Amount in smallest unit (lamports for Solana, wei for EVM) */
21
+ amount: string;
22
+ /** Swap mode, defaults to EXACT_IN */
23
+ mode?: API.SwapMode;
24
+ /** Slippage tolerance, 0-100, defaults to 1 */
25
+ slippage?: number;
26
+ /** Priority fee in microLamports (Solana only) */
27
+ priorityFee?: string;
28
+ /** Jito/0solt tip fee in lamports (Solana only) */
29
+ tipFee?: string;
30
+ /** Enable anti-MEV via Jito/0solt (Solana only) */
31
+ isAntiMev?: boolean;
32
+ /** EIP-2612 permit data, alternative to on-chain approve (EVM only) */
33
+ permit?: string;
34
+ /** Transaction deadline timestamp in ms (EVM only) */
35
+ deadline?: number;
36
+ }
37
+ /** Result returned after a swap transaction is successfully submitted. */
38
+ interface SwapResult {
39
+ /** Transaction hash / signature */
40
+ txHash: string;
41
+ /** Extra data from the API (e.g. jobId for confirmation polling) */
42
+ extra?: Record<string, unknown>;
43
+ }
44
+ /** Phase of the swap flow, used in error callbacks. */
45
+ type SwapPhase = "route" | "sign" | "send";
46
+ /** Options for the {@link useSwap} hook. */
47
+ interface UseSwapOptions {
48
+ /** Called when the transaction is successfully submitted on-chain. */
49
+ onSubmitted?: (result: SwapResult) => void;
50
+ /** Called when an error occurs at any phase of the swap flow. */
51
+ onError?: (error: Error, phase: SwapPhase) => void;
52
+ }
53
+ /** Confirmation status of a tracked transaction. */
54
+ type TxConfirmationStatus = "idle" | "pending" | "confirmed" | "failed";
55
+ /** Options for the {@link useTxConfirmation} hook. */
56
+ interface UseTxConfirmationOptions {
57
+ /** Called when the transaction is confirmed on-chain. */
58
+ onConfirmed?: (txHash: string) => void;
59
+ /** Called when the transaction fails or confirmation times out. */
60
+ onFailed?: (txHash: string, error: Error) => void;
61
+ /** SSE timeout in milliseconds. Defaults to 60000 (60s). */
62
+ timeout?: number;
63
+ }
64
+
65
+ /**
66
+ * Hook that orchestrates the full swap flow: route -> sign -> send.
67
+ *
68
+ * Designed for IoC: no toast, no i18n, no UI side-effects.
69
+ * The caller controls feedback via `onSubmitted` / `onError` callbacks.
70
+ *
71
+ * Works across Solana and EVM chains — chain-specific differences
72
+ * (dex selection, tx format) are handled by the underlying client
73
+ * and wallet adapter abstractions.
74
+ */
75
+ declare function useSwap(options?: UseSwapOptions): {
76
+ swap: (input: SwapInput) => Promise<SwapResult>;
77
+ isSwapping: boolean;
78
+ };
79
+
80
+ interface TrackedTx {
81
+ chain: Chain;
82
+ txHash: string;
83
+ status: TxConfirmationStatus;
84
+ }
85
+ /**
86
+ * Hook that tracks transaction confirmation via backend SSE (Server-Sent Events).
87
+ *
88
+ * Designed to be composed with `useSwap` — call `track()` inside `onSubmitted`
89
+ * to start monitoring. Supports tracking multiple concurrent transactions.
90
+ *
91
+ * @example
92
+ * ```tsx
93
+ * const { swap } = useSwap({ onSubmitted: (r) => track(chain, r.txHash) });
94
+ * const { track, transactions } = useTxConfirmation({
95
+ * onConfirmed: (txHash) => toast.success(`Confirmed: ${txHash}`),
96
+ * onFailed: (txHash) => toast.error(`Failed: ${txHash}`),
97
+ * });
98
+ * ```
99
+ */
100
+ declare function useTxConfirmation(options?: UseTxConfirmationOptions): {
101
+ track: (chain: Chain, txHash: string) => void;
102
+ clear: (txHash: string) => void;
103
+ clearAll: () => void;
104
+ transactions: Map<string, TrackedTx>;
105
+ };
106
+
107
+ declare global {
108
+ interface Window {
109
+ __LIBERFI_VERSION__?: {
110
+ [key: string]: string;
111
+ };
112
+ }
113
+ }
114
+ declare const _default: "0.1.1";
115
+
116
+ export { type SwapInput, type SwapPhase, type SwapResult, type TxConfirmationStatus, type UseSwapOptions, type UseTxConfirmationOptions, useSwap, useTxConfirmation, _default as version };
@@ -0,0 +1,116 @@
1
+ import { Chain, API } from '@liberfi.io/types';
2
+ import { WalletAdapter } from '@liberfi.io/wallet-connector';
3
+
4
+ /**
5
+ * Input parameters for the `swap()` function returned by {@link useSwap}.
6
+ *
7
+ * The caller provides chain, wallet, token addresses, amount and optional
8
+ * chain-specific settings. The hook handles route fetching, signing and
9
+ * transaction submission internally.
10
+ */
11
+ interface SwapInput {
12
+ /** Target chain */
13
+ chain: Chain;
14
+ /** Wallet adapter used to sign the transaction */
15
+ wallet: WalletAdapter;
16
+ /** Input token address */
17
+ input: string;
18
+ /** Output token address */
19
+ output: string;
20
+ /** Amount in smallest unit (lamports for Solana, wei for EVM) */
21
+ amount: string;
22
+ /** Swap mode, defaults to EXACT_IN */
23
+ mode?: API.SwapMode;
24
+ /** Slippage tolerance, 0-100, defaults to 1 */
25
+ slippage?: number;
26
+ /** Priority fee in microLamports (Solana only) */
27
+ priorityFee?: string;
28
+ /** Jito/0solt tip fee in lamports (Solana only) */
29
+ tipFee?: string;
30
+ /** Enable anti-MEV via Jito/0solt (Solana only) */
31
+ isAntiMev?: boolean;
32
+ /** EIP-2612 permit data, alternative to on-chain approve (EVM only) */
33
+ permit?: string;
34
+ /** Transaction deadline timestamp in ms (EVM only) */
35
+ deadline?: number;
36
+ }
37
+ /** Result returned after a swap transaction is successfully submitted. */
38
+ interface SwapResult {
39
+ /** Transaction hash / signature */
40
+ txHash: string;
41
+ /** Extra data from the API (e.g. jobId for confirmation polling) */
42
+ extra?: Record<string, unknown>;
43
+ }
44
+ /** Phase of the swap flow, used in error callbacks. */
45
+ type SwapPhase = "route" | "sign" | "send";
46
+ /** Options for the {@link useSwap} hook. */
47
+ interface UseSwapOptions {
48
+ /** Called when the transaction is successfully submitted on-chain. */
49
+ onSubmitted?: (result: SwapResult) => void;
50
+ /** Called when an error occurs at any phase of the swap flow. */
51
+ onError?: (error: Error, phase: SwapPhase) => void;
52
+ }
53
+ /** Confirmation status of a tracked transaction. */
54
+ type TxConfirmationStatus = "idle" | "pending" | "confirmed" | "failed";
55
+ /** Options for the {@link useTxConfirmation} hook. */
56
+ interface UseTxConfirmationOptions {
57
+ /** Called when the transaction is confirmed on-chain. */
58
+ onConfirmed?: (txHash: string) => void;
59
+ /** Called when the transaction fails or confirmation times out. */
60
+ onFailed?: (txHash: string, error: Error) => void;
61
+ /** SSE timeout in milliseconds. Defaults to 60000 (60s). */
62
+ timeout?: number;
63
+ }
64
+
65
+ /**
66
+ * Hook that orchestrates the full swap flow: route -> sign -> send.
67
+ *
68
+ * Designed for IoC: no toast, no i18n, no UI side-effects.
69
+ * The caller controls feedback via `onSubmitted` / `onError` callbacks.
70
+ *
71
+ * Works across Solana and EVM chains — chain-specific differences
72
+ * (dex selection, tx format) are handled by the underlying client
73
+ * and wallet adapter abstractions.
74
+ */
75
+ declare function useSwap(options?: UseSwapOptions): {
76
+ swap: (input: SwapInput) => Promise<SwapResult>;
77
+ isSwapping: boolean;
78
+ };
79
+
80
+ interface TrackedTx {
81
+ chain: Chain;
82
+ txHash: string;
83
+ status: TxConfirmationStatus;
84
+ }
85
+ /**
86
+ * Hook that tracks transaction confirmation via backend SSE (Server-Sent Events).
87
+ *
88
+ * Designed to be composed with `useSwap` — call `track()` inside `onSubmitted`
89
+ * to start monitoring. Supports tracking multiple concurrent transactions.
90
+ *
91
+ * @example
92
+ * ```tsx
93
+ * const { swap } = useSwap({ onSubmitted: (r) => track(chain, r.txHash) });
94
+ * const { track, transactions } = useTxConfirmation({
95
+ * onConfirmed: (txHash) => toast.success(`Confirmed: ${txHash}`),
96
+ * onFailed: (txHash) => toast.error(`Failed: ${txHash}`),
97
+ * });
98
+ * ```
99
+ */
100
+ declare function useTxConfirmation(options?: UseTxConfirmationOptions): {
101
+ track: (chain: Chain, txHash: string) => void;
102
+ clear: (txHash: string) => void;
103
+ clearAll: () => void;
104
+ transactions: Map<string, TrackedTx>;
105
+ };
106
+
107
+ declare global {
108
+ interface Window {
109
+ __LIBERFI_VERSION__?: {
110
+ [key: string]: string;
111
+ };
112
+ }
113
+ }
114
+ declare const _default: "0.1.1";
115
+
116
+ export { type SwapInput, type SwapPhase, type SwapResult, type TxConfirmationStatus, type UseSwapOptions, type UseTxConfirmationOptions, useSwap, useTxConfirmation, _default as version };
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ 'use strict';var react$1=require('react'),react=require('@liberfi.io/react'),types=require('@liberfi.io/types');function I(p){let o=atob(p),i=new Uint8Array(o.length);for(let s=0;s<o.length;s++)i[s]=o.charCodeAt(s);return i}function R(p){let o="";for(let i=0;i<p.length;i++)o+=String.fromCharCode(p[i]);return btoa(o)}function k(p){let{client:o}=react.useDexClient(),[i,s]=react$1.useState(false),u=react$1.useRef(p);u.current=p;let l=react$1.useCallback(async w=>{let{wallet:d,chain:m,...t}=w;s(true);try{let e;try{e=await o.swapRoute({chain:m,userAddress:d.address,input:t.input,output:t.output,mode:t.mode??types.API.SwapMode.EXACT_IN,amount:t.amount,slippage:t.slippage,priorityFee:t.priorityFee,tipFee:t.tipFee,isAntiMev:t.isAntiMev,permit:t.permit,deadline:t.deadline});}catch(n){let f=n instanceof Error?n:new Error(String(n));throw u.current?.onError?.(f,"route"),f}let a;try{let n=I(e.serializedTx);a=await d.signTransaction(n);}catch(n){let f=n instanceof Error?n:new Error(String(n));throw u.current?.onError?.(f,"sign"),f}let r;try{let n=R(a);r=await o.sendTx({chain:m,serializedTx:n});}catch(n){let f=n instanceof Error?n:new Error(String(n));throw u.current?.onError?.(f,"send"),f}let c={txHash:r.txHash,extra:r.extra};return u.current?.onSubmitted?.(c),c}finally{s(false);}},[o]);return react$1.useMemo(()=>({swap:l,isSwapping:i}),[l,i])}var F=6e4;function V(p){let{client:o}=react.useDexClient(),[i,s]=react$1.useState(()=>new Map),u=react$1.useRef(p);u.current=p;let l=react$1.useCallback((t,e)=>{s(a=>{let r=a.get(t);if(!r||r.status===e)return a;let c=new Map(a);return c.set(t,{...r,status:e}),c});},[]),w=react$1.useCallback((t,e)=>{s(r=>{if(r.has(e))return r;let c=new Map(r);return c.set(e,{chain:t,txHash:e,status:"pending"}),c});let a=u.current?.timeout??F;o.checkTxSuccess(t,e,a).then(r=>{if(r)l(e,"confirmed"),u.current?.onConfirmed?.(e);else {let c=new Error("Transaction failed on-chain");l(e,"failed"),u.current?.onFailed?.(e,c);}}).catch(r=>{let c=r instanceof Error?r:new Error(String(r));l(e,"failed"),u.current?.onFailed?.(e,c);});},[o,l]),d=react$1.useCallback(t=>{s(e=>{if(!e.has(t))return e;let a=new Map(e);return a.delete(t),a});},[]),m=react$1.useCallback(()=>{s(t=>t.size===0?t:new Map);},[]);return react$1.useMemo(()=>({track:w,clear:d,clearAll:m,transactions:i}),[w,d,m,i])}typeof window<"u"&&(window.__LIBERFI_VERSION__=window.__LIBERFI_VERSION__||{},window.__LIBERFI_VERSION__["@liberfi.io/ui-trade"]="0.1.1");var U="0.1.1";exports.useSwap=k;exports.useTxConfirmation=V;exports.version=U;//# sourceMappingURL=index.js.map
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/hooks/useSwap.ts","../src/hooks/useTxConfirmation.ts","../src/version.ts"],"names":["base64ToUint8Array","base64","binary","bytes","i","uint8ArrayToBase64","useSwap","options","client","useDexClient","isSwapping","setIsSwapping","useState","optionsRef","useRef","swap","useCallback","input","wallet","chain","rest","route","API","e","err","signedBytes","unsignedBytes","sendResult","signedBase64","result","useMemo","DEFAULT_TIMEOUT","useTxConfirmation","transactions","setTransactions","updateTx","txHash","status","prev","existing","next","track","timeout","success","clear","clearAll","version_default"],"mappings":"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","file":"index.js","sourcesContent":["import { useCallback, useMemo, useRef, useState } from \"react\";\nimport { useDexClient } from \"@liberfi.io/react\";\nimport { API } from \"@liberfi.io/types\";\nimport type { SwapInput, SwapResult, UseSwapOptions } from \"../types\";\n\nfunction base64ToUint8Array(base64: string): Uint8Array {\n const binary = atob(base64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes;\n}\n\nfunction uint8ArrayToBase64(bytes: Uint8Array): string {\n let binary = \"\";\n for (let i = 0; i < bytes.length; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n}\n\n/**\n * Hook that orchestrates the full swap flow: route -> sign -> send.\n *\n * Designed for IoC: no toast, no i18n, no UI side-effects.\n * The caller controls feedback via `onSubmitted` / `onError` callbacks.\n *\n * Works across Solana and EVM chains — chain-specific differences\n * (dex selection, tx format) are handled by the underlying client\n * and wallet adapter abstractions.\n */\nexport function useSwap(options?: UseSwapOptions) {\n const { client } = useDexClient();\n const [isSwapping, setIsSwapping] = useState(false);\n const optionsRef = useRef(options);\n optionsRef.current = options;\n\n const swap = useCallback(\n async (input: SwapInput): Promise<SwapResult> => {\n const { wallet, chain, ...rest } = input;\n\n setIsSwapping(true);\n try {\n // 1. Fetch route — returns unsigned tx as base64\n let route: API.SwapRoute;\n try {\n route = await client.swapRoute({\n chain,\n userAddress: wallet.address,\n input: rest.input,\n output: rest.output,\n mode: rest.mode ?? API.SwapMode.EXACT_IN,\n amount: rest.amount,\n slippage: rest.slippage,\n priorityFee: rest.priorityFee,\n tipFee: rest.tipFee,\n isAntiMev: rest.isAntiMev,\n permit: rest.permit,\n deadline: rest.deadline,\n });\n } catch (e) {\n const err = e instanceof Error ? e : new Error(String(e));\n optionsRef.current?.onError?.(err, \"route\");\n throw err;\n }\n\n // 2. Sign the transaction via wallet adapter\n let signedBytes: Uint8Array;\n try {\n const unsignedBytes = base64ToUint8Array(route.serializedTx);\n signedBytes = await wallet.signTransaction(unsignedBytes);\n } catch (e) {\n const err = e instanceof Error ? e : new Error(String(e));\n optionsRef.current?.onError?.(err, \"sign\");\n throw err;\n }\n\n // 3. Submit the signed transaction\n let sendResult: API.SendTxResult;\n try {\n const signedBase64 = uint8ArrayToBase64(signedBytes);\n sendResult = await client.sendTx({\n chain,\n serializedTx: signedBase64,\n });\n } catch (e) {\n const err = e instanceof Error ? e : new Error(String(e));\n optionsRef.current?.onError?.(err, \"send\");\n throw err;\n }\n\n const result: SwapResult = {\n txHash: sendResult.txHash,\n extra: sendResult.extra,\n };\n\n optionsRef.current?.onSubmitted?.(result);\n return result;\n } finally {\n setIsSwapping(false);\n }\n },\n [client],\n );\n\n return useMemo(() => ({ swap, isSwapping }), [swap, isSwapping]);\n}\n","import { useCallback, useMemo, useRef, useState } from \"react\";\nimport { useDexClient } from \"@liberfi.io/react\";\nimport { Chain } from \"@liberfi.io/types\";\nimport type { TxConfirmationStatus, UseTxConfirmationOptions } from \"../types\";\n\ninterface TrackedTx {\n chain: Chain;\n txHash: string;\n status: TxConfirmationStatus;\n}\n\nconst DEFAULT_TIMEOUT = 60_000;\n\n/**\n * Hook that tracks transaction confirmation via backend SSE (Server-Sent Events).\n *\n * Designed to be composed with `useSwap` — call `track()` inside `onSubmitted`\n * to start monitoring. Supports tracking multiple concurrent transactions.\n *\n * @example\n * ```tsx\n * const { swap } = useSwap({ onSubmitted: (r) => track(chain, r.txHash) });\n * const { track, transactions } = useTxConfirmation({\n * onConfirmed: (txHash) => toast.success(`Confirmed: ${txHash}`),\n * onFailed: (txHash) => toast.error(`Failed: ${txHash}`),\n * });\n * ```\n */\nexport function useTxConfirmation(options?: UseTxConfirmationOptions) {\n const { client } = useDexClient();\n const [transactions, setTransactions] = useState<Map<string, TrackedTx>>(\n () => new Map(),\n );\n const optionsRef = useRef(options);\n optionsRef.current = options;\n\n const updateTx = useCallback(\n (txHash: string, status: TxConfirmationStatus) => {\n setTransactions((prev) => {\n const existing = prev.get(txHash);\n if (!existing) return prev;\n if (existing.status === status) return prev;\n const next = new Map(prev);\n next.set(txHash, { ...existing, status });\n return next;\n });\n },\n [],\n );\n\n const track = useCallback(\n (chain: Chain, txHash: string) => {\n setTransactions((prev) => {\n if (prev.has(txHash)) return prev;\n const next = new Map(prev);\n next.set(txHash, { chain, txHash, status: \"pending\" });\n return next;\n });\n\n const timeout = optionsRef.current?.timeout ?? DEFAULT_TIMEOUT;\n\n client\n .checkTxSuccess(chain, txHash, timeout)\n .then((success) => {\n if (success) {\n updateTx(txHash, \"confirmed\");\n optionsRef.current?.onConfirmed?.(txHash);\n } else {\n const err = new Error(\"Transaction failed on-chain\");\n updateTx(txHash, \"failed\");\n optionsRef.current?.onFailed?.(txHash, err);\n }\n })\n .catch((e) => {\n const err = e instanceof Error ? e : new Error(String(e));\n updateTx(txHash, \"failed\");\n optionsRef.current?.onFailed?.(txHash, err);\n });\n },\n [client, updateTx],\n );\n\n const clear = useCallback((txHash: string) => {\n setTransactions((prev) => {\n if (!prev.has(txHash)) return prev;\n const next = new Map(prev);\n next.delete(txHash);\n return next;\n });\n }, []);\n\n const clearAll = useCallback(() => {\n setTransactions((prev) => (prev.size === 0 ? prev : new Map()));\n }, []);\n\n return useMemo(\n () => ({ track, clear, clearAll, transactions }),\n [track, clear, clearAll, transactions],\n );\n}\n","declare global {\n interface Window {\n __LIBERFI_VERSION__?: {\n [key: string]: string;\n };\n }\n}\nif (typeof window !== \"undefined\") {\n window.__LIBERFI_VERSION__ = window.__LIBERFI_VERSION__ || {};\n window.__LIBERFI_VERSION__[\"@liberfi.io/ui-trade\"] = \"0.1.1\";\n}\n\nexport default \"0.1.1\";\n"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,2 @@
1
+ import {useState,useRef,useCallback,useMemo}from'react';import {useDexClient}from'@liberfi.io/react';import {API}from'@liberfi.io/types';function I(p){let o=atob(p),i=new Uint8Array(o.length);for(let s=0;s<o.length;s++)i[s]=o.charCodeAt(s);return i}function R(p){let o="";for(let i=0;i<p.length;i++)o+=String.fromCharCode(p[i]);return btoa(o)}function k(p){let{client:o}=useDexClient(),[i,s]=useState(false),u=useRef(p);u.current=p;let l=useCallback(async w=>{let{wallet:d,chain:m,...t}=w;s(true);try{let e;try{e=await o.swapRoute({chain:m,userAddress:d.address,input:t.input,output:t.output,mode:t.mode??API.SwapMode.EXACT_IN,amount:t.amount,slippage:t.slippage,priorityFee:t.priorityFee,tipFee:t.tipFee,isAntiMev:t.isAntiMev,permit:t.permit,deadline:t.deadline});}catch(n){let f=n instanceof Error?n:new Error(String(n));throw u.current?.onError?.(f,"route"),f}let a;try{let n=I(e.serializedTx);a=await d.signTransaction(n);}catch(n){let f=n instanceof Error?n:new Error(String(n));throw u.current?.onError?.(f,"sign"),f}let r;try{let n=R(a);r=await o.sendTx({chain:m,serializedTx:n});}catch(n){let f=n instanceof Error?n:new Error(String(n));throw u.current?.onError?.(f,"send"),f}let c={txHash:r.txHash,extra:r.extra};return u.current?.onSubmitted?.(c),c}finally{s(false);}},[o]);return useMemo(()=>({swap:l,isSwapping:i}),[l,i])}var F=6e4;function V(p){let{client:o}=useDexClient(),[i,s]=useState(()=>new Map),u=useRef(p);u.current=p;let l=useCallback((t,e)=>{s(a=>{let r=a.get(t);if(!r||r.status===e)return a;let c=new Map(a);return c.set(t,{...r,status:e}),c});},[]),w=useCallback((t,e)=>{s(r=>{if(r.has(e))return r;let c=new Map(r);return c.set(e,{chain:t,txHash:e,status:"pending"}),c});let a=u.current?.timeout??F;o.checkTxSuccess(t,e,a).then(r=>{if(r)l(e,"confirmed"),u.current?.onConfirmed?.(e);else {let c=new Error("Transaction failed on-chain");l(e,"failed"),u.current?.onFailed?.(e,c);}}).catch(r=>{let c=r instanceof Error?r:new Error(String(r));l(e,"failed"),u.current?.onFailed?.(e,c);});},[o,l]),d=useCallback(t=>{s(e=>{if(!e.has(t))return e;let a=new Map(e);return a.delete(t),a});},[]),m=useCallback(()=>{s(t=>t.size===0?t:new Map);},[]);return useMemo(()=>({track:w,clear:d,clearAll:m,transactions:i}),[w,d,m,i])}typeof window<"u"&&(window.__LIBERFI_VERSION__=window.__LIBERFI_VERSION__||{},window.__LIBERFI_VERSION__["@liberfi.io/ui-trade"]="0.1.1");var U="0.1.1";export{k as useSwap,V as useTxConfirmation,U as version};//# sourceMappingURL=index.mjs.map
2
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/hooks/useSwap.ts","../src/hooks/useTxConfirmation.ts","../src/version.ts"],"names":["base64ToUint8Array","base64","binary","bytes","i","uint8ArrayToBase64","useSwap","options","client","useDexClient","isSwapping","setIsSwapping","useState","optionsRef","useRef","swap","useCallback","input","wallet","chain","rest","route","API","e","err","signedBytes","unsignedBytes","sendResult","signedBase64","result","useMemo","DEFAULT_TIMEOUT","useTxConfirmation","transactions","setTransactions","updateTx","txHash","status","prev","existing","next","track","timeout","success","clear","clearAll","version_default"],"mappings":"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","file":"index.mjs","sourcesContent":["import { useCallback, useMemo, useRef, useState } from \"react\";\nimport { useDexClient } from \"@liberfi.io/react\";\nimport { API } from \"@liberfi.io/types\";\nimport type { SwapInput, SwapResult, UseSwapOptions } from \"../types\";\n\nfunction base64ToUint8Array(base64: string): Uint8Array {\n const binary = atob(base64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes;\n}\n\nfunction uint8ArrayToBase64(bytes: Uint8Array): string {\n let binary = \"\";\n for (let i = 0; i < bytes.length; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n}\n\n/**\n * Hook that orchestrates the full swap flow: route -> sign -> send.\n *\n * Designed for IoC: no toast, no i18n, no UI side-effects.\n * The caller controls feedback via `onSubmitted` / `onError` callbacks.\n *\n * Works across Solana and EVM chains — chain-specific differences\n * (dex selection, tx format) are handled by the underlying client\n * and wallet adapter abstractions.\n */\nexport function useSwap(options?: UseSwapOptions) {\n const { client } = useDexClient();\n const [isSwapping, setIsSwapping] = useState(false);\n const optionsRef = useRef(options);\n optionsRef.current = options;\n\n const swap = useCallback(\n async (input: SwapInput): Promise<SwapResult> => {\n const { wallet, chain, ...rest } = input;\n\n setIsSwapping(true);\n try {\n // 1. Fetch route — returns unsigned tx as base64\n let route: API.SwapRoute;\n try {\n route = await client.swapRoute({\n chain,\n userAddress: wallet.address,\n input: rest.input,\n output: rest.output,\n mode: rest.mode ?? API.SwapMode.EXACT_IN,\n amount: rest.amount,\n slippage: rest.slippage,\n priorityFee: rest.priorityFee,\n tipFee: rest.tipFee,\n isAntiMev: rest.isAntiMev,\n permit: rest.permit,\n deadline: rest.deadline,\n });\n } catch (e) {\n const err = e instanceof Error ? e : new Error(String(e));\n optionsRef.current?.onError?.(err, \"route\");\n throw err;\n }\n\n // 2. Sign the transaction via wallet adapter\n let signedBytes: Uint8Array;\n try {\n const unsignedBytes = base64ToUint8Array(route.serializedTx);\n signedBytes = await wallet.signTransaction(unsignedBytes);\n } catch (e) {\n const err = e instanceof Error ? e : new Error(String(e));\n optionsRef.current?.onError?.(err, \"sign\");\n throw err;\n }\n\n // 3. Submit the signed transaction\n let sendResult: API.SendTxResult;\n try {\n const signedBase64 = uint8ArrayToBase64(signedBytes);\n sendResult = await client.sendTx({\n chain,\n serializedTx: signedBase64,\n });\n } catch (e) {\n const err = e instanceof Error ? e : new Error(String(e));\n optionsRef.current?.onError?.(err, \"send\");\n throw err;\n }\n\n const result: SwapResult = {\n txHash: sendResult.txHash,\n extra: sendResult.extra,\n };\n\n optionsRef.current?.onSubmitted?.(result);\n return result;\n } finally {\n setIsSwapping(false);\n }\n },\n [client],\n );\n\n return useMemo(() => ({ swap, isSwapping }), [swap, isSwapping]);\n}\n","import { useCallback, useMemo, useRef, useState } from \"react\";\nimport { useDexClient } from \"@liberfi.io/react\";\nimport { Chain } from \"@liberfi.io/types\";\nimport type { TxConfirmationStatus, UseTxConfirmationOptions } from \"../types\";\n\ninterface TrackedTx {\n chain: Chain;\n txHash: string;\n status: TxConfirmationStatus;\n}\n\nconst DEFAULT_TIMEOUT = 60_000;\n\n/**\n * Hook that tracks transaction confirmation via backend SSE (Server-Sent Events).\n *\n * Designed to be composed with `useSwap` — call `track()` inside `onSubmitted`\n * to start monitoring. Supports tracking multiple concurrent transactions.\n *\n * @example\n * ```tsx\n * const { swap } = useSwap({ onSubmitted: (r) => track(chain, r.txHash) });\n * const { track, transactions } = useTxConfirmation({\n * onConfirmed: (txHash) => toast.success(`Confirmed: ${txHash}`),\n * onFailed: (txHash) => toast.error(`Failed: ${txHash}`),\n * });\n * ```\n */\nexport function useTxConfirmation(options?: UseTxConfirmationOptions) {\n const { client } = useDexClient();\n const [transactions, setTransactions] = useState<Map<string, TrackedTx>>(\n () => new Map(),\n );\n const optionsRef = useRef(options);\n optionsRef.current = options;\n\n const updateTx = useCallback(\n (txHash: string, status: TxConfirmationStatus) => {\n setTransactions((prev) => {\n const existing = prev.get(txHash);\n if (!existing) return prev;\n if (existing.status === status) return prev;\n const next = new Map(prev);\n next.set(txHash, { ...existing, status });\n return next;\n });\n },\n [],\n );\n\n const track = useCallback(\n (chain: Chain, txHash: string) => {\n setTransactions((prev) => {\n if (prev.has(txHash)) return prev;\n const next = new Map(prev);\n next.set(txHash, { chain, txHash, status: \"pending\" });\n return next;\n });\n\n const timeout = optionsRef.current?.timeout ?? DEFAULT_TIMEOUT;\n\n client\n .checkTxSuccess(chain, txHash, timeout)\n .then((success) => {\n if (success) {\n updateTx(txHash, \"confirmed\");\n optionsRef.current?.onConfirmed?.(txHash);\n } else {\n const err = new Error(\"Transaction failed on-chain\");\n updateTx(txHash, \"failed\");\n optionsRef.current?.onFailed?.(txHash, err);\n }\n })\n .catch((e) => {\n const err = e instanceof Error ? e : new Error(String(e));\n updateTx(txHash, \"failed\");\n optionsRef.current?.onFailed?.(txHash, err);\n });\n },\n [client, updateTx],\n );\n\n const clear = useCallback((txHash: string) => {\n setTransactions((prev) => {\n if (!prev.has(txHash)) return prev;\n const next = new Map(prev);\n next.delete(txHash);\n return next;\n });\n }, []);\n\n const clearAll = useCallback(() => {\n setTransactions((prev) => (prev.size === 0 ? prev : new Map()));\n }, []);\n\n return useMemo(\n () => ({ track, clear, clearAll, transactions }),\n [track, clear, clearAll, transactions],\n );\n}\n","declare global {\n interface Window {\n __LIBERFI_VERSION__?: {\n [key: string]: string;\n };\n }\n}\nif (typeof window !== \"undefined\") {\n window.__LIBERFI_VERSION__ = window.__LIBERFI_VERSION__ || {};\n window.__LIBERFI_VERSION__[\"@liberfi.io/ui-trade\"] = \"0.1.1\";\n}\n\nexport default \"0.1.1\";\n"]}
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@liberfi.io/ui-trade",
3
+ "version": "0.1.1",
4
+ "description": "Trade hooks for Liberfi React SDK",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.mjs",
7
+ "types": "dist/index.d.ts",
8
+ "keywords": [],
9
+ "author": "liberfi.io",
10
+ "files": [
11
+ "dist"
12
+ ],
13
+ "publishConfig": {
14
+ "access": "public"
15
+ },
16
+ "dependencies": {
17
+ "@liberfi.io/types": "0.1.39"
18
+ },
19
+ "devDependencies": {
20
+ "@types/react": "^19.1.13",
21
+ "@types/react-dom": "^19.1.9",
22
+ "react": "^19.1.1",
23
+ "react-dom": "^19.1.1",
24
+ "tsup": "^8.5.0",
25
+ "typescript": "^5.9.2",
26
+ "@liberfi.io/react": "0.1.16",
27
+ "@liberfi.io/wallet-connector": "0.1.30",
28
+ "tsconfig": "0.1.27"
29
+ },
30
+ "peerDependencies": {
31
+ "react": ">=18",
32
+ "react-dom": ">=18",
33
+ "@liberfi.io/react": "0.1.16",
34
+ "@liberfi.io/wallet-connector": "0.1.30"
35
+ },
36
+ "scripts": {
37
+ "dev": "tsup --watch",
38
+ "build": "tsup",
39
+ "test": "echo \"Error: no test specified\" && exit 1"
40
+ }
41
+ }