@elizaos/plugin-waifu-swap-app 2.0.3-beta.6 → 2.0.3-beta.7
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/dist/SwapAppView.d.ts +12 -0
- package/dist/SwapAppView.d.ts.map +1 -0
- package/dist/SwapAppView.js +357 -0
- package/dist/SwapAppView.js.map +1 -0
- package/dist/SwapSpatialView.d.ts +52 -0
- package/dist/SwapSpatialView.d.ts.map +1 -0
- package/dist/SwapSpatialView.js +107 -0
- package/dist/SwapSpatialView.js.map +1 -0
- package/dist/SwapView.d.ts +30 -0
- package/dist/SwapView.d.ts.map +1 -0
- package/dist/SwapView.js +88 -0
- package/dist/SwapView.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/plugin.d.ts +23 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +24 -0
- package/dist/plugin.js.map +1 -0
- package/dist/register-terminal-view.d.ts +15 -0
- package/dist/register-terminal-view.d.ts.map +1 -0
- package/dist/register-terminal-view.js +32 -0
- package/dist/register-terminal-view.js.map +1 -0
- package/dist/register.d.ts +2 -0
- package/dist/register.d.ts.map +1 -0
- package/dist/register.js +17 -0
- package/dist/register.js.map +1 -0
- package/dist/swap-app-view-bundle.d.ts +3 -0
- package/dist/swap-app-view-bundle.d.ts.map +1 -0
- package/dist/swap-app-view-bundle.js +7 -0
- package/dist/swap-app-view-bundle.js.map +1 -0
- package/dist/swap-app.d.ts +9 -0
- package/dist/swap-app.d.ts.map +1 -0
- package/dist/swap-app.js +18 -0
- package/dist/swap-app.js.map +1 -0
- package/dist/swap-client.d.ts +46 -0
- package/dist/swap-client.d.ts.map +1 -0
- package/dist/swap-client.js +115 -0
- package/dist/swap-client.js.map +1 -0
- package/dist/swap-config.d.ts +65 -0
- package/dist/swap-config.d.ts.map +1 -0
- package/dist/swap-config.js +102 -0
- package/dist/swap-config.js.map +1 -0
- package/dist/swap-contracts.d.ts +173 -0
- package/dist/swap-contracts.d.ts.map +1 -0
- package/dist/swap-contracts.js +97 -0
- package/dist/swap-contracts.js.map +1 -0
- package/dist/ui.d.ts +6 -0
- package/dist/ui.d.ts.map +1 -0
- package/dist/ui.js +14 -0
- package/dist/ui.js.map +1 -0
- package/dist/useSwapState.d.ts +54 -0
- package/dist/useSwapState.d.ts.map +1 -0
- package/dist/useSwapState.js +187 -0
- package/dist/useSwapState.js.map +1 -0
- package/dist/views/bundle.js +817 -0
- package/dist/views/bundle.js.map +1 -0
- package/package.json +6 -6
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { OverlayAppContext } from "@elizaos/app-core";
|
|
2
|
+
import { type SwapToken } from "./swap-contracts";
|
|
3
|
+
export interface SwapAppViewProps extends OverlayAppContext {
|
|
4
|
+
/** Optional host override for which agent's swap capability to invoke. */
|
|
5
|
+
agentTokenAddress?: string;
|
|
6
|
+
/** Optional host-supplied swap-eligible token list. */
|
|
7
|
+
tokens?: readonly SwapToken[];
|
|
8
|
+
/** Raised when the backend reports the capability is unavailable (404). */
|
|
9
|
+
onUnavailable?: () => void;
|
|
10
|
+
}
|
|
11
|
+
export declare function SwapAppView({ exitToApps, agentTokenAddress, tokens: tokensProp, onUnavailable, }: SwapAppViewProps): import("react/jsx-runtime").JSX.Element;
|
|
12
|
+
//# sourceMappingURL=SwapAppView.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SwapAppView.d.ts","sourceRoot":"","sources":["../src/SwapAppView.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAY3D,OAAO,EAIL,KAAK,SAAS,EACf,MAAM,kBAAkB,CAAC;AAuG1B,MAAM,WAAW,gBAAiB,SAAQ,iBAAiB;IACzD,0EAA0E;IAC1E,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,uDAAuD;IACvD,MAAM,CAAC,EAAE,SAAS,SAAS,EAAE,CAAC;IAC9B,2EAA2E;IAC3E,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;CAC5B;AAED,wBAAgB,WAAW,CAAC,EAC1B,UAAU,EACV,iBAAiB,EACjB,MAAM,EAAE,UAAU,EAClB,aAAa,GACd,EAAE,gBAAgB,2CAsSlB"}
|
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Button, PagePanel, Spinner } from "@elizaos/app-core";
|
|
3
|
+
import { useAgentElement } from "@elizaos/ui/agent-surface";
|
|
4
|
+
import {
|
|
5
|
+
ArrowDown,
|
|
6
|
+
ArrowLeft,
|
|
7
|
+
ArrowLeftRight,
|
|
8
|
+
CheckCircle2,
|
|
9
|
+
Info,
|
|
10
|
+
Settings2
|
|
11
|
+
} from "lucide-react";
|
|
12
|
+
import { useId } from "react";
|
|
13
|
+
import {
|
|
14
|
+
PANCAKE_V3_FEE_TIERS,
|
|
15
|
+
SLIPPAGE_PRESETS
|
|
16
|
+
} from "./swap-contracts.js";
|
|
17
|
+
import { useSwapState } from "./useSwapState.js";
|
|
18
|
+
function formatAmount(value, maxFraction = 6) {
|
|
19
|
+
if (!Number.isFinite(value)) return "0";
|
|
20
|
+
return value.toLocaleString("en-US", {
|
|
21
|
+
minimumFractionDigits: 0,
|
|
22
|
+
maximumFractionDigits: value > 1 ? 4 : maxFraction
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
function formatImpact(pct) {
|
|
26
|
+
if (!Number.isFinite(pct)) return "0.00%";
|
|
27
|
+
const sign = pct > 0 ? "+" : "";
|
|
28
|
+
return `${sign}${pct.toFixed(2)}%`;
|
|
29
|
+
}
|
|
30
|
+
function shortAddress(address) {
|
|
31
|
+
return `${address.slice(0, 6)}\u2026${address.slice(-4)}`;
|
|
32
|
+
}
|
|
33
|
+
function TokenChip({ token }) {
|
|
34
|
+
return /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-2 px-1 py-1.5", children: [
|
|
35
|
+
/* @__PURE__ */ jsx("span", { className: "grid h-5 w-5 place-items-center text-[10px] font-semibold text-muted", children: token.symbol.slice(0, 2).toUpperCase() }),
|
|
36
|
+
/* @__PURE__ */ jsx("span", { className: "font-mono text-xs text-txt", children: token.symbol })
|
|
37
|
+
] });
|
|
38
|
+
}
|
|
39
|
+
function TokenSelect({
|
|
40
|
+
label,
|
|
41
|
+
selected,
|
|
42
|
+
tokens,
|
|
43
|
+
exclude,
|
|
44
|
+
disabled,
|
|
45
|
+
onSelect
|
|
46
|
+
}) {
|
|
47
|
+
const selectId = useId();
|
|
48
|
+
const options = tokens.filter(
|
|
49
|
+
(token) => !exclude || token.address !== exclude.address
|
|
50
|
+
);
|
|
51
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
52
|
+
selected ? /* @__PURE__ */ jsx(TokenChip, { token: selected }) : null,
|
|
53
|
+
/* @__PURE__ */ jsx("label", { className: "sr-only", htmlFor: selectId, children: label }),
|
|
54
|
+
/* @__PURE__ */ jsxs(
|
|
55
|
+
"select",
|
|
56
|
+
{
|
|
57
|
+
id: selectId,
|
|
58
|
+
value: selected?.address ?? "",
|
|
59
|
+
disabled: disabled || options.length === 0,
|
|
60
|
+
onChange: (event) => {
|
|
61
|
+
const next = tokens.find(
|
|
62
|
+
(token) => token.address === event.target.value
|
|
63
|
+
);
|
|
64
|
+
if (next) onSelect(next);
|
|
65
|
+
},
|
|
66
|
+
className: "rounded-md border border-border bg-bg-accent px-2 py-1.5 text-xs text-txt outline-none transition-colors focus:border-accent/50 disabled:opacity-60",
|
|
67
|
+
children: [
|
|
68
|
+
selected && !options.some((t) => t.address === selected.address) ? /* @__PURE__ */ jsx("option", { value: selected.address, children: selected.symbol }) : null,
|
|
69
|
+
options.map((token) => /* @__PURE__ */ jsx("option", { value: token.address, children: token.symbol }, token.address))
|
|
70
|
+
]
|
|
71
|
+
}
|
|
72
|
+
)
|
|
73
|
+
] });
|
|
74
|
+
}
|
|
75
|
+
function DetailRow({
|
|
76
|
+
label,
|
|
77
|
+
children,
|
|
78
|
+
tone
|
|
79
|
+
}) {
|
|
80
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3", children: [
|
|
81
|
+
/* @__PURE__ */ jsx("dt", { className: "text-muted", children: label }),
|
|
82
|
+
/* @__PURE__ */ jsx(
|
|
83
|
+
"dd",
|
|
84
|
+
{
|
|
85
|
+
className: `tabular-nums ${tone === "danger" ? "text-danger" : "text-txt"}`,
|
|
86
|
+
children
|
|
87
|
+
}
|
|
88
|
+
)
|
|
89
|
+
] });
|
|
90
|
+
}
|
|
91
|
+
function SwapAppView({
|
|
92
|
+
exitToApps,
|
|
93
|
+
agentTokenAddress,
|
|
94
|
+
tokens: tokensProp,
|
|
95
|
+
onUnavailable
|
|
96
|
+
}) {
|
|
97
|
+
const amountId = useId();
|
|
98
|
+
const {
|
|
99
|
+
config,
|
|
100
|
+
tokens,
|
|
101
|
+
tokenIn,
|
|
102
|
+
tokenOut,
|
|
103
|
+
setTokenIn,
|
|
104
|
+
setTokenOut,
|
|
105
|
+
reverse,
|
|
106
|
+
amountIn,
|
|
107
|
+
setAmountIn,
|
|
108
|
+
slippagePct,
|
|
109
|
+
setSlippagePct,
|
|
110
|
+
fee,
|
|
111
|
+
setFee,
|
|
112
|
+
quote,
|
|
113
|
+
amountValid,
|
|
114
|
+
canSwap,
|
|
115
|
+
executeEnabled,
|
|
116
|
+
quoting,
|
|
117
|
+
executing,
|
|
118
|
+
error,
|
|
119
|
+
outcome,
|
|
120
|
+
executeSwap
|
|
121
|
+
} = useSwapState({ agentTokenAddress, tokens: tokensProp, onUnavailable });
|
|
122
|
+
const backButton = useAgentElement({
|
|
123
|
+
id: "action-back",
|
|
124
|
+
role: "button",
|
|
125
|
+
label: "Back to apps",
|
|
126
|
+
group: "swap-header",
|
|
127
|
+
description: "Exit the swap view and return to the apps overlay"
|
|
128
|
+
});
|
|
129
|
+
const reverseButton = useAgentElement({
|
|
130
|
+
id: "action-reverse",
|
|
131
|
+
role: "button",
|
|
132
|
+
label: "Reverse direction",
|
|
133
|
+
group: "swap-form",
|
|
134
|
+
description: "Swap the token-in and token-out sides"
|
|
135
|
+
});
|
|
136
|
+
const swapButton = useAgentElement({
|
|
137
|
+
id: "action-swap",
|
|
138
|
+
role: "button",
|
|
139
|
+
label: "Swap",
|
|
140
|
+
group: "swap-form",
|
|
141
|
+
description: "Execute the swap with the current quote",
|
|
142
|
+
status: executing ? "active" : "inactive"
|
|
143
|
+
});
|
|
144
|
+
const amountField = useAgentElement({
|
|
145
|
+
id: "field-amount",
|
|
146
|
+
role: "number-input",
|
|
147
|
+
label: "Amount in",
|
|
148
|
+
group: "swap-form",
|
|
149
|
+
description: "Amount of the input token to swap"
|
|
150
|
+
});
|
|
151
|
+
const impactDanger = (quote?.priceImpactPct ?? 0) < -1;
|
|
152
|
+
return /* @__PURE__ */ jsxs(
|
|
153
|
+
"div",
|
|
154
|
+
{
|
|
155
|
+
"data-testid": "swap-shell",
|
|
156
|
+
className: "fixed inset-0 z-50 flex h-[100vh] flex-col overflow-hidden bg-bg supports-[height:100dvh]:h-[100dvh]",
|
|
157
|
+
children: [
|
|
158
|
+
/* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-3 px-3 py-2", children: [
|
|
159
|
+
/* @__PURE__ */ jsx(
|
|
160
|
+
Button,
|
|
161
|
+
{
|
|
162
|
+
ref: backButton.ref,
|
|
163
|
+
...backButton.agentProps,
|
|
164
|
+
variant: "ghost",
|
|
165
|
+
size: "icon",
|
|
166
|
+
className: "h-9 w-9 text-muted hover:text-txt",
|
|
167
|
+
onClick: exitToApps,
|
|
168
|
+
"aria-label": "Back",
|
|
169
|
+
children: /* @__PURE__ */ jsx(ArrowLeft, { className: "h-4 w-4" })
|
|
170
|
+
}
|
|
171
|
+
),
|
|
172
|
+
/* @__PURE__ */ jsx("div", { className: "min-w-0", children: /* @__PURE__ */ jsx("h1", { className: "text-base font-semibold text-txt", children: "Swap" }) }),
|
|
173
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1" }),
|
|
174
|
+
/* @__PURE__ */ jsx("span", { className: "inline-flex items-center gap-1.5 px-1 py-0.5 text-[10px] font-semibold uppercase tracking-[0.12em] text-muted", children: "PancakeSwap v3" })
|
|
175
|
+
] }),
|
|
176
|
+
/* @__PURE__ */ jsx("div", { className: "chat-native-scrollbar flex-1 overflow-y-auto px-3 py-2 sm:px-5", children: /* @__PURE__ */ jsxs("div", { className: "mx-auto max-w-xl space-y-3", children: [
|
|
177
|
+
!config.agentTokenAddress && /* @__PURE__ */ jsx(PagePanel.Notice, { tone: "warning", children: "Unavailable" }),
|
|
178
|
+
/* @__PURE__ */ jsxs("section", { className: "py-2", children: [
|
|
179
|
+
/* @__PURE__ */ jsx("div", { className: "mb-2 flex items-center justify-between text-[11px] font-semibold uppercase tracking-[0.12em] text-muted", children: /* @__PURE__ */ jsx("span", { children: "from" }) }),
|
|
180
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
181
|
+
/* @__PURE__ */ jsx(
|
|
182
|
+
TokenSelect,
|
|
183
|
+
{
|
|
184
|
+
label: "From token",
|
|
185
|
+
selected: tokenIn,
|
|
186
|
+
tokens,
|
|
187
|
+
exclude: tokenOut,
|
|
188
|
+
disabled: executing,
|
|
189
|
+
onSelect: setTokenIn
|
|
190
|
+
}
|
|
191
|
+
),
|
|
192
|
+
/* @__PURE__ */ jsx(
|
|
193
|
+
"input",
|
|
194
|
+
{
|
|
195
|
+
ref: amountField.ref,
|
|
196
|
+
...amountField.agentProps,
|
|
197
|
+
id: amountId,
|
|
198
|
+
value: amountIn,
|
|
199
|
+
inputMode: "decimal",
|
|
200
|
+
placeholder: "0.0",
|
|
201
|
+
disabled: executing,
|
|
202
|
+
onChange: (event) => setAmountIn(event.target.value),
|
|
203
|
+
className: "ml-auto w-full bg-transparent text-right font-mono text-2xl text-txt tabular-nums outline-none placeholder:text-muted disabled:opacity-60",
|
|
204
|
+
"aria-label": "Amount in"
|
|
205
|
+
}
|
|
206
|
+
)
|
|
207
|
+
] })
|
|
208
|
+
] }),
|
|
209
|
+
/* @__PURE__ */ jsx("div", { className: "-my-2 flex justify-center", children: /* @__PURE__ */ jsx(
|
|
210
|
+
Button,
|
|
211
|
+
{
|
|
212
|
+
ref: reverseButton.ref,
|
|
213
|
+
...reverseButton.agentProps,
|
|
214
|
+
variant: "ghost",
|
|
215
|
+
size: "icon",
|
|
216
|
+
className: "h-9 w-9 text-muted hover:text-accent",
|
|
217
|
+
onClick: reverse,
|
|
218
|
+
disabled: executing,
|
|
219
|
+
"aria-label": "Reverse direction",
|
|
220
|
+
children: /* @__PURE__ */ jsx(ArrowDown, { className: "h-4 w-4" })
|
|
221
|
+
}
|
|
222
|
+
) }),
|
|
223
|
+
/* @__PURE__ */ jsxs("section", { className: "py-2", children: [
|
|
224
|
+
/* @__PURE__ */ jsxs("div", { className: "mb-2 flex items-center justify-between text-[11px] font-semibold uppercase tracking-[0.12em] text-muted", children: [
|
|
225
|
+
/* @__PURE__ */ jsx("span", { children: "to (estimate)" }),
|
|
226
|
+
quoting ? /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1.5 normal-case text-[10px] tracking-normal", children: [
|
|
227
|
+
/* @__PURE__ */ jsx(Spinner, { className: "h-3 w-3" }),
|
|
228
|
+
"quoting"
|
|
229
|
+
] }) : quote ? /* @__PURE__ */ jsx("span", { className: "normal-case text-[10px] tracking-normal", children: quote.source === "backend" ? "live quote" : "estimated" }) : null
|
|
230
|
+
] }),
|
|
231
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
232
|
+
/* @__PURE__ */ jsx(
|
|
233
|
+
TokenSelect,
|
|
234
|
+
{
|
|
235
|
+
label: "To token",
|
|
236
|
+
selected: tokenOut,
|
|
237
|
+
tokens,
|
|
238
|
+
exclude: tokenIn,
|
|
239
|
+
disabled: executing,
|
|
240
|
+
onSelect: setTokenOut
|
|
241
|
+
}
|
|
242
|
+
),
|
|
243
|
+
/* @__PURE__ */ jsx("div", { className: "ml-auto font-mono text-2xl text-txt/85 tabular-nums", children: quote ? formatAmount(quote.amountOut) : "0.0" })
|
|
244
|
+
] })
|
|
245
|
+
] }),
|
|
246
|
+
/* @__PURE__ */ jsxs("section", { className: "py-2", children: [
|
|
247
|
+
/* @__PURE__ */ jsxs("div", { className: "mb-2 flex items-center gap-2 text-[11px] font-semibold uppercase tracking-[0.12em] text-muted", children: [
|
|
248
|
+
/* @__PURE__ */ jsx(Settings2, { className: "h-3.5 w-3.5" }),
|
|
249
|
+
"slippage tolerance"
|
|
250
|
+
] }),
|
|
251
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1.5", children: SLIPPAGE_PRESETS.map((preset) => /* @__PURE__ */ jsxs(
|
|
252
|
+
Button,
|
|
253
|
+
{
|
|
254
|
+
type: "button",
|
|
255
|
+
variant: preset === slippagePct ? "secondary" : "ghost",
|
|
256
|
+
size: "sm",
|
|
257
|
+
className: "h-7 px-2 font-mono text-xs tabular-nums",
|
|
258
|
+
disabled: executing,
|
|
259
|
+
onClick: () => setSlippagePct(preset),
|
|
260
|
+
"aria-pressed": preset === slippagePct,
|
|
261
|
+
children: [
|
|
262
|
+
preset,
|
|
263
|
+
"%"
|
|
264
|
+
]
|
|
265
|
+
},
|
|
266
|
+
preset
|
|
267
|
+
)) }),
|
|
268
|
+
/* @__PURE__ */ jsx("div", { className: "mt-3 mb-2 text-[11px] font-semibold uppercase tracking-[0.12em] text-muted", children: "fee tier" }),
|
|
269
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1.5", children: PANCAKE_V3_FEE_TIERS.map((tier) => /* @__PURE__ */ jsxs(
|
|
270
|
+
Button,
|
|
271
|
+
{
|
|
272
|
+
type: "button",
|
|
273
|
+
variant: tier === fee ? "secondary" : "ghost",
|
|
274
|
+
size: "sm",
|
|
275
|
+
className: "h-7 px-2 font-mono text-xs tabular-nums",
|
|
276
|
+
disabled: executing,
|
|
277
|
+
onClick: () => setFee(tier),
|
|
278
|
+
"aria-pressed": tier === fee,
|
|
279
|
+
children: [
|
|
280
|
+
(tier / 1e4).toFixed(2),
|
|
281
|
+
"%"
|
|
282
|
+
]
|
|
283
|
+
},
|
|
284
|
+
tier
|
|
285
|
+
)) })
|
|
286
|
+
] }),
|
|
287
|
+
quote && amountValid ? /* @__PURE__ */ jsxs("dl", { className: "space-y-2 px-1 py-2 text-xs", children: [
|
|
288
|
+
/* @__PURE__ */ jsx(DetailRow, { label: "route", children: /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1.5", children: [
|
|
289
|
+
/* @__PURE__ */ jsx(ArrowLeftRight, { className: "h-3.5 w-3.5 text-muted" }),
|
|
290
|
+
"via PancakeSwap v3"
|
|
291
|
+
] }) }),
|
|
292
|
+
/* @__PURE__ */ jsx(
|
|
293
|
+
DetailRow,
|
|
294
|
+
{
|
|
295
|
+
label: "price impact",
|
|
296
|
+
tone: impactDanger ? "danger" : "default",
|
|
297
|
+
children: formatImpact(quote.priceImpactPct)
|
|
298
|
+
}
|
|
299
|
+
),
|
|
300
|
+
/* @__PURE__ */ jsxs(DetailRow, { label: "slippage", children: [
|
|
301
|
+
quote.slippagePct,
|
|
302
|
+
"%"
|
|
303
|
+
] }),
|
|
304
|
+
/* @__PURE__ */ jsxs(DetailRow, { label: "minimum received", children: [
|
|
305
|
+
formatAmount(quote.minAmountOut),
|
|
306
|
+
" ",
|
|
307
|
+
tokenOut?.symbol ?? ""
|
|
308
|
+
] })
|
|
309
|
+
] }) : null,
|
|
310
|
+
error && /* @__PURE__ */ jsx(
|
|
311
|
+
PagePanel.Notice,
|
|
312
|
+
{
|
|
313
|
+
tone: error.kind === "auth" ? "accent" : "danger",
|
|
314
|
+
children: error.message
|
|
315
|
+
}
|
|
316
|
+
),
|
|
317
|
+
outcome?.kind === "stubbed" && /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2 px-1 py-2 text-sm text-muted", children: [
|
|
318
|
+
/* @__PURE__ */ jsx(Info, { className: "mt-0.5 h-4 w-4 shrink-0" }),
|
|
319
|
+
/* @__PURE__ */ jsx("span", { children: outcome.message })
|
|
320
|
+
] }),
|
|
321
|
+
outcome?.kind === "prepared" && /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2 px-1 py-2 text-sm text-ok", children: [
|
|
322
|
+
/* @__PURE__ */ jsx(CheckCircle2, { className: "mt-0.5 h-4 w-4 shrink-0" }),
|
|
323
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
324
|
+
"transaction prepared for ",
|
|
325
|
+
shortAddress(outcome.to),
|
|
326
|
+
" \u2014 sign in your wallet to complete"
|
|
327
|
+
] })
|
|
328
|
+
] }),
|
|
329
|
+
/* @__PURE__ */ jsx(
|
|
330
|
+
Button,
|
|
331
|
+
{
|
|
332
|
+
ref: swapButton.ref,
|
|
333
|
+
...swapButton.agentProps,
|
|
334
|
+
type: "button",
|
|
335
|
+
variant: "default",
|
|
336
|
+
className: "w-full gap-2",
|
|
337
|
+
disabled: !canSwap,
|
|
338
|
+
onClick: () => void executeSwap(),
|
|
339
|
+
children: executing ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
340
|
+
/* @__PURE__ */ jsx(Spinner, { className: "h-4 w-4" }),
|
|
341
|
+
"preparing swap"
|
|
342
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
343
|
+
/* @__PURE__ */ jsx(ArrowLeftRight, { className: "h-4 w-4" }),
|
|
344
|
+
executeEnabled ? "swap" : "preview swap"
|
|
345
|
+
] })
|
|
346
|
+
}
|
|
347
|
+
),
|
|
348
|
+
!executeEnabled && /* @__PURE__ */ jsx("p", { className: "sr-only", children: "quote-only preview \u2014 on-chain execution lands when the agent signer is enabled" })
|
|
349
|
+
] }) })
|
|
350
|
+
]
|
|
351
|
+
}
|
|
352
|
+
);
|
|
353
|
+
}
|
|
354
|
+
export {
|
|
355
|
+
SwapAppView
|
|
356
|
+
};
|
|
357
|
+
//# sourceMappingURL=SwapAppView.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/SwapAppView.tsx"],"sourcesContent":["import type { OverlayAppContext } from \"@elizaos/app-core\";\nimport { Button, PagePanel, Spinner } from \"@elizaos/app-core\";\nimport { useAgentElement } from \"@elizaos/ui/agent-surface\";\nimport {\n ArrowDown,\n ArrowLeft,\n ArrowLeftRight,\n CheckCircle2,\n Info,\n Settings2,\n} from \"lucide-react\";\nimport { type ReactNode, useId } from \"react\";\nimport {\n PANCAKE_V3_FEE_TIERS,\n type PancakeV3Fee,\n SLIPPAGE_PRESETS,\n type SwapToken,\n} from \"./swap-contracts.js\";\nimport { useSwapState } from \"./useSwapState.js\";\n\nfunction formatAmount(value: number, maxFraction = 6): string {\n if (!Number.isFinite(value)) return \"0\";\n return value.toLocaleString(\"en-US\", {\n minimumFractionDigits: 0,\n maximumFractionDigits: value > 1 ? 4 : maxFraction,\n });\n}\n\nfunction formatImpact(pct: number): string {\n if (!Number.isFinite(pct)) return \"0.00%\";\n const sign = pct > 0 ? \"+\" : \"\";\n return `${sign}${pct.toFixed(2)}%`;\n}\n\nfunction shortAddress(address: string): string {\n return `${address.slice(0, 6)}…${address.slice(-4)}`;\n}\n\nfunction TokenChip({ token }: { token: SwapToken }) {\n return (\n <span className=\"inline-flex items-center gap-2 px-1 py-1.5\">\n <span className=\"grid h-5 w-5 place-items-center text-[10px] font-semibold text-muted\">\n {token.symbol.slice(0, 2).toUpperCase()}\n </span>\n <span className=\"font-mono text-xs text-txt\">{token.symbol}</span>\n </span>\n );\n}\n\nfunction TokenSelect({\n label,\n selected,\n tokens,\n exclude,\n disabled,\n onSelect,\n}: {\n label: string;\n selected: SwapToken | null;\n tokens: readonly SwapToken[];\n exclude: SwapToken | null;\n disabled: boolean;\n onSelect: (token: SwapToken) => void;\n}) {\n const selectId = useId();\n const options = tokens.filter(\n (token) => !exclude || token.address !== exclude.address,\n );\n return (\n <div className=\"flex items-center gap-2\">\n {selected ? <TokenChip token={selected} /> : null}\n <label className=\"sr-only\" htmlFor={selectId}>\n {label}\n </label>\n <select\n id={selectId}\n value={selected?.address ?? \"\"}\n disabled={disabled || options.length === 0}\n onChange={(event) => {\n const next = tokens.find(\n (token) => token.address === event.target.value,\n );\n if (next) onSelect(next);\n }}\n className=\"rounded-md border border-border bg-bg-accent px-2 py-1.5 text-xs text-txt outline-none transition-colors focus:border-accent/50 disabled:opacity-60\"\n >\n {selected && !options.some((t) => t.address === selected.address) ? (\n <option value={selected.address}>{selected.symbol}</option>\n ) : null}\n {options.map((token) => (\n <option key={token.address} value={token.address}>\n {token.symbol}\n </option>\n ))}\n </select>\n </div>\n );\n}\n\nfunction DetailRow({\n label,\n children,\n tone,\n}: {\n label: string;\n children: ReactNode;\n tone?: \"default\" | \"danger\";\n}) {\n return (\n <div className=\"flex items-center justify-between gap-3\">\n <dt className=\"text-muted\">{label}</dt>\n <dd\n className={`tabular-nums ${tone === \"danger\" ? \"text-danger\" : \"text-txt\"}`}\n >\n {children}\n </dd>\n </div>\n );\n}\n\nexport interface SwapAppViewProps extends OverlayAppContext {\n /** Optional host override for which agent's swap capability to invoke. */\n agentTokenAddress?: string;\n /** Optional host-supplied swap-eligible token list. */\n tokens?: readonly SwapToken[];\n /** Raised when the backend reports the capability is unavailable (404). */\n onUnavailable?: () => void;\n}\n\nexport function SwapAppView({\n exitToApps,\n agentTokenAddress,\n tokens: tokensProp,\n onUnavailable,\n}: SwapAppViewProps) {\n const amountId = useId();\n const {\n config,\n tokens,\n tokenIn,\n tokenOut,\n setTokenIn,\n setTokenOut,\n reverse,\n amountIn,\n setAmountIn,\n slippagePct,\n setSlippagePct,\n fee,\n setFee,\n quote,\n amountValid,\n canSwap,\n executeEnabled,\n quoting,\n executing,\n error,\n outcome,\n executeSwap,\n } = useSwapState({ agentTokenAddress, tokens: tokensProp, onUnavailable });\n\n const backButton = useAgentElement<HTMLButtonElement>({\n id: \"action-back\",\n role: \"button\",\n label: \"Back to apps\",\n group: \"swap-header\",\n description: \"Exit the swap view and return to the apps overlay\",\n });\n const reverseButton = useAgentElement<HTMLButtonElement>({\n id: \"action-reverse\",\n role: \"button\",\n label: \"Reverse direction\",\n group: \"swap-form\",\n description: \"Swap the token-in and token-out sides\",\n });\n const swapButton = useAgentElement<HTMLButtonElement>({\n id: \"action-swap\",\n role: \"button\",\n label: \"Swap\",\n group: \"swap-form\",\n description: \"Execute the swap with the current quote\",\n status: executing ? \"active\" : \"inactive\",\n });\n const amountField = useAgentElement<HTMLInputElement>({\n id: \"field-amount\",\n role: \"number-input\",\n label: \"Amount in\",\n group: \"swap-form\",\n description: \"Amount of the input token to swap\",\n });\n\n const impactDanger = (quote?.priceImpactPct ?? 0) < -1;\n\n return (\n <div\n data-testid=\"swap-shell\"\n className=\"fixed inset-0 z-50 flex h-[100vh] flex-col overflow-hidden bg-bg supports-[height:100dvh]:h-[100dvh]\"\n >\n <div className=\"flex shrink-0 items-center gap-3 px-3 py-2\">\n <Button\n ref={backButton.ref}\n {...backButton.agentProps}\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-9 w-9 text-muted hover:text-txt\"\n onClick={exitToApps}\n aria-label=\"Back\"\n >\n <ArrowLeft className=\"h-4 w-4\" />\n </Button>\n\n <div className=\"min-w-0\">\n <h1 className=\"text-base font-semibold text-txt\">Swap</h1>\n </div>\n\n <div className=\"flex-1\" />\n\n <span className=\"inline-flex items-center gap-1.5 px-1 py-0.5 text-[10px] font-semibold uppercase tracking-[0.12em] text-muted\">\n PancakeSwap v3\n </span>\n </div>\n\n <div className=\"chat-native-scrollbar flex-1 overflow-y-auto px-3 py-2 sm:px-5\">\n <div className=\"mx-auto max-w-xl space-y-3\">\n {!config.agentTokenAddress && (\n <PagePanel.Notice tone=\"warning\">Unavailable</PagePanel.Notice>\n )}\n\n {/* From */}\n <section className=\"py-2\">\n <div className=\"mb-2 flex items-center justify-between text-[11px] font-semibold uppercase tracking-[0.12em] text-muted\">\n <span>from</span>\n </div>\n <div className=\"flex items-center gap-3\">\n <TokenSelect\n label=\"From token\"\n selected={tokenIn}\n tokens={tokens}\n exclude={tokenOut}\n disabled={executing}\n onSelect={setTokenIn}\n />\n <input\n ref={amountField.ref}\n {...amountField.agentProps}\n id={amountId}\n value={amountIn}\n inputMode=\"decimal\"\n placeholder=\"0.0\"\n disabled={executing}\n onChange={(event) => setAmountIn(event.target.value)}\n className=\"ml-auto w-full bg-transparent text-right font-mono text-2xl text-txt tabular-nums outline-none placeholder:text-muted disabled:opacity-60\"\n aria-label=\"Amount in\"\n />\n </div>\n </section>\n\n {/* Direction */}\n <div className=\"-my-2 flex justify-center\">\n <Button\n ref={reverseButton.ref}\n {...reverseButton.agentProps}\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-9 w-9 text-muted hover:text-accent\"\n onClick={reverse}\n disabled={executing}\n aria-label=\"Reverse direction\"\n >\n <ArrowDown className=\"h-4 w-4\" />\n </Button>\n </div>\n\n {/* To */}\n <section className=\"py-2\">\n <div className=\"mb-2 flex items-center justify-between text-[11px] font-semibold uppercase tracking-[0.12em] text-muted\">\n <span>to (estimate)</span>\n {quoting ? (\n <span className=\"inline-flex items-center gap-1.5 normal-case text-[10px] tracking-normal\">\n <Spinner className=\"h-3 w-3\" />\n quoting\n </span>\n ) : quote ? (\n <span className=\"normal-case text-[10px] tracking-normal\">\n {quote.source === \"backend\" ? \"live quote\" : \"estimated\"}\n </span>\n ) : null}\n </div>\n <div className=\"flex items-center gap-3\">\n <TokenSelect\n label=\"To token\"\n selected={tokenOut}\n tokens={tokens}\n exclude={tokenIn}\n disabled={executing}\n onSelect={setTokenOut}\n />\n <div className=\"ml-auto font-mono text-2xl text-txt/85 tabular-nums\">\n {quote ? formatAmount(quote.amountOut) : \"0.0\"}\n </div>\n </div>\n </section>\n\n {/* Slippage + fee controls */}\n <section className=\"py-2\">\n <div className=\"mb-2 flex items-center gap-2 text-[11px] font-semibold uppercase tracking-[0.12em] text-muted\">\n <Settings2 className=\"h-3.5 w-3.5\" />\n slippage tolerance\n </div>\n <div className=\"flex flex-wrap gap-1.5\">\n {SLIPPAGE_PRESETS.map((preset) => (\n <Button\n key={preset}\n type=\"button\"\n variant={preset === slippagePct ? \"secondary\" : \"ghost\"}\n size=\"sm\"\n className=\"h-7 px-2 font-mono text-xs tabular-nums\"\n disabled={executing}\n onClick={() => setSlippagePct(preset)}\n aria-pressed={preset === slippagePct}\n >\n {preset}%\n </Button>\n ))}\n </div>\n\n <div className=\"mt-3 mb-2 text-[11px] font-semibold uppercase tracking-[0.12em] text-muted\">\n fee tier\n </div>\n <div className=\"flex flex-wrap gap-1.5\">\n {PANCAKE_V3_FEE_TIERS.map((tier: PancakeV3Fee) => (\n <Button\n key={tier}\n type=\"button\"\n variant={tier === fee ? \"secondary\" : \"ghost\"}\n size=\"sm\"\n className=\"h-7 px-2 font-mono text-xs tabular-nums\"\n disabled={executing}\n onClick={() => setFee(tier)}\n aria-pressed={tier === fee}\n >\n {(tier / 10000).toFixed(2)}%\n </Button>\n ))}\n </div>\n </section>\n\n {/* Route detail */}\n {quote && amountValid ? (\n <dl className=\"space-y-2 px-1 py-2 text-xs\">\n <DetailRow label=\"route\">\n <span className=\"inline-flex items-center gap-1.5\">\n <ArrowLeftRight className=\"h-3.5 w-3.5 text-muted\" />\n via PancakeSwap v3\n </span>\n </DetailRow>\n <DetailRow\n label=\"price impact\"\n tone={impactDanger ? \"danger\" : \"default\"}\n >\n {formatImpact(quote.priceImpactPct)}\n </DetailRow>\n <DetailRow label=\"slippage\">{quote.slippagePct}%</DetailRow>\n <DetailRow label=\"minimum received\">\n {formatAmount(quote.minAmountOut)} {tokenOut?.symbol ?? \"\"}\n </DetailRow>\n </dl>\n ) : null}\n\n {/* Errors */}\n {error && (\n <PagePanel.Notice\n tone={error.kind === \"auth\" ? \"accent\" : \"danger\"}\n >\n {error.message}\n </PagePanel.Notice>\n )}\n\n {/* Outcome */}\n {outcome?.kind === \"stubbed\" && (\n <div className=\"flex items-start gap-2 px-1 py-2 text-sm text-muted\">\n <Info className=\"mt-0.5 h-4 w-4 shrink-0\" />\n <span>{outcome.message}</span>\n </div>\n )}\n {outcome?.kind === \"prepared\" && (\n <div className=\"flex items-start gap-2 px-1 py-2 text-sm text-ok\">\n <CheckCircle2 className=\"mt-0.5 h-4 w-4 shrink-0\" />\n <span>\n transaction prepared for {shortAddress(outcome.to)} — sign in\n your wallet to complete\n </span>\n </div>\n )}\n\n {/* Swap CTA */}\n <Button\n ref={swapButton.ref}\n {...swapButton.agentProps}\n type=\"button\"\n variant=\"default\"\n className=\"w-full gap-2\"\n disabled={!canSwap}\n onClick={() => void executeSwap()}\n >\n {executing ? (\n <>\n <Spinner className=\"h-4 w-4\" />\n preparing swap\n </>\n ) : (\n <>\n <ArrowLeftRight className=\"h-4 w-4\" />\n {executeEnabled ? \"swap\" : \"preview swap\"}\n </>\n )}\n </Button>\n\n {!executeEnabled && (\n <p className=\"sr-only\">\n quote-only preview — on-chain execution lands when the agent\n signer is enabled\n </p>\n )}\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":"AAwCI,SA8WU,UA7WR,KADF;AAvCJ,SAAS,QAAQ,WAAW,eAAe;AAC3C,SAAS,uBAAuB;AAChC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAyB,aAAa;AACtC;AAAA,EACE;AAAA,EAEA;AAAA,OAEK;AACP,SAAS,oBAAoB;AAE7B,SAAS,aAAa,OAAe,cAAc,GAAW;AAC5D,MAAI,CAAC,OAAO,SAAS,KAAK,EAAG,QAAO;AACpC,SAAO,MAAM,eAAe,SAAS;AAAA,IACnC,uBAAuB;AAAA,IACvB,uBAAuB,QAAQ,IAAI,IAAI;AAAA,EACzC,CAAC;AACH;AAEA,SAAS,aAAa,KAAqB;AACzC,MAAI,CAAC,OAAO,SAAS,GAAG,EAAG,QAAO;AAClC,QAAM,OAAO,MAAM,IAAI,MAAM;AAC7B,SAAO,GAAG,IAAI,GAAG,IAAI,QAAQ,CAAC,CAAC;AACjC;AAEA,SAAS,aAAa,SAAyB;AAC7C,SAAO,GAAG,QAAQ,MAAM,GAAG,CAAC,CAAC,SAAI,QAAQ,MAAM,EAAE,CAAC;AACpD;AAEA,SAAS,UAAU,EAAE,MAAM,GAAyB;AAClD,SACE,qBAAC,UAAK,WAAU,8CACd;AAAA,wBAAC,UAAK,WAAU,wEACb,gBAAM,OAAO,MAAM,GAAG,CAAC,EAAE,YAAY,GACxC;AAAA,IACA,oBAAC,UAAK,WAAU,8BAA8B,gBAAM,QAAO;AAAA,KAC7D;AAEJ;AAEA,SAAS,YAAY;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAOG;AACD,QAAM,WAAW,MAAM;AACvB,QAAM,UAAU,OAAO;AAAA,IACrB,CAAC,UAAU,CAAC,WAAW,MAAM,YAAY,QAAQ;AAAA,EACnD;AACA,SACE,qBAAC,SAAI,WAAU,2BACZ;AAAA,eAAW,oBAAC,aAAU,OAAO,UAAU,IAAK;AAAA,IAC7C,oBAAC,WAAM,WAAU,WAAU,SAAS,UACjC,iBACH;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,IAAI;AAAA,QACJ,OAAO,UAAU,WAAW;AAAA,QAC5B,UAAU,YAAY,QAAQ,WAAW;AAAA,QACzC,UAAU,CAAC,UAAU;AACnB,gBAAM,OAAO,OAAO;AAAA,YAClB,CAAC,UAAU,MAAM,YAAY,MAAM,OAAO;AAAA,UAC5C;AACA,cAAI,KAAM,UAAS,IAAI;AAAA,QACzB;AAAA,QACA,WAAU;AAAA,QAET;AAAA,sBAAY,CAAC,QAAQ,KAAK,CAAC,MAAM,EAAE,YAAY,SAAS,OAAO,IAC9D,oBAAC,YAAO,OAAO,SAAS,SAAU,mBAAS,QAAO,IAChD;AAAA,UACH,QAAQ,IAAI,CAAC,UACZ,oBAAC,YAA2B,OAAO,MAAM,SACtC,gBAAM,UADI,MAAM,OAEnB,CACD;AAAA;AAAA;AAAA,IACH;AAAA,KACF;AAEJ;AAEA,SAAS,UAAU;AAAA,EACjB;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,SACE,qBAAC,SAAI,WAAU,2CACb;AAAA,wBAAC,QAAG,WAAU,cAAc,iBAAM;AAAA,IAClC;AAAA,MAAC;AAAA;AAAA,QACC,WAAW,gBAAgB,SAAS,WAAW,gBAAgB,UAAU;AAAA,QAExE;AAAA;AAAA,IACH;AAAA,KACF;AAEJ;AAWO,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA;AAAA,EACA,QAAQ;AAAA,EACR;AACF,GAAqB;AACnB,QAAM,WAAW,MAAM;AACvB,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,aAAa,EAAE,mBAAmB,QAAQ,YAAY,cAAc,CAAC;AAEzE,QAAM,aAAa,gBAAmC;AAAA,IACpD,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,OAAO;AAAA,IACP,OAAO;AAAA,IACP,aAAa;AAAA,EACf,CAAC;AACD,QAAM,gBAAgB,gBAAmC;AAAA,IACvD,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,OAAO;AAAA,IACP,OAAO;AAAA,IACP,aAAa;AAAA,EACf,CAAC;AACD,QAAM,aAAa,gBAAmC;AAAA,IACpD,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,OAAO;AAAA,IACP,OAAO;AAAA,IACP,aAAa;AAAA,IACb,QAAQ,YAAY,WAAW;AAAA,EACjC,CAAC;AACD,QAAM,cAAc,gBAAkC;AAAA,IACpD,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,OAAO;AAAA,IACP,OAAO;AAAA,IACP,aAAa;AAAA,EACf,CAAC;AAED,QAAM,gBAAgB,OAAO,kBAAkB,KAAK;AAEpD,SACE;AAAA,IAAC;AAAA;AAAA,MACC,eAAY;AAAA,MACZ,WAAU;AAAA,MAEV;AAAA,6BAAC,SAAI,WAAU,8CACb;AAAA;AAAA,YAAC;AAAA;AAAA,cACC,KAAK,WAAW;AAAA,cACf,GAAG,WAAW;AAAA,cACf,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,WAAU;AAAA,cACV,SAAS;AAAA,cACT,cAAW;AAAA,cAEX,8BAAC,aAAU,WAAU,WAAU;AAAA;AAAA,UACjC;AAAA,UAEA,oBAAC,SAAI,WAAU,WACb,8BAAC,QAAG,WAAU,oCAAmC,kBAAI,GACvD;AAAA,UAEA,oBAAC,SAAI,WAAU,UAAS;AAAA,UAExB,oBAAC,UAAK,WAAU,iHAAgH,4BAEhI;AAAA,WACF;AAAA,QAEA,oBAAC,SAAI,WAAU,kEACb,+BAAC,SAAI,WAAU,8BACZ;AAAA,WAAC,OAAO,qBACP,oBAAC,UAAU,QAAV,EAAiB,MAAK,WAAU,yBAAW;AAAA,UAI9C,qBAAC,aAAQ,WAAU,QACjB;AAAA,gCAAC,SAAI,WAAU,2GACb,8BAAC,UAAK,kBAAI,GACZ;AAAA,YACA,qBAAC,SAAI,WAAU,2BACb;AAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,OAAM;AAAA,kBACN,UAAU;AAAA,kBACV;AAAA,kBACA,SAAS;AAAA,kBACT,UAAU;AAAA,kBACV,UAAU;AAAA;AAAA,cACZ;AAAA,cACA;AAAA,gBAAC;AAAA;AAAA,kBACC,KAAK,YAAY;AAAA,kBAChB,GAAG,YAAY;AAAA,kBAChB,IAAI;AAAA,kBACJ,OAAO;AAAA,kBACP,WAAU;AAAA,kBACV,aAAY;AAAA,kBACZ,UAAU;AAAA,kBACV,UAAU,CAAC,UAAU,YAAY,MAAM,OAAO,KAAK;AAAA,kBACnD,WAAU;AAAA,kBACV,cAAW;AAAA;AAAA,cACb;AAAA,eACF;AAAA,aACF;AAAA,UAGA,oBAAC,SAAI,WAAU,6BACb;AAAA,YAAC;AAAA;AAAA,cACC,KAAK,cAAc;AAAA,cAClB,GAAG,cAAc;AAAA,cAClB,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,WAAU;AAAA,cACV,SAAS;AAAA,cACT,UAAU;AAAA,cACV,cAAW;AAAA,cAEX,8BAAC,aAAU,WAAU,WAAU;AAAA;AAAA,UACjC,GACF;AAAA,UAGA,qBAAC,aAAQ,WAAU,QACjB;AAAA,iCAAC,SAAI,WAAU,2GACb;AAAA,kCAAC,UAAK,2BAAa;AAAA,cAClB,UACC,qBAAC,UAAK,WAAU,4EACd;AAAA,oCAAC,WAAQ,WAAU,WAAU;AAAA,gBAAE;AAAA,iBAEjC,IACE,QACF,oBAAC,UAAK,WAAU,2CACb,gBAAM,WAAW,YAAY,eAAe,aAC/C,IACE;AAAA,eACN;AAAA,YACA,qBAAC,SAAI,WAAU,2BACb;AAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,OAAM;AAAA,kBACN,UAAU;AAAA,kBACV;AAAA,kBACA,SAAS;AAAA,kBACT,UAAU;AAAA,kBACV,UAAU;AAAA;AAAA,cACZ;AAAA,cACA,oBAAC,SAAI,WAAU,uDACZ,kBAAQ,aAAa,MAAM,SAAS,IAAI,OAC3C;AAAA,eACF;AAAA,aACF;AAAA,UAGA,qBAAC,aAAQ,WAAU,QACjB;AAAA,iCAAC,SAAI,WAAU,iGACb;AAAA,kCAAC,aAAU,WAAU,eAAc;AAAA,cAAE;AAAA,eAEvC;AAAA,YACA,oBAAC,SAAI,WAAU,0BACZ,2BAAiB,IAAI,CAAC,WACrB;AAAA,cAAC;AAAA;AAAA,gBAEC,MAAK;AAAA,gBACL,SAAS,WAAW,cAAc,cAAc;AAAA,gBAChD,MAAK;AAAA,gBACL,WAAU;AAAA,gBACV,UAAU;AAAA,gBACV,SAAS,MAAM,eAAe,MAAM;AAAA,gBACpC,gBAAc,WAAW;AAAA,gBAExB;AAAA;AAAA,kBAAO;AAAA;AAAA;AAAA,cATH;AAAA,YAUP,CACD,GACH;AAAA,YAEA,oBAAC,SAAI,WAAU,8EAA6E,sBAE5F;AAAA,YACA,oBAAC,SAAI,WAAU,0BACZ,+BAAqB,IAAI,CAAC,SACzB;AAAA,cAAC;AAAA;AAAA,gBAEC,MAAK;AAAA,gBACL,SAAS,SAAS,MAAM,cAAc;AAAA,gBACtC,MAAK;AAAA,gBACL,WAAU;AAAA,gBACV,UAAU;AAAA,gBACV,SAAS,MAAM,OAAO,IAAI;AAAA,gBAC1B,gBAAc,SAAS;AAAA,gBAErB;AAAA,0BAAO,KAAO,QAAQ,CAAC;AAAA,kBAAE;AAAA;AAAA;AAAA,cATtB;AAAA,YAUP,CACD,GACH;AAAA,aACF;AAAA,UAGC,SAAS,cACR,qBAAC,QAAG,WAAU,+BACZ;AAAA,gCAAC,aAAU,OAAM,SACf,+BAAC,UAAK,WAAU,oCACd;AAAA,kCAAC,kBAAe,WAAU,0BAAyB;AAAA,cAAE;AAAA,eAEvD,GACF;AAAA,YACA;AAAA,cAAC;AAAA;AAAA,gBACC,OAAM;AAAA,gBACN,MAAM,eAAe,WAAW;AAAA,gBAE/B,uBAAa,MAAM,cAAc;AAAA;AAAA,YACpC;AAAA,YACA,qBAAC,aAAU,OAAM,YAAY;AAAA,oBAAM;AAAA,cAAY;AAAA,eAAC;AAAA,YAChD,qBAAC,aAAU,OAAM,oBACd;AAAA,2BAAa,MAAM,YAAY;AAAA,cAAE;AAAA,cAAE,UAAU,UAAU;AAAA,eAC1D;AAAA,aACF,IACE;AAAA,UAGH,SACC;AAAA,YAAC,UAAU;AAAA,YAAV;AAAA,cACC,MAAM,MAAM,SAAS,SAAS,WAAW;AAAA,cAExC,gBAAM;AAAA;AAAA,UACT;AAAA,UAID,SAAS,SAAS,aACjB,qBAAC,SAAI,WAAU,uDACb;AAAA,gCAAC,QAAK,WAAU,2BAA0B;AAAA,YAC1C,oBAAC,UAAM,kBAAQ,SAAQ;AAAA,aACzB;AAAA,UAED,SAAS,SAAS,cACjB,qBAAC,SAAI,WAAU,oDACb;AAAA,gCAAC,gBAAa,WAAU,2BAA0B;AAAA,YAClD,qBAAC,UAAK;AAAA;AAAA,cACsB,aAAa,QAAQ,EAAE;AAAA,cAAE;AAAA,eAErD;AAAA,aACF;AAAA,UAIF;AAAA,YAAC;AAAA;AAAA,cACC,KAAK,WAAW;AAAA,cACf,GAAG,WAAW;AAAA,cACf,MAAK;AAAA,cACL,SAAQ;AAAA,cACR,WAAU;AAAA,cACV,UAAU,CAAC;AAAA,cACX,SAAS,MAAM,KAAK,YAAY;AAAA,cAE/B,sBACC,iCACE;AAAA,oCAAC,WAAQ,WAAU,WAAU;AAAA,gBAAE;AAAA,iBAEjC,IAEA,iCACE;AAAA,oCAAC,kBAAe,WAAU,WAAU;AAAA,gBACnC,iBAAiB,SAAS;AAAA,iBAC7B;AAAA;AAAA,UAEJ;AAAA,UAEC,CAAC,kBACA,oBAAC,OAAE,WAAU,WAAU,iGAGvB;AAAA,WAEJ,GACF;AAAA;AAAA;AAAA,EACF;AAEJ;","names":[]}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SwapSpatialView — the swap surface authored once with the spatial vocabulary,
|
|
3
|
+
* so it renders correctly wherever it is displayed:
|
|
4
|
+
*
|
|
5
|
+
* - GUI / XR — mounted in `<SpatialSurface>` (DOM; XR scales up).
|
|
6
|
+
* - TUI — rendered to real terminal lines by the agent terminal, via
|
|
7
|
+
* `registerSpatialTerminalView` (see `register-terminal-view.tsx`).
|
|
8
|
+
*
|
|
9
|
+
* It is purely presentational (a snapshot + an action callback in, primitives
|
|
10
|
+
* out) and imports only the cross-modality primitives, so it is safe to render
|
|
11
|
+
* in the Node agent process where the terminal lives (no @elizaos/app-core
|
|
12
|
+
* React-DOM client or swap-capability runtime import reaches the bundle).
|
|
13
|
+
*
|
|
14
|
+
* Execution stays honest: the swap action is quote-only (SWAP_EXECUTE_ENABLED is
|
|
15
|
+
* false), so the outcome line surfaces the "not enabled yet" preview message
|
|
16
|
+
* rather than fabricating a money path.
|
|
17
|
+
*/
|
|
18
|
+
/** Projected, display-only quote numbers. */
|
|
19
|
+
export interface SwapSnapshotQuote {
|
|
20
|
+
amountOut: number;
|
|
21
|
+
minAmountOut: number;
|
|
22
|
+
priceImpactPct: number;
|
|
23
|
+
source: "local-estimate" | "backend";
|
|
24
|
+
}
|
|
25
|
+
/** The full presentational state the view renders from. */
|
|
26
|
+
export interface SwapSnapshot {
|
|
27
|
+
tokenInSymbol: string;
|
|
28
|
+
tokenOutSymbol: string;
|
|
29
|
+
tokenSymbols: string[];
|
|
30
|
+
amountIn: string;
|
|
31
|
+
slippagePct: number;
|
|
32
|
+
quote: SwapSnapshotQuote | null;
|
|
33
|
+
canSwap: boolean;
|
|
34
|
+
quoting: boolean;
|
|
35
|
+
executing: boolean;
|
|
36
|
+
error: {
|
|
37
|
+
message: string;
|
|
38
|
+
} | null;
|
|
39
|
+
outcome: {
|
|
40
|
+
message: string;
|
|
41
|
+
} | null;
|
|
42
|
+
}
|
|
43
|
+
export interface SwapSpatialViewProps {
|
|
44
|
+
snapshot: SwapSnapshot;
|
|
45
|
+
/**
|
|
46
|
+
* Dispatched action ids: `token-in:<symbol>`, `token-out:<symbol>`,
|
|
47
|
+
* `amount:<value>`, `swap`.
|
|
48
|
+
*/
|
|
49
|
+
onAction?: (action: string) => void;
|
|
50
|
+
}
|
|
51
|
+
export declare function SwapSpatialView({ snapshot, onAction }: SwapSpatialViewProps): import("react/jsx-runtime").JSX.Element;
|
|
52
|
+
//# sourceMappingURL=SwapSpatialView.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SwapSpatialView.d.ts","sourceRoot":"","sources":["../src/SwapSpatialView.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAWH,6CAA6C;AAC7C,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,gBAAgB,GAAG,SAAS,CAAC;CACtC;AAED,2DAA2D;AAC3D,MAAM,WAAW,YAAY;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAClC,OAAO,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CACrC;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,YAAY,CAAC;IACvB;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CACrC;AAgBD,wBAAgB,eAAe,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,oBAAoB,2CA0F3E"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import {
|
|
3
|
+
Button,
|
|
4
|
+
Card,
|
|
5
|
+
Divider,
|
|
6
|
+
Field,
|
|
7
|
+
HStack,
|
|
8
|
+
Text
|
|
9
|
+
} from "@elizaos/ui/spatial";
|
|
10
|
+
function formatAmount(value) {
|
|
11
|
+
if (!Number.isFinite(value)) return "0";
|
|
12
|
+
return value.toLocaleString("en-US", {
|
|
13
|
+
minimumFractionDigits: 0,
|
|
14
|
+
maximumFractionDigits: value > 1 ? 4 : 6
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
function formatImpact(pct) {
|
|
18
|
+
if (!Number.isFinite(pct)) return "0.00%";
|
|
19
|
+
const sign = pct > 0 ? "+" : "";
|
|
20
|
+
return `${sign}${pct.toFixed(2)}%`;
|
|
21
|
+
}
|
|
22
|
+
function SwapSpatialView({ snapshot, onAction }) {
|
|
23
|
+
const { quote, error, outcome, quoting, executing } = snapshot;
|
|
24
|
+
const impactDanger = (quote?.priceImpactPct ?? 0) < -1;
|
|
25
|
+
return /* @__PURE__ */ jsxs(Card, { gap: 1, padding: 1, children: [
|
|
26
|
+
/* @__PURE__ */ jsxs(HStack, { gap: 1, align: "center", children: [
|
|
27
|
+
/* @__PURE__ */ jsx(Text, { style: "caption", tone: "muted", grow: 1, children: "PancakeSwap v3" }),
|
|
28
|
+
/* @__PURE__ */ jsxs(Text, { style: "caption", tone: "muted", children: [
|
|
29
|
+
"slippage ",
|
|
30
|
+
snapshot.slippagePct,
|
|
31
|
+
"%"
|
|
32
|
+
] })
|
|
33
|
+
] }),
|
|
34
|
+
/* @__PURE__ */ jsx(Divider, { label: "from" }),
|
|
35
|
+
/* @__PURE__ */ jsx(
|
|
36
|
+
Field,
|
|
37
|
+
{
|
|
38
|
+
kind: "select",
|
|
39
|
+
label: "from",
|
|
40
|
+
value: snapshot.tokenInSymbol,
|
|
41
|
+
options: snapshot.tokenSymbols,
|
|
42
|
+
disabled: executing,
|
|
43
|
+
onChange: (v) => onAction?.(`token-in:${v}`)
|
|
44
|
+
}
|
|
45
|
+
),
|
|
46
|
+
/* @__PURE__ */ jsx(
|
|
47
|
+
Field,
|
|
48
|
+
{
|
|
49
|
+
kind: "number",
|
|
50
|
+
label: "amount",
|
|
51
|
+
value: snapshot.amountIn,
|
|
52
|
+
placeholder: "0.0",
|
|
53
|
+
disabled: executing,
|
|
54
|
+
onChange: (v) => onAction?.(`amount:${v}`)
|
|
55
|
+
}
|
|
56
|
+
),
|
|
57
|
+
/* @__PURE__ */ jsx(Divider, { label: "to" }),
|
|
58
|
+
/* @__PURE__ */ jsx(
|
|
59
|
+
Field,
|
|
60
|
+
{
|
|
61
|
+
kind: "select",
|
|
62
|
+
label: "to",
|
|
63
|
+
value: snapshot.tokenOutSymbol,
|
|
64
|
+
options: snapshot.tokenSymbols,
|
|
65
|
+
disabled: executing,
|
|
66
|
+
onChange: (v) => onAction?.(`token-out:${v}`)
|
|
67
|
+
}
|
|
68
|
+
),
|
|
69
|
+
quote ? /* @__PURE__ */ jsxs(HStack, { gap: 1, align: "center", wrap: true, children: [
|
|
70
|
+
/* @__PURE__ */ jsxs(Text, { grow: 1, children: [
|
|
71
|
+
"\u2248 ",
|
|
72
|
+
formatAmount(quote.amountOut),
|
|
73
|
+
" ",
|
|
74
|
+
snapshot.tokenOutSymbol
|
|
75
|
+
] }),
|
|
76
|
+
/* @__PURE__ */ jsx(Text, { style: "caption", tone: "muted", children: quote.source === "backend" ? "live" : "estimated" })
|
|
77
|
+
] }) : /* @__PURE__ */ jsx(Text, { tone: "muted", style: "caption", children: quoting ? "quoting\u2026" : "enter an amount" }),
|
|
78
|
+
quote ? /* @__PURE__ */ jsxs(HStack, { gap: 1, align: "center", wrap: true, children: [
|
|
79
|
+
/* @__PURE__ */ jsxs(Text, { style: "caption", tone: "muted", grow: 1, children: [
|
|
80
|
+
"min ",
|
|
81
|
+
formatAmount(quote.minAmountOut),
|
|
82
|
+
" ",
|
|
83
|
+
snapshot.tokenOutSymbol
|
|
84
|
+
] }),
|
|
85
|
+
/* @__PURE__ */ jsxs(Text, { style: "caption", tone: impactDanger ? "danger" : "muted", children: [
|
|
86
|
+
"impact ",
|
|
87
|
+
formatImpact(quote.priceImpactPct)
|
|
88
|
+
] })
|
|
89
|
+
] }) : null,
|
|
90
|
+
/* @__PURE__ */ jsx(HStack, { gap: 1, children: /* @__PURE__ */ jsx(
|
|
91
|
+
Button,
|
|
92
|
+
{
|
|
93
|
+
grow: 1,
|
|
94
|
+
agent: "swap",
|
|
95
|
+
disabled: !snapshot.canSwap,
|
|
96
|
+
onPress: () => onAction?.("swap"),
|
|
97
|
+
children: executing ? "preparing\u2026" : "Swap"
|
|
98
|
+
}
|
|
99
|
+
) }),
|
|
100
|
+
error ? /* @__PURE__ */ jsx(Text, { tone: "danger", style: "caption", children: error.message }) : null,
|
|
101
|
+
outcome ? /* @__PURE__ */ jsx(Text, { tone: "muted", style: "caption", children: outcome.message }) : null
|
|
102
|
+
] });
|
|
103
|
+
}
|
|
104
|
+
export {
|
|
105
|
+
SwapSpatialView
|
|
106
|
+
};
|
|
107
|
+
//# sourceMappingURL=SwapSpatialView.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/SwapSpatialView.tsx"],"sourcesContent":["/**\n * SwapSpatialView — the swap surface authored once with the spatial vocabulary,\n * so it renders correctly wherever it is displayed:\n *\n * - GUI / XR — mounted in `<SpatialSurface>` (DOM; XR scales up).\n * - TUI — rendered to real terminal lines by the agent terminal, via\n * `registerSpatialTerminalView` (see `register-terminal-view.tsx`).\n *\n * It is purely presentational (a snapshot + an action callback in, primitives\n * out) and imports only the cross-modality primitives, so it is safe to render\n * in the Node agent process where the terminal lives (no @elizaos/app-core\n * React-DOM client or swap-capability runtime import reaches the bundle).\n *\n * Execution stays honest: the swap action is quote-only (SWAP_EXECUTE_ENABLED is\n * false), so the outcome line surfaces the \"not enabled yet\" preview message\n * rather than fabricating a money path.\n */\n\nimport {\n Button,\n Card,\n Divider,\n Field,\n HStack,\n Text,\n} from \"@elizaos/ui/spatial\";\n\n/** Projected, display-only quote numbers. */\nexport interface SwapSnapshotQuote {\n amountOut: number;\n minAmountOut: number;\n priceImpactPct: number;\n source: \"local-estimate\" | \"backend\";\n}\n\n/** The full presentational state the view renders from. */\nexport interface SwapSnapshot {\n tokenInSymbol: string;\n tokenOutSymbol: string;\n tokenSymbols: string[];\n amountIn: string;\n slippagePct: number;\n quote: SwapSnapshotQuote | null;\n canSwap: boolean;\n quoting: boolean;\n executing: boolean;\n error: { message: string } | null;\n outcome: { message: string } | null;\n}\n\nexport interface SwapSpatialViewProps {\n snapshot: SwapSnapshot;\n /**\n * Dispatched action ids: `token-in:<symbol>`, `token-out:<symbol>`,\n * `amount:<value>`, `swap`.\n */\n onAction?: (action: string) => void;\n}\n\nfunction formatAmount(value: number): string {\n if (!Number.isFinite(value)) return \"0\";\n return value.toLocaleString(\"en-US\", {\n minimumFractionDigits: 0,\n maximumFractionDigits: value > 1 ? 4 : 6,\n });\n}\n\nfunction formatImpact(pct: number): string {\n if (!Number.isFinite(pct)) return \"0.00%\";\n const sign = pct > 0 ? \"+\" : \"\";\n return `${sign}${pct.toFixed(2)}%`;\n}\n\nexport function SwapSpatialView({ snapshot, onAction }: SwapSpatialViewProps) {\n const { quote, error, outcome, quoting, executing } = snapshot;\n const impactDanger = (quote?.priceImpactPct ?? 0) < -1;\n\n return (\n <Card gap={1} padding={1}>\n <HStack gap={1} align=\"center\">\n <Text style=\"caption\" tone=\"muted\" grow={1}>\n PancakeSwap v3\n </Text>\n <Text style=\"caption\" tone=\"muted\">\n slippage {snapshot.slippagePct}%\n </Text>\n </HStack>\n\n <Divider label=\"from\" />\n <Field\n kind=\"select\"\n label=\"from\"\n value={snapshot.tokenInSymbol}\n options={snapshot.tokenSymbols}\n disabled={executing}\n onChange={(v) => onAction?.(`token-in:${v}`)}\n />\n <Field\n kind=\"number\"\n label=\"amount\"\n value={snapshot.amountIn}\n placeholder=\"0.0\"\n disabled={executing}\n onChange={(v) => onAction?.(`amount:${v}`)}\n />\n\n <Divider label=\"to\" />\n <Field\n kind=\"select\"\n label=\"to\"\n value={snapshot.tokenOutSymbol}\n options={snapshot.tokenSymbols}\n disabled={executing}\n onChange={(v) => onAction?.(`token-out:${v}`)}\n />\n {quote ? (\n <HStack gap={1} align=\"center\" wrap>\n <Text grow={1}>\n ≈ {formatAmount(quote.amountOut)} {snapshot.tokenOutSymbol}\n </Text>\n <Text style=\"caption\" tone=\"muted\">\n {quote.source === \"backend\" ? \"live\" : \"estimated\"}\n </Text>\n </HStack>\n ) : (\n <Text tone=\"muted\" style=\"caption\">\n {quoting ? \"quoting…\" : \"enter an amount\"}\n </Text>\n )}\n {quote ? (\n <HStack gap={1} align=\"center\" wrap>\n <Text style=\"caption\" tone=\"muted\" grow={1}>\n min {formatAmount(quote.minAmountOut)} {snapshot.tokenOutSymbol}\n </Text>\n <Text style=\"caption\" tone={impactDanger ? \"danger\" : \"muted\"}>\n impact {formatImpact(quote.priceImpactPct)}\n </Text>\n </HStack>\n ) : null}\n\n <HStack gap={1}>\n <Button\n grow={1}\n agent=\"swap\"\n disabled={!snapshot.canSwap}\n onPress={() => onAction?.(\"swap\")}\n >\n {executing ? \"preparing…\" : \"Swap\"}\n </Button>\n </HStack>\n\n {error ? (\n <Text tone=\"danger\" style=\"caption\">\n {error.message}\n </Text>\n ) : null}\n {outcome ? (\n <Text tone=\"muted\" style=\"caption\">\n {outcome.message}\n </Text>\n ) : null}\n </Card>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SwapView — the single GUI/XR data wrapper for the swap surface.
|
|
3
|
+
*
|
|
4
|
+
* It owns the live swap state (token-in/token-out selection, the amount + the
|
|
5
|
+
* quote/execute lifecycle via {@link useSwapState}) and renders the one
|
|
6
|
+
* presentational {@link SwapSpatialView} inside a {@link SpatialSurface}.
|
|
7
|
+
* Omitting the `modality` prop lets `SpatialSurface` auto-detect GUI vs XR via
|
|
8
|
+
* `window.__elizaXRContext`, so the SAME component serves both surfaces. The TUI
|
|
9
|
+
* surface renders the same `SwapSpatialView` through the terminal registry (see
|
|
10
|
+
* `register-terminal-view.tsx`).
|
|
11
|
+
*/
|
|
12
|
+
import type { SwapToken } from "./swap-contracts";
|
|
13
|
+
/**
|
|
14
|
+
* Host props for the unified swap surface. All optional: the spatial wrapper is
|
|
15
|
+
* mounted as an in-process app-shell page / bundled view, not the full-screen
|
|
16
|
+
* overlay, so it needs none of the `OverlayAppContext` callbacks the legacy
|
|
17
|
+
* {@link import("./SwapAppView").SwapAppView} consumed. It only forwards the
|
|
18
|
+
* optional host overrides into the swap state. Keeping them all-optional lets
|
|
19
|
+
* the app-shell loader's `Record<string, unknown>` component typing accept it.
|
|
20
|
+
*/
|
|
21
|
+
export interface SwapViewProps {
|
|
22
|
+
/** Optional host override for which agent's swap capability to invoke. */
|
|
23
|
+
agentTokenAddress?: string;
|
|
24
|
+
/** Optional host-supplied swap-eligible token list. */
|
|
25
|
+
tokens?: readonly SwapToken[];
|
|
26
|
+
/** Raised when the backend reports the capability is unavailable (404). */
|
|
27
|
+
onUnavailable?: () => void;
|
|
28
|
+
}
|
|
29
|
+
export declare function SwapView({ agentTokenAddress, tokens: tokensProp, onUnavailable, }?: SwapViewProps): import("react/jsx-runtime").JSX.Element;
|
|
30
|
+
//# sourceMappingURL=SwapView.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SwapView.d.ts","sourceRoot":"","sources":["../src/SwapView.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAGlD;;;;;;;GAOG;AACH,MAAM,WAAW,aAAa;IAC5B,0EAA0E;IAC1E,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,uDAAuD;IACvD,MAAM,CAAC,EAAE,SAAS,SAAS,EAAE,CAAC;IAC9B,2EAA2E;IAC3E,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;CAC5B;AAoBD,wBAAgB,QAAQ,CAAC,EACvB,iBAAiB,EACjB,MAAM,EAAE,UAAU,EAClB,aAAa,GACd,GAAE,aAAkB,2CAsEpB"}
|