@liberfi.io/ui-trade 0.1.4 → 0.1.6
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 +235 -47
- package/dist/index.d.mts +217 -41
- package/dist/index.d.ts +217 -41
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +20 -11
package/README.md
CHANGED
|
@@ -6,7 +6,8 @@ The package is organized in three layers:
|
|
|
6
6
|
|
|
7
7
|
- **Hooks** (`useSwap`, `useSwapRoutePolling`, `useTxConfirmation`) — pure-logic building blocks with no UI side-effects, designed for IoC.
|
|
8
8
|
- **Swap Widget** (`SwapWidget` / `useSwapScript` / `SwapUI` / `SwapPreviewModal`) — a full swap form with preview-before-confirm flow, following the Script/Widget/UI three-layer architecture, composable at any level.
|
|
9
|
-
- **Instant Trade** (`InstantTradeWidget` / `InstantTradeProvider` / `PresetFormWidget`) — a configurable quick-trade form with buy/sell tabs, preset management, customizable quick-amount buttons, and trade settings (slippage, priority fee, tip fee, anti-MEV).
|
|
9
|
+
- **Instant Trade** (`InstantTradeWidget` / `InstantTradeProvider` / `MultiChainPresetFormWidget` / `PresetFormWidget`) — a configurable quick-trade form with buy/sell tabs, preset management, customizable quick-amount buttons, and trade settings (slippage, priority fee, tip fee, anti-MEV).
|
|
10
|
+
- **State atoms** (`presetAtomFamily` / `instantTradeAmountAtomFamily`) — Jotai-based persistent state for trade presets and amount/preset selection, storage-backend agnostic via `atomWithStorage`.
|
|
10
11
|
|
|
11
12
|
## Design Philosophy
|
|
12
13
|
|
|
@@ -26,8 +27,10 @@ Peer dependencies the consumer must provide:
|
|
|
26
27
|
|
|
27
28
|
- `react` (>=18)
|
|
28
29
|
- `react-dom` (>=18)
|
|
30
|
+
- `jotai` (>=2.15.1) — used for persistent preset state via `atomWithStorage`
|
|
29
31
|
- `@liberfi.io/react` (provides `DexClientProvider` and `useDexClient`)
|
|
30
32
|
- `@liberfi.io/ui` (provides UI components: `Button`, `Input`, `Modal`, `Avatar`, etc.)
|
|
33
|
+
- `@liberfi.io/ui-chain-select` (provides `ChainSelectMobileUI` for `MultiChainPresetFormWidget`)
|
|
31
34
|
- `@liberfi.io/wallet-connector` (provides `WalletAdapter` type)
|
|
32
35
|
|
|
33
36
|
## API Reference
|
|
@@ -511,47 +514,185 @@ Full instant-trade form with buy/sell tabs, amount input, quick buttons, preset
|
|
|
511
514
|
|
|
512
515
|
#### `InstantTradeProvider`
|
|
513
516
|
|
|
514
|
-
Context provider for instant trade state. Use with `
|
|
515
|
-
|
|
516
|
-
```tsx
|
|
517
|
-
<InstantTradeProvider chain={Chain.SOLANA} tokenAddress="...">
|
|
518
|
-
<InstantTradeAmountInput
|
|
519
|
-
amount={amount}
|
|
520
|
-
onAmountChange={setAmount}
|
|
521
|
-
preset={preset}
|
|
522
|
-
onPresetChange={setPreset}
|
|
523
|
-
/>
|
|
524
|
-
<InstantTradeButton />
|
|
525
|
-
</InstantTradeProvider>
|
|
526
|
-
```
|
|
517
|
+
Context provider for instant trade state. Use with `InstantTradeButton` for compact inline trading.
|
|
527
518
|
|
|
528
519
|
#### `useInstantTradeScript(params)`
|
|
529
520
|
|
|
530
521
|
Script-layer hook for the instant trade form. Must be used inside an `InstantTradeProvider`. Encapsulates token queries, balance queries, form state, and swap execution.
|
|
531
522
|
|
|
532
|
-
#### `
|
|
533
|
-
|
|
534
|
-
|
|
523
|
+
#### `AmountPresetInputUI`
|
|
524
|
+
|
|
525
|
+
Pure presentational compact amount input with token icon, lightning icon, and 3 preset buttons (P1/P2/P3) with tooltips. No context dependency — all data is received via props.
|
|
526
|
+
|
|
527
|
+
**Props (`AmountPresetInputUIProps`):**
|
|
528
|
+
|
|
529
|
+
| Name | Type | Description |
|
|
530
|
+
| ----------------- | -------------------------------- | ------------------------------------------------------------------- |
|
|
531
|
+
| `token` | `PredefinedToken` | Payment token (provides symbol, decimals, and icon). |
|
|
532
|
+
| `chain` | `Chain` | Target chain — used by preset tooltips to show chain-specific info. |
|
|
533
|
+
| `amount?` | `number` | Current amount value. |
|
|
534
|
+
| `onAmountChange` | `(amount?: number) => void` | Called when the amount changes. |
|
|
535
|
+
| `preset?` | `number` | Currently selected preset index (0–2). Defaults to 0. |
|
|
536
|
+
| `onPresetChange?` | `(preset: number) => void` | Called when the user selects a different preset. |
|
|
537
|
+
| `onPresetClick?` | `(preset: number) => void` | Called when the user clicks the already-selected preset. |
|
|
538
|
+
| `presetValues?` | `TradePresetValues[]` | Preset configurations for tooltip display. Falls back to defaults. |
|
|
539
|
+
| `size?` | `"sm" \| "lg"` | Controls overall component size. Defaults to `"sm"`. |
|
|
540
|
+
| `variant?` | `"default" \| "bordered"` | Visual variant. |
|
|
541
|
+
| `radius?` | `"full" \| "lg" \| "md" \| "sm"` | Border radius. |
|
|
542
|
+
| `fullWidth?` | `boolean` | Whether the input takes full width. |
|
|
543
|
+
| `className?` | `string` | External style customization. |
|
|
544
|
+
|
|
545
|
+
#### `AmountPresetInputWidget`
|
|
546
|
+
|
|
547
|
+
Atom-backed widget that wraps `AmountPresetInputUI` with `atomWithStorage` persistence. Amount and preset selection are persisted per `id + chain + token.address` so different payment tokens and chains have separate saved values.
|
|
548
|
+
|
|
549
|
+
**Props (`AmountPresetInputWidgetProps`):**
|
|
550
|
+
|
|
551
|
+
| Name | Type | Description |
|
|
552
|
+
| ------------------- | -------------------------------- | ---------------------------------------------------------------------------- |
|
|
553
|
+
| `id` | `string` | Business identifier for storage key (e.g. `"token-detail"`). |
|
|
554
|
+
| `chain` | `Chain` | Target chain. |
|
|
555
|
+
| `token` | `PredefinedToken` | Payment token (provides symbol, decimals, address for storage key). |
|
|
556
|
+
| `storageKeyPrefix?` | `string` | Storage key prefix. Must match `PresetFormWidget`. Defaults to `"liberfi."`. |
|
|
557
|
+
| `onAmountChange?` | `(amount?: number) => void` | Notification callback (does not control state). |
|
|
558
|
+
| `onPresetChange?` | `(preset: number) => void` | Notification callback (does not control state). |
|
|
559
|
+
| `onPresetClick?` | `(preset: number) => void` | Called when the user clicks the already-selected preset. |
|
|
560
|
+
| `size?` | `"sm" \| "lg"` | Controls overall component size. Defaults to `"sm"`. |
|
|
561
|
+
| `variant?` | `"default" \| "bordered"` | Visual variant. |
|
|
562
|
+
| `radius?` | `"full" \| "lg" \| "md" \| "sm"` | Border radius. |
|
|
563
|
+
| `fullWidth?` | `boolean` | Whether the input takes full width. |
|
|
564
|
+
| `className?` | `string` | External style customization. |
|
|
535
565
|
|
|
536
566
|
#### `InstantTradeButton`
|
|
537
567
|
|
|
538
568
|
Trade execution button that reads state from `InstantTradeProvider`. Handles wallet resolution, amount conversion, and swap execution.
|
|
539
569
|
|
|
570
|
+
#### `MultiChainPresetFormWidget`
|
|
571
|
+
|
|
572
|
+
Self-contained multi-chain preset editor. Combines chain switching (`ChainSelectMobileUI`), preset index tabs (P1/P2/P3), and a persisted `PresetFormWidget`.
|
|
573
|
+
|
|
574
|
+
```tsx
|
|
575
|
+
<MultiChainPresetFormWidget
|
|
576
|
+
chains={[Chain.SOLANA, Chain.ETHEREUM, Chain.BINANCE]}
|
|
577
|
+
onChange={(chain, idx, value) => console.log(chain, idx, value)}
|
|
578
|
+
/>
|
|
579
|
+
```
|
|
580
|
+
|
|
581
|
+
**Props (`MultiChainPresetFormWidgetProps`):**
|
|
582
|
+
|
|
583
|
+
| Name | Type | Description |
|
|
584
|
+
| ------------------- | ----------------------------------------------------------------------- | ---------------------------------------------------- |
|
|
585
|
+
| `chains` | `Chain[]` | Available chains to switch between. |
|
|
586
|
+
| `defaultChain?` | `Chain` | Initial chain. Defaults to first item in `chains`. |
|
|
587
|
+
| `storageKeyPrefix?` | `string` | Storage key prefix. Defaults to `"liberfi."`. |
|
|
588
|
+
| `onChange?` | `(chain: Chain, presetIndex: number, value: TradePresetValues) => void` | Notification callback with chain and preset context. |
|
|
589
|
+
| `className?` | `string` | External style customization. |
|
|
590
|
+
|
|
540
591
|
#### `PresetFormWidget`
|
|
541
592
|
|
|
542
|
-
|
|
593
|
+
Atom-backed widget for editing a single trade preset (slippage, priority fee, tip fee, auto fee, anti-MEV, custom RPC). State is persisted via `atomWithStorage` (keyed by prefix + chain + preset index).
|
|
594
|
+
|
|
595
|
+
For a pure presentational form without persistence, use `PresetFormUI` directly.
|
|
543
596
|
|
|
544
597
|
```tsx
|
|
545
598
|
<PresetFormWidget
|
|
546
599
|
chain={Chain.SOLANA}
|
|
547
|
-
|
|
548
|
-
|
|
600
|
+
presetIndex={0}
|
|
601
|
+
storageKeyPrefix="myapp."
|
|
602
|
+
onChange={(next) => console.log("Preset changed:", next)}
|
|
549
603
|
/>
|
|
550
604
|
```
|
|
551
605
|
|
|
606
|
+
**Props (`PresetFormWidgetProps`):**
|
|
607
|
+
|
|
608
|
+
| Name | Type | Description |
|
|
609
|
+
| ------------------- | ------------------------------------ | ---------------------------------------------------- |
|
|
610
|
+
| `chain` | `Chain` | Target chain — determines default values and fields. |
|
|
611
|
+
| `presetIndex?` | `number` | Preset index (0, 1, or 2). Defaults to 0. |
|
|
612
|
+
| `storageKeyPrefix?` | `string` | Storage key prefix. Defaults to `"liberfi."`. |
|
|
613
|
+
| `onChange?` | `(value: TradePresetValues) => void` | Notification callback (does not control state). |
|
|
614
|
+
| `className?` | `string` | External style customization. |
|
|
615
|
+
|
|
552
616
|
#### `PresetFormUI`
|
|
553
617
|
|
|
554
|
-
Pure presentational preset form. Accepts value/onChange props directly
|
|
618
|
+
Pure presentational preset form. Accepts value/onChange props directly. No persistence — the caller owns the state.
|
|
619
|
+
|
|
620
|
+
#### `useInstantTradeAmount(params)`
|
|
621
|
+
|
|
622
|
+
Read-only hook for the persisted instant-trade amount and preset index. Reads from the same `atomWithStorage` atom family that `AmountPresetInputWidget` writes to.
|
|
623
|
+
|
|
624
|
+
**Parameters (`UseInstantTradeAmountParams`):**
|
|
625
|
+
|
|
626
|
+
| Name | Type | Description |
|
|
627
|
+
| ------------------- | -------- | ----------------------------------------------------------------------------- |
|
|
628
|
+
| `id` | `string` | Business identifier (must match the widget's `id`). |
|
|
629
|
+
| `chain` | `Chain` | Target chain. |
|
|
630
|
+
| `tokenAddress` | `string` | Payment token address. |
|
|
631
|
+
| `storageKeyPrefix?` | `string` | Storage key prefix. Must match the widget's prefix. Defaults to `"liberfi."`. |
|
|
632
|
+
|
|
633
|
+
**Returns:** `AmountPresetState`
|
|
634
|
+
|
|
635
|
+
| Name | Type | Description |
|
|
636
|
+
| -------- | --------------------- | ----------------------- |
|
|
637
|
+
| `amount` | `number \| undefined` | Persisted amount value. |
|
|
638
|
+
| `preset` | `number` | Persisted preset index. |
|
|
639
|
+
|
|
640
|
+
### State Atoms
|
|
641
|
+
|
|
642
|
+
#### `presetAtomFamily`
|
|
643
|
+
|
|
644
|
+
Atom family for trade preset values, persisted via `atomWithStorage`. Each atom is keyed by `"{chain}:{index}"` (use `presetKey` to build the key). Default values are chain-specific.
|
|
645
|
+
|
|
646
|
+
```typescript
|
|
647
|
+
import { presetAtomFamily, presetKey } from "@liberfi.io/ui-trade";
|
|
648
|
+
|
|
649
|
+
const atom = presetAtomFamily(presetKey(Chain.SOLANA, "buy", 0));
|
|
650
|
+
```
|
|
651
|
+
|
|
652
|
+
#### `presetKey(chain, direction, index, prefix?)`
|
|
653
|
+
|
|
654
|
+
Constructs an atomFamily key string from chain, direction, preset index and optional prefix.
|
|
655
|
+
|
|
656
|
+
| Name | Type | Description |
|
|
657
|
+
| ----------- | ----------------- | --------------------------------------------- |
|
|
658
|
+
| `chain` | `Chain` | Target chain. |
|
|
659
|
+
| `direction` | `"buy" \| "sell"` | Trade direction. |
|
|
660
|
+
| `index` | `number` | Preset index (0, 1, or 2). |
|
|
661
|
+
| `prefix?` | `string` | Storage key prefix. Defaults to `"liberfi."`. |
|
|
662
|
+
|
|
663
|
+
**Returns:** `string` — key for use with `presetAtomFamily`.
|
|
664
|
+
|
|
665
|
+
#### `instantTradeAmountAtomFamily`
|
|
666
|
+
|
|
667
|
+
Atom family for instant-trade amount and preset index, persisted via `atomWithStorage`. Each atom is keyed by a string built with `instantTradeAmountKey`. The storage key includes `id`, `chain`, and `tokenAddress` so the same token on different chains has separate persisted values.
|
|
668
|
+
|
|
669
|
+
```typescript
|
|
670
|
+
import {
|
|
671
|
+
instantTradeAmountAtomFamily,
|
|
672
|
+
instantTradeAmountKey,
|
|
673
|
+
} from "@liberfi.io/ui-trade";
|
|
674
|
+
|
|
675
|
+
const atom = instantTradeAmountAtomFamily(
|
|
676
|
+
instantTradeAmountKey(
|
|
677
|
+
"token-detail",
|
|
678
|
+
Chain.SOLANA,
|
|
679
|
+
"11111111111111111111111111111111",
|
|
680
|
+
),
|
|
681
|
+
);
|
|
682
|
+
```
|
|
683
|
+
|
|
684
|
+
#### `instantTradeAmountKey(id, chain, tokenAddress, prefix?)`
|
|
685
|
+
|
|
686
|
+
Constructs an atomFamily key string for instant-trade amount + preset state.
|
|
687
|
+
|
|
688
|
+
| Name | Type | Description |
|
|
689
|
+
| -------------- | -------- | --------------------------------------------- |
|
|
690
|
+
| `id` | `string` | Business identifier. |
|
|
691
|
+
| `chain` | `Chain` | Target chain. |
|
|
692
|
+
| `tokenAddress` | `string` | Payment token address. |
|
|
693
|
+
| `prefix?` | `string` | Storage key prefix. Defaults to `"liberfi."`. |
|
|
694
|
+
|
|
695
|
+
**Returns:** `string` — key for use with `instantTradeAmountAtomFamily`.
|
|
555
696
|
|
|
556
697
|
### Instant Trade Types
|
|
557
698
|
|
|
@@ -588,7 +729,7 @@ interface SellSettings {
|
|
|
588
729
|
}
|
|
589
730
|
```
|
|
590
731
|
|
|
591
|
-
#### `
|
|
732
|
+
#### `DEFAULT_SOL_TRADE_PRESET`
|
|
592
733
|
|
|
593
734
|
Default preset values: slippage=20, priorityFee=0.001, tipFee=0.001, autoFee=false, maxAutoFee=0.1, antiMev="off".
|
|
594
735
|
|
|
@@ -620,53 +761,100 @@ function TokenTradePage({ tokenAddress }: { tokenAddress: string }) {
|
|
|
620
761
|
}
|
|
621
762
|
```
|
|
622
763
|
|
|
623
|
-
###
|
|
764
|
+
### AmountPresetInputWidget (Persisted Quick-Buy)
|
|
624
765
|
|
|
625
766
|
```tsx
|
|
626
767
|
import { Chain } from "@liberfi.io/types";
|
|
627
|
-
import {
|
|
628
|
-
|
|
629
|
-
InstantTradeAmountInput,
|
|
630
|
-
InstantTradeButton,
|
|
631
|
-
} from "@liberfi.io/ui-trade";
|
|
768
|
+
import { AmountPresetInputWidget } from "@liberfi.io/ui-trade";
|
|
769
|
+
import { SOLANA_TOKENS } from "@liberfi.io/utils";
|
|
632
770
|
|
|
633
|
-
function TokenHeader(
|
|
771
|
+
function TokenHeader() {
|
|
634
772
|
return (
|
|
635
|
-
<
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
<InstantTradeButton />
|
|
644
|
-
</div>
|
|
645
|
-
</InstantTradeProvider>
|
|
773
|
+
<AmountPresetInputWidget
|
|
774
|
+
id="token-detail"
|
|
775
|
+
chain={Chain.SOLANA}
|
|
776
|
+
token={SOLANA_TOKENS.native}
|
|
777
|
+
variant="bordered"
|
|
778
|
+
size="sm"
|
|
779
|
+
onPresetClick={(p) => console.log(`Open settings for preset ${p}`)}
|
|
780
|
+
/>
|
|
646
781
|
);
|
|
647
782
|
}
|
|
648
783
|
```
|
|
649
784
|
|
|
650
|
-
###
|
|
785
|
+
### AmountPresetInputUI (Controlled)
|
|
651
786
|
|
|
652
787
|
```tsx
|
|
653
788
|
import { useState } from "react";
|
|
654
789
|
import { Chain } from "@liberfi.io/types";
|
|
655
|
-
import {
|
|
790
|
+
import { AmountPresetInputUI } from "@liberfi.io/ui-trade";
|
|
791
|
+
import { SOLANA_TOKENS } from "@liberfi.io/utils";
|
|
656
792
|
|
|
657
|
-
function
|
|
658
|
-
const [
|
|
793
|
+
function CustomAmountInput() {
|
|
794
|
+
const [amount, setAmount] = useState<number | undefined>();
|
|
795
|
+
const [preset, setPreset] = useState(0);
|
|
659
796
|
|
|
660
797
|
return (
|
|
661
|
-
<
|
|
798
|
+
<AmountPresetInputUI
|
|
799
|
+
token={SOLANA_TOKENS.native}
|
|
662
800
|
chain={Chain.SOLANA}
|
|
663
|
-
|
|
664
|
-
|
|
801
|
+
amount={amount}
|
|
802
|
+
onAmountChange={setAmount}
|
|
803
|
+
preset={preset}
|
|
804
|
+
onPresetChange={setPreset}
|
|
805
|
+
variant="bordered"
|
|
806
|
+
size="lg"
|
|
807
|
+
/>
|
|
808
|
+
);
|
|
809
|
+
}
|
|
810
|
+
```
|
|
811
|
+
|
|
812
|
+
### Reading Persisted Amount/Preset
|
|
813
|
+
|
|
814
|
+
```tsx
|
|
815
|
+
import { Chain } from "@liberfi.io/types";
|
|
816
|
+
import { useInstantTradeAmount } from "@liberfi.io/ui-trade";
|
|
817
|
+
|
|
818
|
+
function useTokenDetailAmount(tokenAddress: string) {
|
|
819
|
+
const { amount, preset } = useInstantTradeAmount({
|
|
820
|
+
id: "token-detail",
|
|
821
|
+
chain: Chain.SOLANA,
|
|
822
|
+
tokenAddress,
|
|
823
|
+
});
|
|
824
|
+
return { amount, preset };
|
|
825
|
+
}
|
|
826
|
+
```
|
|
827
|
+
|
|
828
|
+
### Multi-Chain Preset Settings Editor
|
|
829
|
+
|
|
830
|
+
```tsx
|
|
831
|
+
import { Chain } from "@liberfi.io/types";
|
|
832
|
+
import { MultiChainPresetFormWidget } from "@liberfi.io/ui-trade";
|
|
833
|
+
|
|
834
|
+
function TradeSettings() {
|
|
835
|
+
return (
|
|
836
|
+
<MultiChainPresetFormWidget
|
|
837
|
+
chains={[Chain.SOLANA, Chain.ETHEREUM, Chain.BINANCE]}
|
|
838
|
+
storageKeyPrefix="myapp."
|
|
839
|
+
onChange={(chain, idx, value) =>
|
|
840
|
+
console.log(`chain=${chain}, preset=${idx}`, value)
|
|
841
|
+
}
|
|
665
842
|
/>
|
|
666
843
|
);
|
|
667
844
|
}
|
|
668
845
|
```
|
|
669
846
|
|
|
847
|
+
### Reading Preset Values from Atoms
|
|
848
|
+
|
|
849
|
+
```tsx
|
|
850
|
+
import { Chain } from "@liberfi.io/types";
|
|
851
|
+
import { usePresetValues } from "@liberfi.io/ui-trade";
|
|
852
|
+
|
|
853
|
+
function useCurrentPreset(chain: Chain, index: number) {
|
|
854
|
+
return usePresetValues({ chain, direction: "buy", presetIndex: index });
|
|
855
|
+
}
|
|
856
|
+
```
|
|
857
|
+
|
|
670
858
|
## Future Improvements
|
|
671
859
|
|
|
672
860
|
- Add `useSwapQuote` hook for fetching quotes without executing (read-only route info).
|