@nexus-cross/dapp-ui 1.4.0-beta.4 → 1.4.0-beta.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/dist/index.d.cts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Scope } from '@sentry/react';
2
2
  import * as React from 'react';
3
- import { Component, ReactNode, ErrorInfo, CSSProperties } from 'react';
3
+ import { Component, ReactNode, ErrorInfo, CSSProperties, ElementType, ButtonHTMLAttributes } from 'react';
4
4
  import * as react_jsx_runtime from 'react/jsx-runtime';
5
5
  import * as _tanstack_react_query from '@tanstack/react-query';
6
6
  import { UseQueryOptions } from '@tanstack/react-query';
@@ -11,6 +11,87 @@ type DrawerDirection$1 = "right" | "bottom" | "left";
11
11
 
12
12
  declare function resolveEnvironment(env?: Environment | "staging" | "prd" | "prod" | "stg"): Environment;
13
13
 
14
+ /** env별로 다르면 객체, 모든 env 동일하면 T 단일 값. */
15
+ type RemoteEnvValue<T> = T | Record<Environment, T>;
16
+ type AppsConfig = {
17
+ skills?: RemoteEnvValue<string>;
18
+ gametokenBridge?: RemoteEnvValue<string>;
19
+ /** 브릿지 버튼을 새창 대신 같은 창으로 여는 gametoken 사이트 URL prefix 목록. */
20
+ gametokenSites?: string[];
21
+ bridgePoweredBy?: {
22
+ url?: RemoteEnvValue<string>;
23
+ };
24
+ /**
25
+ * 약관 문서 링크. 브릿지 약관 동의 모달의 Terms of Service 링크가 읽는다 —
26
+ * cross-game-swap의 legal.json과 같은 운영 방식(무배포 교체). 호출부가
27
+ * `termsUrl` prop을 넘기면 그 값이 우선, 값이 없으면 DEFAULT_TERMS_URL 폴백.
28
+ */
29
+ legal?: {
30
+ termsUrl?: RemoteEnvValue<string>;
31
+ };
32
+ /**
33
+ * Get ONEUSD chooser action visibility. Swap/Bridge default to enabled;
34
+ * Transfer Crypto defaults to disabled when remote config is unavailable.
35
+ */
36
+ getOneUsd?: {
37
+ modes?: {
38
+ swap?: boolean;
39
+ bridge?: boolean;
40
+ transferCrypto?: boolean;
41
+ };
42
+ /**
43
+ * 액션별 최소 dapp-ui 버전. 호스트가 설치한 dapp-ui 가 이 값보다 낮으면
44
+ * `modes`가 true여도 해당 액션을 숨긴다 — 구버전에서 깨지는 기능을 호스트
45
+ * 재배포 없이 끄기 위한 장치. 값이 없으면 버전 제한 없음, 형식이 깨져
46
+ * 있으면 통과(설정 오타로 전체가 사라지지 않게).
47
+ */
48
+ minVersions?: {
49
+ swap?: string;
50
+ bridge?: string;
51
+ transferCrypto?: string;
52
+ };
53
+ };
54
+ /**
55
+ * 토큰 상세화면 섹션별 노출 여부. 값이 없으면 기본값(history·balance만 노출).
56
+ * 섹션 키: chart / balance(=My Balance + Send) / overview / social / history.
57
+ * env별 값은 apps.json 파일 자체가 환경마다 분리돼 있으므로 단순 boolean만 받는다.
58
+ */
59
+ tokenDetail?: {
60
+ sections?: {
61
+ chart?: boolean;
62
+ balance?: boolean;
63
+ overview?: boolean;
64
+ social?: boolean;
65
+ history?: boolean;
66
+ };
67
+ };
68
+ /**
69
+ * Relay(외부체인 → CROSS 입금) 운영 설정.
70
+ * `minDepositAmount`: 입금 위저드 Continue를 막는 최소 수량(사람 단위,
71
+ * 토큰 공통). CDN 값이 없거나 fetch 실패 시 호출부 폴백(6)이 적용된다 —
72
+ * endpoints.json과 달리 UI 게이트라 폴백을 허용한다.
73
+ */
74
+ relay?: {
75
+ minDepositAmount?: RemoteEnvValue<number | string>;
76
+ /**
77
+ * `maxDepositAmount`: Continue를 막는 최대 수량(사람 단위, 토큰 공통).
78
+ * 브릿지/DEX 유동성 한도를 운영이 수동 반영하는 값 — 미설정 시 상한 없음.
79
+ */
80
+ maxDepositAmount?: RemoteEnvValue<number | string>;
81
+ /**
82
+ * Role-labelled Relay factory addresses. New SDKs prefer this field so
83
+ * operators can tell the StandingForwarderFactory and
84
+ * DepositorForwarderFactory apart without relying on array order.
85
+ *
86
+ * A legacy `trustedFactories` field, if encountered, is deliberately not
87
+ * typed or read by current code.
88
+ */
89
+ forwarderFactories?: RemoteEnvValue<{
90
+ standingForwarderFactory?: string;
91
+ depositorForwarderFactory?: string;
92
+ }>;
93
+ };
94
+ };
14
95
  declare const CHAINS_CONFIG_FILE = "chains.json";
15
96
  /** 체인 하나의 표시 메타. 지정 안 된 필드는 호출부 폴백(온체인/하드코딩)으로. */
16
97
  type ChainDisplayMeta = {
@@ -92,7 +173,7 @@ declare class DappUiErrorBoundary extends Component<DappUiErrorBoundaryProps, Da
92
173
  render(): ReactNode;
93
174
  }
94
175
 
95
- type DappUiFeature = "app_launcher" | "bridge" | "connect_button" | "relay" | "send" | "skills" | "wallet_connect" | "wallet_info" | "wallet_portfolio";
176
+ type DappUiFeature = "app_launcher" | "bridge" | "connect_button" | "get_one_usd" | "relay" | "send" | "skills" | "wallet_connect" | "wallet_info" | "wallet_portfolio";
96
177
  type DappUiFlow = "connect" | "send" | "bridge" | "withdraw" | "relay";
97
178
  type DappUiFailureReason = "user-rejected" | "insufficient-gas" | "timeout" | "contract-reverted" | "network" | "unknown";
98
179
  interface TrackDappUiFunnelOptions {
@@ -755,7 +836,7 @@ interface BridgeInfoTokenRef {
755
836
  interface BridgeInfoRow {
756
837
  label: string;
757
838
  value: string;
758
- tone?: "default" | "accent" | "warning";
839
+ tone?: "default" | "accent" | "warning" | "danger";
759
840
  routeTokens?: BridgeInfoTokenRef[];
760
841
  valueToken?: BridgeInfoTokenRef;
761
842
  }
@@ -848,9 +929,22 @@ interface BridgeFlowProps {
848
929
  onFailed?: (info: BridgeFailedInfo) => void;
849
930
  onClose?: () => void;
850
931
  onBackToWallet?: () => void;
932
+ /**
933
+ * 이 거래의 수수료를 서비스가 대납하는지. 견적(`BridgeTxSummary.txFeeInfo`)의
934
+ * `isDelegateFee` 는 가스만 가리키므로, 스왑/브릿지 수수료 대납은 호출부가
935
+ * 알려줘야 한다(Get ONEUSD 는 `pairs.swap/bridge.feeDelegated` 로 안다).
936
+ */
937
+ feeDelegated?: boolean;
938
+ /** Compact modal mode: fixed direction, no history entry, host-provided title. */
939
+ variant?: "default" | "embedded";
940
+ title?: string;
941
+ /** Embedded mode only. Defaults to whether `walletAddress` is present. */
942
+ isConnected?: boolean;
943
+ /** Opens the host wallet connection flow from the embedded CTA. */
944
+ onRequestConnect?: () => void;
851
945
  className?: string;
852
946
  }
853
- declare function BridgeFlow({ onClose, onBackToWallet, env, className, ...rest }: BridgeFlowProps): react_jsx_runtime.JSX.Element;
947
+ declare function BridgeFlow({ onClose, onBackToWallet, feeDelegated, env, variant, title: titleProp, isConnected: isConnectedProp, onRequestConnect, className, ...rest }: BridgeFlowProps): react_jsx_runtime.JSX.Element;
854
948
 
855
949
  interface WalletInfoTriggerProps {
856
950
  asChild?: boolean;
@@ -1321,1352 +1415,1473 @@ interface WalletPortfolioBodyProps {
1321
1415
  }
1322
1416
  declare function WalletPortfolioBody({ env, theme, walletAddress, walletName, onBack, showHeader, variant, className, onOutlink, lpBalanceReader, stakingRewardsReader, sendTransaction, estimateGas, conversionRatio, currencySymbol, sections, }: WalletPortfolioBodyProps): react_jsx_runtime.JSX.Element;
1323
1417
 
1324
- declare function CROSSxIcon(): react_jsx_runtime.JSX.Element;
1325
- declare function MetaMaskIcon(): react_jsx_runtime.JSX.Element;
1326
- declare function BinanceIcon(): react_jsx_runtime.JSX.Element;
1327
- declare function Verse8Icon(): react_jsx_runtime.JSX.Element;
1328
- declare function TronIcon(): react_jsx_runtime.JSX.Element;
1329
- declare function GoogleIcon(): react_jsx_runtime.JSX.Element;
1330
- declare function AppleIcon(): react_jsx_runtime.JSX.Element;
1331
-
1332
- declare const WALLET_REGISTRY: {
1333
- cross_embedded: {
1334
- id: string;
1335
- name: "ONEpocket with Social";
1336
- description: string;
1337
- icon: typeof CROSSxIcon;
1338
- };
1339
- cross_wallet: {
1340
- id: string;
1341
- name: "ONEpocket";
1342
- description: string;
1343
- icon: typeof CROSSxIcon;
1344
- featured: true;
1345
- };
1346
- cross_extension: {
1347
- id: string;
1348
- name: "ONEpocket Extension";
1349
- description: string;
1350
- icon: typeof CROSSxIcon;
1351
- rdns: string;
1352
- installUrl: string;
1353
- visibility: "desktop-only";
1354
- };
1355
- metamask: {
1356
- id: string;
1357
- name: string;
1358
- description: string;
1359
- icon: typeof MetaMaskIcon;
1360
- rdns: string;
1361
- };
1362
- binance: {
1363
- id: string;
1364
- name: string;
1365
- description: string;
1366
- icon: typeof BinanceIcon;
1367
- };
1368
- verse8: {
1369
- id: string;
1370
- name: string;
1371
- description: string;
1372
- icon: typeof Verse8Icon;
1373
- badge: string;
1374
- };
1375
- tron: {
1376
- id: string;
1377
- name: string;
1378
- description: string;
1379
- icon: typeof TronIcon;
1380
- badge: string;
1381
- };
1382
- };
1383
- type WalletId = keyof typeof WALLET_REGISTRY;
1384
- declare const SOCIAL_REGISTRY: {
1385
- google: {
1386
- id: string;
1387
- name: string;
1388
- icon: typeof GoogleIcon;
1389
- };
1390
- apple: {
1391
- id: string;
1392
- name: string;
1393
- icon: typeof AppleIcon;
1394
- };
1395
- };
1396
- type SocialId = keyof typeof SOCIAL_REGISTRY;
1397
-
1398
- /**
1399
- * Per-instance layout overrides applied as inline CSS variables.
1400
- *
1401
- * Colors / typography are driven by the design system (`--ds-*`, published
1402
- * by `CrossConnectKitProvider` from `@nexus-cross/crossx-design-system`) —
1403
- * retheme there, not per modal. Only layout knobs remain here.
1404
- */
1405
- interface WalletConnectModalStyle extends CSSProperties {
1406
- "--wcm-dialog-width"?: string;
1407
- "--wcm-drawer-max-width"?: string;
1408
- "--wcm-drawer-min-width"?: string;
1418
+ /** One origin-side ERC-20 (or native, address = zero) token the UI may offer. */
1419
+ interface Token {
1420
+ symbol: string;
1421
+ address: string;
1422
+ decimals: number;
1423
+ logoUrl?: string;
1409
1424
  }
1410
- type WalletVisibility = "always" | "mobile-only" | "desktop-only";
1411
- interface WalletConfig {
1412
- id: string;
1413
- name: string;
1414
- description: string;
1415
- icon: () => ReactNode;
1416
- rdns?: string;
1417
- featured?: boolean;
1418
- badge?: string;
1419
- installUrl?: string;
1420
- visibility?: WalletVisibility;
1425
+ /** The fixed destination asset every order delivers: crossd on CROSS. */
1426
+ interface Destination {
1427
+ symbol: string;
1428
+ chainId: number;
1429
+ address: string;
1430
+ decimals: number;
1431
+ note?: string;
1421
1432
  }
1422
- type WalletHandlers = Partial<Record<WalletId, () => void | Promise<void>>>;
1423
- interface SocialConfig {
1424
- id: string;
1425
- name: string;
1426
- icon: () => ReactNode;
1433
+ /** Origin chain VM family: "evm" (default) or "svm" (Solana). */
1434
+ type ChainKind = 'evm' | 'svm';
1435
+ /**
1436
+ * One delivery-side asset an order's crossd-equivalent output may be paid
1437
+ * out as -- the default target (isDefault: true) is crossd itself
1438
+ * (byte-identical to Catalog.destination); non-default targets are
1439
+ * alternate payout assets the user may opt into (see GET /v1/deposit-address's
1440
+ * `target` query param). `external: true` marks a target delivered via an
1441
+ * external adapter (e.g. pONEUSD) rather than natively minted -- the UI
1442
+ * shows an extra trust note for these (Task 9).
1443
+ */
1444
+ type Target = {
1445
+ symbol: string;
1446
+ address: string;
1447
+ decimals: number;
1448
+ isDefault: boolean;
1449
+ external: boolean;
1450
+ };
1451
+ /** One supported (chain, token) pair the UI can offer as an order's source. */
1452
+ interface OriginOption {
1453
+ chainId: number;
1454
+ chainName: string;
1455
+ /**
1456
+ * VM family of the origin chain. "svm" (Solana) origins are display-only:
1457
+ * the connected EVM wallet cannot sign them, so no one-click deposit or
1458
+ * balance read is offered -- the user pays out-of-band from a Solana wallet.
1459
+ */
1460
+ kind: ChainKind;
1461
+ token: Token;
1462
+ /** Smallest-unit base-10 integer string (matches Token.decimals). */
1463
+ minAmount: string;
1464
+ /** Smallest-unit base-10 integer string; absent = no configured cap. */
1465
+ maxAmount?: string;
1427
1466
  }
1428
- type SocialHandlers = Partial<Record<SocialId, () => void | Promise<void>>>;
1429
- type DrawerDirection = "bottom" | "left" | "right" | "top";
1430
- interface WalletConnectModalProps {
1431
- wallets: WalletHandlers;
1432
- socialProviders?: SocialHandlers;
1467
+ /**
1468
+ * Which order-creation flow is live: "standing" (GET /v1/deposit-address
1469
+ * returns a stable, reusable per-user address) or "per_order" (the legacy
1470
+ * flow, a fresh forwarder minted per POST /v1/orders). See
1471
+ * internal/catalog.Catalog.AddressMode's doc comment.
1472
+ */
1473
+ type AddressMode = 'standing' | 'per_order';
1474
+ /** GET /v1/config response: the curated catalog of origins + fixed destination. */
1475
+ interface Catalog {
1476
+ destination: Destination;
1477
+ origins: OriginOption[];
1478
+ addressMode: AddressMode;
1433
1479
  /**
1434
- * URL the "Terms of Service" link in the footer points to. When
1435
- * omitted the text is rendered without an anchor (still styled in the
1436
- * primary color to match the design).
1480
+ * The user-selectable delivery targets an order may pay out as (Task 4).
1481
+ * Always includes the default target (crossd, byte-identical to
1482
+ * `destination`). Defaults to `[]` when the backend response omits this
1483
+ * field entirely -- back-compat with an older backend that predates
1484
+ * per-target delivery (see createRelayClient's getConfig).
1437
1485
  */
1438
- termsUrl?: string;
1439
- /** URL the "Privacy Policy" link in the footer points to. */
1440
- privacyUrl?: string;
1441
- theme?: "dark" | "light";
1442
- mobileBreakpoint?: number;
1443
- drawerDirection?: DrawerDirection;
1444
- dialogWidth?: string;
1445
- drawerMaxWidth?: string;
1446
- drawerMinWidth?: string;
1447
- style?: WalletConnectModalStyle;
1448
- open?: boolean;
1449
- onOpenChange?: (open: boolean) => void;
1450
- children: ReactNode;
1486
+ targets: Target[];
1451
1487
  }
1452
- interface WalletConnectModalTriggerProps {
1453
- asChild?: boolean;
1454
- children?: ReactNode;
1488
+ /** POST /v1/quote request body. */
1489
+ interface QuoteRequest {
1490
+ originChainId: number;
1491
+ originCurrency: string;
1492
+ /** Smallest-unit base-10 integer string. */
1493
+ amount: string;
1455
1494
  }
1456
- interface WalletConnectModalContentProps {
1457
- className?: string;
1495
+ /** POST /v1/quote response body. */
1496
+ interface QuoteResult {
1497
+ /** Smallest-unit (BSC USDT, 18 decimals) base-10 integer string. */
1498
+ expectedBscUsdt: string;
1499
+ belowMin: boolean;
1500
+ /**
1501
+ * Smallest-unit (crossd, catalog.destination.decimals) base-10 integer
1502
+ * string. Currently assumed at 1:1 parity with BSC USDT -- see
1503
+ * assumesParity.
1504
+ */
1505
+ expectedCrossd: string;
1506
+ assumesParity: boolean;
1507
+ /**
1508
+ * The fee DEDUCTED FROM the bridged amount, in USD, as a decimal string --
1509
+ * Relay's relayer fee plus any app surcharge (upstream af35dd5). It is
1510
+ * exactly what accounts for the gap between what the user sends and
1511
+ * `expectedBscUsdt`.
1512
+ *
1513
+ * It deliberately EXCLUDES the user's own origin-chain gas: that is paid from
1514
+ * their wallet in the origin chain's native token, the wallet already quotes
1515
+ * it at signing time, and none of it comes out of the bridged amount.
1516
+ *
1517
+ * Absent means UNKNOWN, never free -- render absence as absence. "$0.00" for
1518
+ * a fee nobody could compute is the one wrong reading. (A genuine zero, e.g.
1519
+ * the direct BSC-USDT route with no Relay leg, is also absent rather than
1520
+ * "0": no Relay leg means no relayer fee to report.)
1521
+ */
1522
+ feeUsd?: string;
1523
+ /**
1524
+ * How many seconds this quote stays valid. Drives the refresh cadence in
1525
+ * useDepositAddress -- the widget previously hardcoded 30s with no
1526
+ * relationship to the quote's real lifetime. Absent when the backend has no
1527
+ * TTL configured, in which case the client keeps its own default interval.
1528
+ *
1529
+ * There is deliberately no eta/duration field here. An earlier version of
1530
+ * this type carried `etaSeconds` on the assumption that Relay's quote
1531
+ * reports timing; it does not -- the response has no ETA field of any kind
1532
+ * -- so it was removed rather than left permanently undefined.
1533
+ */
1534
+ ttl?: number;
1458
1535
  }
1459
-
1460
- declare function WalletConnectModalTrigger({ asChild, children, }: WalletConnectModalTriggerProps): react_jsx_runtime.JSX.Element;
1461
-
1462
- declare function WalletConnectModalContent({ className, }: WalletConnectModalContentProps): react_jsx_runtime.JSX.Element;
1463
-
1464
- declare function WalletConnectModalRoot({ wallets, socialProviders, termsUrl, privacyUrl, theme, mobileBreakpoint, drawerDirection, dialogWidth, drawerMaxWidth, drawerMinWidth, style, open: openProp, onOpenChange, children, }: WalletConnectModalProps): react_jsx_runtime.JSX.Element;
1465
- declare const WalletConnectModal: typeof WalletConnectModalRoot & {
1466
- Trigger: typeof WalletConnectModalTrigger;
1467
- Content: typeof WalletConnectModalContent;
1468
- };
1469
-
1470
- interface DetectedWallet {
1471
- rdns: string;
1472
- name: string;
1473
- icon?: string;
1536
+ /** GET /v1/deposit-address request query params -- no amount: a standing
1537
+ * address is resolved purely from (user, originChainId, originCurrency),
1538
+ * independent of any deposit size. */
1539
+ interface DepositAddressRequest {
1540
+ user: string;
1541
+ originChainId: number;
1542
+ originCurrency: string;
1474
1543
  }
1475
- interface WalletDetectResult {
1476
- wallets: DetectedWallet[];
1477
- isDetected: (rdns: string) => boolean;
1478
- isLoading: boolean;
1544
+ /**
1545
+ * GET /v1/deposit-address response body -- a stable, reusable deposit
1546
+ * address for this (user, origin chain, origin token). The same request
1547
+ * always resolves to the same address; no order/deposit is created by
1548
+ * fetching it, and it accepts any number of deposits over time (see
1549
+ * internal/standing.Service.GetOrCreateDepositAddress).
1550
+ */
1551
+ interface DepositAddressResult {
1552
+ user: string;
1553
+ forwarder: string;
1554
+ version: number;
1555
+ depositAddress: string;
1556
+ originChainId: number;
1557
+ originCurrency: string;
1479
1558
  }
1480
- declare function useWalletDetect(): WalletDetectResult;
1481
-
1482
1559
  /**
1483
- * `ConnectButton`의 `style` prop 타입. 표준 `CSSProperties` 위에
1484
- * `--cb-*` CSS 커스텀 변수 키를 추가해 자동완성을 지원한다.
1485
- *
1486
- * 사용 예: `style={{ "--cb-bg": "#7346f3", "--cb-pill-bg": "#1a1a2e" }}`
1560
+ * One row of GET /v1/orders?user=...'s "orders" array. A single order can
1561
+ * aggregate several deposits made to the same reusable forwarder; `deposits[]`
1562
+ * is the per-arrival identity. Amount fields are smallest-unit base-10 integer
1563
+ * strings, "" when not yet known.
1564
+ */
1565
+ interface OrderSummary {
1566
+ orderId: string;
1567
+ status: string;
1568
+ source: string;
1569
+ amountIn: string;
1570
+ expectedOut: string;
1571
+ bscBridgeTx: string;
1572
+ originChainId: number;
1573
+ originCurrency: string;
1574
+ /** CROSS delivery-token symbol this order pays out as (a Catalog.targets
1575
+ * symbol, e.g. "pONEUSD"); "" / omitted means the default target. Used to
1576
+ * label the "out" side with the actual delivered token. */
1577
+ target?: string;
1578
+ forwarderVersion: number;
1579
+ /** RFC3339 timestamp. */
1580
+ createdAt: string;
1581
+ /** What the user ACTUALLY received, observed from the CROSS delivery
1582
+ * transfer. Distinct from expectedOut, which is the pre-delivery projection
1583
+ * after fees -- the two differ by swap slippage and any executor fallback.
1584
+ * "" until delivery, and for orders delivered before the backend recorded it. */
1585
+ amountOut?: string;
1586
+ /** The CROSS-side transaction that delivered the funds. "" until delivery. */
1587
+ deliveryTxHash?: string;
1588
+ /** RFC3339 timestamp of the COMPLETED transition -- when the user received
1589
+ * the funds. Absent for orders that never completed. */
1590
+ completedAt?: string;
1591
+ /** The individual deposits this delivery paid out, oldest first. There can be
1592
+ * SEVERAL: a user may top up a little at a time and the sweeper aggregates
1593
+ * whatever has arrived into one order. Empty when the backend has not
1594
+ * attributed the deposits to this order yet. */
1595
+ deposits?: OrderDeposit[];
1596
+ }
1597
+ /** One deposit inside an order, as GET /v1/orders reports it.
1487
1598
  *
1488
- * 변수는 ConnectButton 의 모든 상태(disconnected / connecting / connected
1489
- * pill)에 cascading 된다. WalletInfo popover 의 스타일은 별도
1490
- * `walletInfoStyle` prop 으로 분리되어 있다.
1599
+ * originChainId/originCurrency are the chain and token the user ACTUALLY paid,
1600
+ * which the order itself cannot report (one reusable deposit address serves
1601
+ * every origin route, so the swept balance carries no memory of where it came
1602
+ * from). They are absent when the backend has not attributed the deposit --
1603
+ * for a DIRECT BSC deposit that is permanent and correct, since it has no
1604
+ * cross-chain leg. */
1605
+ interface OrderDeposit {
1606
+ /** Amount that arrived at the forwarder, in BSC USDT base units. NOT the
1607
+ * amount sent on the origin chain, which is larger by Relay's fees and
1608
+ * denominated in the origin token's own decimals. */
1609
+ amount: string;
1610
+ blockNumber: number;
1611
+ originChainId?: number;
1612
+ originCurrency?: string;
1613
+ /** The BSC-side arrival (transfer into the forwarder). */
1614
+ txHash: string;
1615
+ /** The user's own send on the ORIGIN chain -- what the "Deposit" step links
1616
+ * to. Absent when unattributed. */
1617
+ originTxHash?: string;
1618
+ }
1619
+ type StepStatus = 'done' | 'active' | 'pending';
1620
+ interface OrderStep {
1621
+ key: string;
1622
+ label: string;
1623
+ status: StepStatus;
1624
+ }
1625
+ /**
1626
+ * GET /v1/orders/{orderId} response body. "status" is the raw backend state
1627
+ * (e.g. "AWAITING_DEPOSIT", "COMPLETED", "FAILED", ...); "steps" is the
1628
+ * friendlier 3-stage deposit -> bridge -> deliver breakdown the UI renders.
1491
1629
  */
1492
- interface ConnectButtonStyle extends CSSProperties {
1493
- "--cb-bg"?: string;
1494
- "--cb-bg-hover"?: string;
1495
- "--cb-color"?: string;
1496
- "--cb-border"?: string;
1497
- "--cb-radius"?: string;
1498
- "--cb-height"?: string;
1499
- "--cb-padding"?: string;
1500
- "--cb-font-family"?: string;
1501
- "--cb-font-size"?: string;
1502
- "--cb-font-weight"?: string | number;
1503
- "--cb-line-height"?: string | number;
1504
- "--cb-letter-spacing"?: string;
1505
- "--cb-gap"?: string;
1506
- "--cb-transition"?: string;
1507
- "--cb-loading-opacity"?: string | number;
1508
- "--cb-press-scale"?: string | number;
1509
- "--cb-icon-size"?: string;
1510
- "--cb-spinner-size"?: string;
1511
- "--cb-spinner-thumb"?: string;
1512
- "--cb-spinner-track"?: string;
1513
- "--cb-pill-bg"?: string;
1514
- "--cb-pill-bg-hover"?: string;
1515
- "--cb-pill-color"?: string;
1516
- "--cb-pill-border"?: string;
1517
- "--cb-pill-radius"?: string;
1518
- "--cb-pill-height"?: string;
1519
- "--cb-pill-padding"?: string;
1520
- "--cb-pill-press-scale"?: string | number;
1521
- "--cb-pill-font-family"?: string;
1522
- "--cb-pill-font-size"?: string;
1523
- "--cb-pill-font-weight"?: string | number;
1524
- "--cb-pill-line-height"?: string | number;
1525
- "--cb-pill-gap"?: string;
1526
- "--cb-pill-icon-size"?: string;
1527
- "--cb-pill-icon-placeholder-bg"?: string;
1528
- "--cb-pill-address-font"?: string;
1529
- "--cb-pill-address-font-size"?: string;
1530
- "--cb-pill-address-letter-spacing"?: string;
1630
+ interface Order {
1631
+ orderId: string;
1632
+ status: string;
1633
+ steps: OrderStep[];
1634
+ bridgeIndex: string;
1635
+ txs: {
1636
+ bscBridge: string;
1637
+ crossFinalize: string;
1638
+ crossExecute: string;
1639
+ };
1531
1640
  }
1532
1641
  /**
1533
- * Resolved wallet provider — determines which icon + display name appears
1534
- * in the connected pill.
1535
- *
1536
- * - `google` / `apple`: crossy-sdk 2.0 OAuth login types (embedded wallet)
1537
- * - `cross`: generic CROSSx mark (covers CROSSx 1.0 extension/app + 2.0
1538
- * embedded when no OAuth provider is attached)
1539
- * - `metamask` / `binance`: external wallets
1642
+ * GET /v1/recovery?user=... response body -- the permissionless self-recovery
1643
+ * status for a user's standing forwarder on BSC. Task 1's endpoint; consumed
1644
+ * by useRecovery (Task 2) to drive the settings-menu "Recover stuck funds"
1645
+ * panel. Every recovery tx (factory.deploy, forwarder.execute/sweepToUser)
1646
+ * takes no destination argument -- funds always route to `forwarder`'s
1647
+ * immutable recipient, so this info is advisory/orientation only, never a
1648
+ * capability check the UI should use to block the user.
1540
1649
  */
1541
- type WalletProvider = "google" | "apple" | "cross" | "metamask" | "binance";
1542
- interface ConnectButtonProps {
1543
- /** 사용자가 Connect 버튼을 눌러 연결이 진행 중. 스피너 버튼으로 전환된다. */
1544
- isConnecting?: boolean;
1650
+ interface RecoveryInfo {
1651
+ user: string;
1652
+ /** The user's forwarder address on BSC for the requested target (CREATE2, deterministic from
1653
+ * user+version+target). */
1654
+ forwarder: string;
1655
+ /** Whether `forwarder` has been deployed on-chain yet. */
1656
+ isDeployed: boolean;
1657
+ /** BSC USDT token contract address -- always BSC USDT regardless of `target` (the forwarder
1658
+ * holds BSC USDT pre-bridge in every case). */
1659
+ token: string;
1660
+ decimals: number;
1661
+ /** Smallest-unit base-10 integer string -- the forwarder's current token balance. */
1662
+ balance: string;
1663
+ /** The factory that deploys/derives `forwarder` for the requested target: the
1664
+ * DepositorForwarderFactory for a depositor-kind target, the StandingForwarderFactory
1665
+ * otherwise (recovery follow-up, multi-target). */
1666
+ factory: string;
1667
+ version: number;
1668
+ /** Smallest-unit base-10 integer string -- the bridge's configured minimum. */
1669
+ bridgeMinWei: string;
1670
+ /** Server's best-effort recommendation: "execute" (balance clears the bridge minimum, so a
1671
+ * normal delivery can complete), "sweep" (below minimum -- recover directly instead), or
1672
+ * "none" (no balance to act on). Advisory only -- never used to disable an action. */
1673
+ suggestedAction: 'execute' | 'sweep' | 'none';
1674
+ /** True when the backend sees this balance as possibly mid-flight (e.g. a sweep/bridge job
1675
+ * already in progress) -- advisory caution only, must NOT disable either recovery action. */
1676
+ inFlight: boolean;
1677
+ inFlightReason?: string;
1545
1678
  /**
1546
- * 0x… 지갑 주소. 지정되면 connected pill로 렌더링된다. 없으면
1547
- * disconnected 버튼("Connect Wallet")으로 떨어진다.
1679
+ * Task 6/7: every known BSC token held at `forwarder` (not just the primary `token`/`balance`
1680
+ * pair above, which only ever reports BSC USDT) -- lets the UI surface a MISDEPOSITED token
1681
+ * (e.g. someone sent BUSD to a USDT-swap forwarder) that the top-level fields alone can't
1682
+ * represent. Optional/omitted for an older backend that predates this field -- back-compat,
1683
+ * byte-identical to pre-Task-6 behavior when absent (the UI falls back to `token`/`balance`).
1684
+ * Each entry's `suggestedAction` mirrors the top-level one's semantics, per-token.
1548
1685
  */
1549
- address?: string;
1686
+ tokens?: {
1687
+ address: string;
1688
+ symbol: string;
1689
+ decimals: number;
1690
+ /** Smallest-unit base-10 integer string -- this token's current balance at `forwarder`. */
1691
+ balance: string;
1692
+ /** Server's advisory recoverable flag for this token -- never used to disable the sweep
1693
+ * action (see `recover`'s doc in useRecovery.ts), only to decide which tokens the UI lists. */
1694
+ recoverable: boolean;
1695
+ suggestedAction: 'execute' | 'sweep' | 'none';
1696
+ }[];
1697
+ }
1698
+ /** GET /v1/recovery request query params. */
1699
+ interface RecoveryRequest {
1700
+ user: string;
1701
+ /** Selected CROSS delivery target symbol (mirrors DepositAddressRequest's `target`) -- omitted
1702
+ * (or empty) selects the configured default, preserving pre-multi-target behavior
1703
+ * byte-for-byte. Passed through verbatim as "?target=" when set. */
1704
+ target?: string;
1705
+ }
1706
+
1707
+ /** Thrown for any non-2xx API response. `status` is the HTTP status code. */
1708
+ declare class RelayApiError extends Error {
1709
+ status: number;
1710
+ /** Parsed JSON error body when the response was valid JSON, else undefined. */
1711
+ body?: unknown;
1712
+ constructor(status: number, message: string, body?: unknown);
1713
+ }
1714
+ interface RelayClientOptions {
1715
+ /** API origin, e.g. "https://orchestrator.example.com". Trailing slashes are stripped. */
1716
+ baseUrl: string;
1717
+ }
1718
+ interface RelayClient {
1719
+ /** GET /v1/config -- the curated origin catalog + fixed crossd destination. */
1720
+ getConfig(): Promise<Catalog>;
1721
+ /** POST /v1/quote -- a price-only preview, no order/deposit is created. */
1722
+ getQuote(req: QuoteRequest): Promise<QuoteResult>;
1550
1723
  /**
1551
- * 트리거 pill에 표시될 provider 아이콘 키.
1724
+ * GET /v1/deposit-address -- resolves the stable, reusable deposit
1725
+ * address for (user, originChainId, originCurrency). No amount is
1726
+ * involved and no order is created; the same address can receive any
1727
+ * number of deposits of any size. Several deposits can be aggregated into
1728
+ * one order when they jointly fund the same reusable forwarder.
1552
1729
  *
1553
- * `address`가 있는데 `provider`가 `undefined`면 SDK 조회 중인 전이
1554
- * 상태로 취급해 placeholder 원을 띄운다(`pending` 플래시 방지).
1555
- */
1556
- provider?: WalletProvider;
1557
- /**
1558
- * 트리거 버튼 aria-label에 포함될 provider 표시 이름. 미지정 시
1559
- * `provider`로부터 기본값이 유추된다 (예: 'Google', 'CROSSx').
1560
- */
1561
- providerName?: string;
1562
- /** WalletInfo 헤더에 노출될 계정 라벨 (예: "Account 1", 사용자 지정 이름). */
1563
- accountName?: string;
1564
- /** Send 주소록의 My Account 탭에 노출할 계정 목록. */
1565
- sendAccounts?: SendAccount[];
1566
- /** disconnected 상태에서 버튼 클릭 핸들러. */
1567
- onConnect?: () => void;
1568
- /** connected 상태에서 WalletInfo 하단 Disconnect 클릭 핸들러. */
1569
- onDisconnect?: () => void;
1570
- /**
1571
- * 주소 복사 성공 콜백. WalletInfo의 `onCopyAddress(address, success)` 에서
1572
- * `success === true`일 때만 호출된다.
1573
- */
1574
- onCopy?: () => void;
1575
- /** 지갑 변경 chevron 클릭 핸들러. 지정하지 않으면 chevron이 숨김 처리된다. */
1576
- onSelectWallet?: () => void;
1577
- /**
1578
- * WalletInfo 기본 액션 row의 Buy 클릭 핸들러. Promise를 반환하면 reject 시
1579
- * Buy 카드가 `onBuyDisabledMessage`와 동일한 토스트로 실패를 안내한다.
1580
- */
1581
- onBuy?: () => void | Promise<void>;
1582
- /**
1583
- * Buy 카드를 시각적으로 비활성 상태로 표시하고, 사용자가 클릭하면 이 메시지를
1584
- * 토스트로 띄운다. `onBuy`보다 우선. WalletInfoProps의 동일 prop으로 그대로
1585
- * 전달된다.
1586
- */
1587
- onBuyDisabledMessage?: string;
1588
- /**
1589
- * disconnected 버튼 라벨. 기본 'Connect Wallet'.
1590
- * 문자열 외에 ReactNode를 넘겨 아이콘-only / 커스텀 마크업을 렌더할 수 있다
1591
- * (모바일에서 아이콘만 보여주고 싶을 때 등).
1592
- */
1593
- label?: ReactNode;
1594
- /** isConnecting 상태 라벨. 기본 'Connecting...'. */
1595
- connectingLabel?: ReactNode;
1596
- /** WalletInfo 내장 Disconnect 버튼 라벨. 기본 'Disconnect'. */
1597
- disconnectLabel?: string;
1598
- /**
1599
- * 외부(호출부)에서 주입하는 className. disconnected / connecting /
1600
- * connected(트리거 pill)에 공통으로 추가된다 (기본 `cb-button` /
1601
- * `cb-pill` 클래스에 병합).
1602
- */
1603
- className?: string;
1604
- /**
1605
- * 버튼 자체(`disconnected` / `connecting` / `connected pill`)의
1606
- * CSS 커스텀 변수 오버라이드. WalletInfo popover 스타일은 별도
1607
- * `walletInfoStyle` 로 분리되어 있다.
1608
- */
1609
- style?: ConnectButtonStyle;
1610
- /**
1611
- * 트리거 pill 을 눌러 열리는 WalletInfo popover/drawer 의 CSS
1612
- * 커스텀 변수 오버라이드 (`WalletInfoStyle`).
1730
+ * `target` (Task 8) is the delivery asset's symbol from
1731
+ * `Catalog.targets` -- sent as `&target=<symbol>` only when it's a
1732
+ * non-empty string; omitted otherwise, in which case the backend
1733
+ * resolves the default target (byte-identical to pre-Task-6 behavior).
1613
1734
  */
1614
- walletInfoStyle?: WalletInfoStyle;
1615
- theme?: Theme;
1616
- env?: Environment;
1617
- showBalance?: boolean;
1618
- showPortfolio?: boolean;
1619
- drawerDirection?: DrawerDirection$1;
1620
- modal?: boolean;
1621
- connectorId?: ConnectorId;
1622
- /** Send 페이지의 일반 토큰 전송에 사용할 외부 트랜잭션 전송 함수. */
1623
- sendTransaction?: SendTransactionFn$1;
1624
- getTransactionReceipt?: GetTransactionReceiptFn;
1735
+ getDepositAddress(req: DepositAddressRequest, target?: string): Promise<DepositAddressResult>;
1625
1736
  /**
1626
- * Send 확인 단계의 가스/수수료 추정 함수. 미주입 시 SendPage Confirm 화면의
1627
- * Est. Tx Fee / Gas Limit / Max. Total Amount 행이 "—"로 표시된다.
1737
+ * GET /v1/orders/{orderId} -- current status + stepper progress for one
1738
+ * order. Reads are public (unauthenticated).
1628
1739
  */
1629
- estimateGas?: EstimateGasFn;
1740
+ getOrder(orderId: string): Promise<Order>;
1630
1741
  /**
1631
- * 상단 QR 버튼 / 기본 액션 row의 Receive / Send 콜백. (Buy는 위 onBuy로
1632
- * 정의됨.)
1742
+ * GET /v1/orders?user=... -- every order swept from deposits to that
1743
+ * user's standing address(es) (newest-first, capped server-side).
1633
1744
  */
1634
- onReceive?: () => void;
1745
+ listOrders(user: string): Promise<OrderSummary[]>;
1746
+ /** Absolute URL of the SSE order-change stream for `user`
1747
+ * (GET /v1/orders/stream?user=...). Emits `event: connected` on open,
1748
+ * `event: orders-changed` when that user's orders change, and `:
1749
+ * heartbeat` comments -- it carries no order data itself, so consumers
1750
+ * always follow up with `listOrders`. */
1751
+ ordersStreamUrl(user: string): string;
1635
1752
  /**
1636
- * @deprecated Bridge 버튼은 항상 apps.json(gametokenBridge) 웹으로
1637
- * 이동한다. 이 콜백은 더 이상 호출되지 않는다.
1753
+ * GET /v1/recovery?user=... -- permissionless self-recovery status for a
1754
+ * user's forwarder on BSC (Task 1). `req.target` (optional) selects which
1755
+ * per-target forwarder/factory to report -- omitted selects the
1756
+ * configured default, byte-identical to pre-multi-target behavior.
1757
+ * Purely informational -- fetching it never triggers or blocks any
1758
+ * on-chain action. The response's `tokens[]` (Task 6/7 -- every known BSC
1759
+ * token held at the forwarder) flows through as-is: it's plain JSON, so no
1760
+ * extra parsing/mapping is needed beyond RecoveryInfo's own typing, and
1761
+ * it's simply absent/undefined for an older backend that predates it.
1638
1762
  */
1639
- onBridge?: () => void;
1640
- onSend?: () => void;
1641
- bridgeTokens?: BridgeToken[];
1642
- bridgeHistory?: BridgeHistoryItem[];
1643
- getBridgeQuote?: BridgeQuoteFn;
1644
- getBridgeToTokens?: BridgeGetToTokensFn;
1645
- getBridgeApproval?: BridgeGetApprovalFn;
1646
- approveBridge?: BridgeApproveFn;
1647
- submitBridge?: BridgeSubmitFn;
1763
+ getRecovery(req: RecoveryRequest): Promise<RecoveryInfo>;
1648
1764
  }
1649
-
1650
- /**
1651
- * 3-state wallet connect button. Caller drives the visual state:
1652
- *
1653
- * - `isConnecting === true` → 스피너 disabled 버튼
1654
- * - `address` 있음 → WalletInfo + connected pill
1655
- * - `address`가 있는데 `provider` 없음 → SDK 조회 전이 상태, placeholder 원
1656
- * - 둘 다 없음 → "Connect Wallet" 버튼
1657
- *
1658
- * view-only: wagmi / connect-kit 같은 web3 의존성은 갖지 않으며 모든
1659
- * 상태/데이터/콜백은 props로 주입받는다. 실제 wagmi 연결 로직은
1660
- * `@nexus-cross/connect-kit-react`의 상위 래퍼에서 수행한다.
1661
- */
1662
- declare function ConnectButton({ isConnecting, address, provider, providerName, accountName, sendAccounts, onConnect, onDisconnect, onCopy, onSelectWallet, onBuy, onBuyDisabledMessage, label, connectingLabel, disconnectLabel, className, theme, env, showBalance, showPortfolio, drawerDirection, modal, connectorId, style, walletInfoStyle, sendTransaction, getTransactionReceipt, estimateGas, onReceive, onBridge, onSend, bridgeTokens, bridgeHistory, getBridgeQuote, getBridgeToTokens, getBridgeApproval, approveBridge, submitBridge, }: ConnectButtonProps): react_jsx_runtime.JSX.Element;
1663
-
1664
1765
  /**
1665
- * Wallet provider icons used by `ConnectButton`. Ported from
1666
- * `@nexus-cross/connect-kit-wagmi` so dapp-ui stays a self-contained,
1667
- * bundler-agnostic module (no SVG loader required) and doesn't pull in a
1668
- * web3 dependency for icon assets.
1669
- *
1670
- * Each icon is an inline `data:image/svg+xml` URI so it can be consumed
1671
- * directly by `<img src={...}>`.
1766
+ * Builds a framework-agnostic Relay API client. Uses plain `fetch` only --
1767
+ * no react-query, no RainbowKit/wagmi. `baseUrl` is passed in explicitly (no
1768
+ * `import.meta.env` coupling) so the widget can be embedded in any host app's
1769
+ * own config/env story.
1672
1770
  *
1673
- * Source references mirror the ones in `connect-kit-wagmi/src/wallets/icons.ts`:
1674
- * wallet-crossx.svg → CROSSX_ICON (cross / cross-extension / cross-embedded fallback)
1675
- * wallet-metamask.svg → METAMASK_ICON
1676
- * wallet-binance.svg → BINANCE_ICON
1771
+ * No API key: the backend has no inbound key gate (upstream 83845fb removed
1772
+ * the dead `apiKey`/X-API-Key plumbing -- a security control that does not
1773
+ * exist must not appear in a public type).
1677
1774
  */
1678
- declare const CROSSX_ICON: string;
1679
- declare const METAMASK_ICON: string;
1680
- declare const BINANCE_ICON: string;
1681
- declare const GOOGLE_ICON: string;
1682
- declare const APPLE_ICON: string;
1775
+ declare function createRelayClient(options: RelayClientOptions): RelayClient;
1683
1776
 
1684
- /**
1685
- * `SkillsButton`의 `style` prop 타입. 표준 `CSSProperties` 위에
1686
- * `--sb-*` CSS 커스텀 변수 키를 추가해 자동완성을 지원한다.
1687
- *
1688
- * 사용 예: `style={{ "--sb-color": "white", "--sb-bg": "rgba(0,0,0,0.4)" }}`
1689
- *
1690
- * CSS 변수는 자식 요소(아이콘, 스피너)로 cascading 되므로, `--sb-color`
1691
- * 하나만 바꿔도 텍스트·아이콘·스피너가 모두 같은 색을 따라간다.
1692
- */
1693
- interface SkillsButtonStyle extends CSSProperties {
1694
- "--sb-bg"?: string;
1695
- "--sb-border"?: string;
1696
- "--sb-border-hover"?: string;
1697
- "--sb-color"?: string;
1698
- "--sb-color-hover"?: string;
1699
- "--sb-radius"?: string;
1700
- "--sb-height"?: string;
1701
- "--sb-padding"?: string;
1702
- "--sb-gap"?: string;
1703
- "--sb-font-size"?: string;
1704
- "--sb-font-weight"?: string | number;
1705
- "--sb-line-height"?: string | number;
1706
- "--sb-letter-spacing"?: string;
1707
- "--sb-blur"?: string;
1708
- "--sb-border-width"?: string;
1709
- "--sb-icon-size"?: string;
1710
- "--sb-icon-hover-rotation"?: string;
1711
- "--sb-spinner-size"?: string;
1712
- "--sb-spinner-thumb"?: string;
1713
- "--sb-spinner-track"?: string;
1714
- "--sb-disabled-opacity"?: string | number;
1715
- "--sb-press-scale"?: string | number;
1716
- "--sb-hover-duration"?: string;
1717
- "--sb-icon-duration"?: string;
1718
- "--sb-easing"?: string;
1719
- }
1720
- interface SkillsButtonProps {
1721
- /** Button text label */
1722
- label?: string;
1723
- /** Skills service URL or path to navigate to */
1724
- href?: string;
1725
- /** Called when button is clicked (instead of navigation if provided) */
1726
- onClick?: () => void | Promise<void>;
1727
- /** Optional CSS class name (merged with built-in `.sb-button`) */
1728
- className?: string;
1729
- /** Inline style + CSS custom property overrides (`SkillsButtonStyle`) */
1730
- style?: SkillsButtonStyle;
1731
- /** Light/dark surface preset (sets `data-theme`). Defaults to no preset. */
1732
- theme?: Theme;
1733
- /** Disable the button */
1734
- disabled?: boolean;
1735
- /** Whether button is in loading state */
1736
- isLoading?: boolean;
1737
- /** Label shown while loading */
1738
- loadingLabel?: string;
1739
- /** Open link in new tab */
1740
- openInNewTab?: boolean;
1741
- /** Button type attribute */
1742
- type?: "button" | "submit" | "reset";
1777
+ interface DefaultToken {
1778
+ chainId: number;
1779
+ /** Token contract address, or the zero address for the chain's native asset. */
1780
+ address: string;
1743
1781
  }
1744
1782
 
1745
- /**
1746
- * @deprecated 이동 대상은 apps.json(skills)이 단일 소스다. 이 상수는 더 이상
1747
- * 폴백으로 쓰이지 않으며 하위 호환(공개 export)용으로만 남아 있다.
1748
- */
1749
- declare const DEFAULT_SKILLS_HREF = "https://www.onechain.nexus/skills";
1750
- declare function SkillsButton({ label, href, onClick, className, style, theme, disabled, isLoading, loadingLabel, openInNewTab, type, }: SkillsButtonProps): react_jsx_runtime.JSX.Element;
1751
-
1752
- /** One origin-side ERC-20 (or native, address = zero) token the UI may offer. */
1753
- interface Token {
1754
- symbol: string;
1755
- address: string;
1756
- decimals: number;
1757
- logoUrl?: string;
1783
+ type Hex = `0x${string}`;
1784
+ interface RelayTxRequest {
1785
+ chainId: number;
1786
+ to: Hex;
1787
+ value?: bigint;
1788
+ data?: Hex;
1758
1789
  }
1759
- /** The fixed destination asset every order delivers: crossd on CROSS. */
1760
- interface Destination {
1761
- symbol: string;
1790
+ interface RelayContractCall {
1762
1791
  chainId: number;
1763
- address: string;
1792
+ address: Hex;
1793
+ abi: readonly unknown[];
1794
+ functionName: string;
1795
+ args: readonly unknown[];
1796
+ }
1797
+ interface RelayBalance {
1798
+ value: bigint;
1764
1799
  decimals: number;
1765
- note?: string;
1800
+ symbol: string;
1766
1801
  }
1767
- /** Origin chain VM family: "evm" (default) or "svm" (Solana). */
1768
- type ChainKind = 'evm' | 'svm';
1769
- /**
1770
- * One delivery-side asset an order's crossd-equivalent output may be paid
1771
- * out as -- the default target (isDefault: true) is crossd itself
1772
- * (byte-identical to Catalog.destination); non-default targets are
1773
- * alternate payout assets the user may opt into (see GET /v1/deposit-address's
1774
- * `target` query param). `external: true` marks a target delivered via an
1775
- * external adapter (e.g. pONEUSD) rather than natively minted -- the UI
1776
- * shows an extra trust note for these (Task 9).
1777
- */
1778
- type Target = {
1779
- symbol: string;
1780
- address: string;
1781
- decimals: number;
1782
- isDefault: boolean;
1783
- external: boolean;
1784
- };
1785
- /** One supported (chain, token) pair the UI can offer as an order's source. */
1786
- interface OriginOption {
1802
+ type SendTransactionFn = (req: RelayTxRequest) => Promise<Hex>;
1803
+ type WriteContractFn = (call: RelayContractCall) => Promise<Hex>;
1804
+ type ReadContractFn = (call: RelayContractCall) => Promise<unknown>;
1805
+ type SwitchChainFn = (chainId: number) => Promise<void>;
1806
+ type WaitForReceiptFn = (p: {
1787
1807
  chainId: number;
1788
- chainName: string;
1789
- /**
1790
- * VM family of the origin chain. "svm" (Solana) origins are display-only:
1791
- * the connected EVM wallet cannot sign them, so no one-click deposit or
1792
- * balance read is offered -- the user pays out-of-band from a Solana wallet.
1793
- */
1794
- kind: ChainKind;
1795
- token: Token;
1796
- /** Smallest-unit base-10 integer string (matches Token.decimals). */
1797
- minAmount: string;
1798
- /** Smallest-unit base-10 integer string; absent = no configured cap. */
1799
- maxAmount?: string;
1808
+ hash: Hex;
1809
+ }) => Promise<{
1810
+ status: "success" | "reverted";
1811
+ }>;
1812
+ type GetBalanceFn = (p: {
1813
+ chainId: number;
1814
+ address: Hex;
1815
+ token?: Hex;
1816
+ }) => Promise<RelayBalance>;
1817
+ /** 지갑 주입 props — 전부 optional, 미주입 시 graceful degradation. */
1818
+ interface RelayWalletProps {
1819
+ walletAddress?: string;
1820
+ walletChainId?: number;
1821
+ sendTransaction?: SendTransactionFn;
1822
+ writeContract?: WriteContractFn;
1823
+ readContract?: ReadContractFn;
1824
+ switchChain?: SwitchChainFn;
1825
+ waitForReceipt?: WaitForReceiptFn;
1826
+ getBalance?: GetBalanceFn;
1827
+ }
1828
+ /** A recovery transaction confirmed successfully on BNB Smart Chain. */
1829
+ interface RecoverySuccessResult {
1830
+ action: "execute" | "sweep";
1831
+ forwarder: string;
1832
+ actionTxHash: string;
1833
+ /** Present only when this attempt first had to deploy the forwarder. */
1834
+ deployTxHash?: string;
1800
1835
  }
1836
+ type RelayTheme = "dark" | "light";
1837
+ type RelayDrawerDirection = "bottom" | "left" | "right" | "top";
1801
1838
  /**
1802
- * Which order-creation flow is live: "standing" (GET /v1/deposit-address
1803
- * returns a stable, reusable per-user address) or "per_order" (the legacy
1804
- * flow, a fresh forwarder minted per POST /v1/orders). See
1805
- * internal/catalog.Catalog.AddressMode's doc comment.
1839
+ * Props of the `<RelayDeposit>` compound root (Task 11) — the union of
1840
+ *
1841
+ * * `RelayWalletProps` (injected wallet capabilities, all optional),
1842
+ * * the source widget's own configuration props (relay-protocol
1843
+ * `packages/relay-widget/src/components/RelayDeposit.tsx`), minus its
1844
+ * `theme: 'auto'` option, which the shared modal shell doesn't have, and
1845
+ * * `ResponsiveShellProps`' modal/drawer knobs (theme/breakpoint/size/open),
1846
+ * re-declared here rather than extended so the public surface reads as one
1847
+ * flat prop list.
1848
+ *
1849
+ * `children` holds `<RelayDeposit.Trigger>` / `<RelayDeposit.Content>`.
1806
1850
  */
1807
- type AddressMode = 'standing' | 'per_order';
1808
- /** GET /v1/config response: the curated catalog of origins + fixed destination. */
1809
- interface Catalog {
1810
- destination: Destination;
1811
- origins: OriginOption[];
1812
- addressMode: AddressMode;
1851
+ interface RelayDepositProps extends RelayWalletProps {
1852
+ /** Pre-built client. Takes precedence over apiBaseUrl. */
1853
+ client?: RelayClient;
1854
+ /** Used to build a client via createRelayClient when `client` isn't passed. */
1855
+ apiBaseUrl?: string;
1813
1856
  /**
1814
- * The user-selectable delivery targets an order may pay out as (Task 4).
1815
- * Always includes the default target (crossd, byte-identical to
1816
- * `destination`). Defaults to `[]` when the backend response omits this
1817
- * field entirely -- back-compat with an older backend that predates
1818
- * per-target delivery (see createRelayClient's getConfig).
1857
+ * Selects a built-in default relay API base URL (dev/stage/production) when
1858
+ * `apiBaseUrl` isn't passed. `client`/`apiBaseUrl` still take precedence --
1859
+ * this is only consulted when neither is provided. Omitted falls back to
1860
+ * the same global environment resolution every other dapp-ui feature uses
1861
+ * (see `resolveEnvironment`), defaulting to production.
1819
1862
  */
1820
- targets: Target[];
1821
- }
1822
- /** POST /v1/quote request body. */
1823
- interface QuoteRequest {
1824
- originChainId: number;
1825
- originCurrency: string;
1826
- /** Smallest-unit base-10 integer string. */
1827
- amount: string;
1863
+ environment?: Environment;
1864
+ /** Restrict the catalog's origins to these chain ids. */
1865
+ chains?: number[];
1866
+ /** Controlled recipient; when provided the recipient input is hidden and no wallet
1867
+ * connection is required to fetch a deposit address. Defaults to `walletAddress`. */
1868
+ recipient?: string;
1869
+ /** Require a valid connected wallet before the deposit flow can issue an
1870
+ * address, quote an amount, or start live order/recovery reads. When enabled,
1871
+ * the recipient is pinned to `walletAddress`; a controlled `recipient` cannot
1872
+ * redirect the connected user's deposit. Defaults to `true` when
1873
+ * `showRecipientInput` is explicitly `false`, otherwise `false` for the
1874
+ * low-level public-address integration. `CrossRelayDeposit` always enables
1875
+ * this guard. */
1876
+ requireWalletConnection?: boolean;
1877
+ /** Hide the editable recipient input even when `recipient` is NOT controlled
1878
+ * (default `true` = original behavior). Hosts that lock the recipient to the
1879
+ * connected wallet set this `false` so a disconnected user sees a connect
1880
+ * prompt instead of a free-form address field — the deposit address can then
1881
+ * only ever resolve to the logged-in wallet. */
1882
+ showRecipientInput?: boolean;
1883
+ /** Controlled human-decimal amount; when provided the amount input is hidden. Optional —
1884
+ * it only drives the quote preview, and never blocks the deposit address. */
1885
+ amount?: string;
1886
+ /** Hide the amount input entirely (address-only, send-any-amount). Independent of `amount`. */
1887
+ hideAmount?: boolean;
1888
+ /** Render the EVM one-click deposit button (default `false`: the modal only
1889
+ * offers the QR / copy-address manual deposit path). Opt in with `true` for
1890
+ * hosts whose users connect external wallets that can sign on the origin
1891
+ * chains — CROSS embedded-wallet users never can, hence the off default. */
1892
+ showOneClickDeposit?: boolean;
1893
+ /** Enable recovery actions (default `false` for low-level RelayDeposit).
1894
+ * The Recover tab remains visible so the Deposit navigation always has the
1895
+ * same three entries; when disabled it shows an unavailable-state message.
1896
+ * Recovery signs on BSC with the connected wallet, which CROSS embedded-wallet
1897
+ * users can never do — so actions stay unavailable unless a host serving
1898
+ * external wallets opts in. Even opted in, it still requires the injected
1899
+ * `writeContract`/`readContract`/`waitForReceipt` capability trio. */
1900
+ showRecovery?: boolean;
1901
+ /** Which (chainId, token address) to default-select once the catalog loads. */
1902
+ defaultToken?: DefaultToken;
1903
+ /** Restricts the delivery-token picker to these symbols from `Catalog.targets`. */
1904
+ targetTokens?: string[];
1905
+ /** Which delivery-token symbol to select initially, instead of the catalog's own default. */
1906
+ defaultTarget?: string;
1907
+ /** Whether to render the delivery-token picker at all. Default `true`; the picker only
1908
+ * ever renders when there is more than one target to choose from either way. */
1909
+ showTargetSelector?: boolean;
1910
+ /** Overrides the pinned factory set the one-click deposit verifies the forwarder against. */
1911
+ trustedFactories?: readonly string[];
1912
+ onDepositAddress?: (result: DepositAddressResult) => void;
1913
+ /** Fired once per one-click deposit that CONFIRMED successfully, with the tx
1914
+ * hash. NOT fired on submission, and NOT fired for a tx that reverted --
1915
+ * watch `depositState` (phase/txHash/reverted) for those. Safe to treat as
1916
+ * "the funds moved" (upstream 83845fb). */
1917
+ onDeposited?: (txHash: string) => void;
1918
+ /** Fired once after a recovery action receipt confirms successfully. */
1919
+ onRecoverySuccess?: (result: RecoverySuccessResult) => void;
1920
+ onError?: (error: Error) => void;
1921
+ /** Called by the `Connect Wallet` CTA under the locked card that stands in for the QR
1922
+ * while the required connected wallet (or, in low-level public-address mode,
1923
+ * a usable recipient) is absent. Omitted — the locked card renders as text
1924
+ * only, with no button. */
1925
+ onRequestConnect?: () => void;
1926
+ /** @deprecated The Deposit footer entry was removed. Retained as a no-op
1927
+ * compatibility prop so existing hosts do not need an immediate migration. */
1928
+ onOpenHistory?: () => void;
1929
+ /** Extra class name(s) for the modal/drawer content element. */
1930
+ className?: string;
1931
+ theme?: RelayTheme;
1932
+ mobileBreakpoint?: number;
1933
+ drawerDirection?: RelayDrawerDirection;
1934
+ dialogWidth?: string;
1935
+ drawerMaxWidth?: string;
1936
+ drawerMinWidth?: string;
1937
+ style?: CSSProperties;
1938
+ open?: boolean;
1939
+ onOpenChange?: (open: boolean) => void;
1940
+ children?: ReactNode;
1828
1941
  }
1829
- /** POST /v1/quote response body. */
1830
- interface QuoteResult {
1831
- /** Smallest-unit (BSC USDT, 18 decimals) base-10 integer string. */
1832
- expectedBscUsdt: string;
1833
- belowMin: boolean;
1942
+ /**
1943
+ * Props of the `<RelayRecovery>` compound root — the standalone
1944
+ * "Recover stuck funds" modal, i.e. the deposit wizard's gear panel lifted out
1945
+ * into a modal of its own so a host can offer recovery WITHOUT the deposit
1946
+ * flow (the gear inside `<RelayDeposit>` is unaffected and still opt-in via
1947
+ * `showRecovery`).
1948
+ *
1949
+ * Extends `RelayWalletProps` because recovery is signing-first: unlike
1950
+ * `<RelayHistory>` (read-only, no wallet capabilities at all), the whole point
1951
+ * of this modal is that the USER signs the permissionless recovery tx on BSC.
1952
+ * A wallet missing the `writeContract`/`readContract`/`waitForReceipt` trio
1953
+ * gets a short note instead of a dead panel.
1954
+ *
1955
+ * `children` holds `<RelayRecovery.Trigger>` / `<RelayRecovery.Content>`.
1956
+ */
1957
+ interface RelayRecoveryProps extends RelayWalletProps {
1958
+ /** Pre-built client. Takes precedence over apiBaseUrl. */
1959
+ client?: RelayClient;
1960
+ /** Used to build a client via createRelayClient when `client` isn't passed. */
1961
+ apiBaseUrl?: string;
1834
1962
  /**
1835
- * Smallest-unit (crossd, catalog.destination.decimals) base-10 integer
1836
- * string. Currently assumed at 1:1 parity with BSC USDT -- see
1837
- * assumesParity.
1963
+ * Selects a built-in default relay API base URL (dev/stage/production) when
1964
+ * `apiBaseUrl` isn't passed. `client`/`apiBaseUrl` still take precedence --
1965
+ * this is only consulted when neither is provided. Omitted falls back to
1966
+ * the same global environment resolution every other dapp-ui feature uses
1967
+ * (see `resolveEnvironment`), defaulting to production.
1838
1968
  */
1839
- expectedCrossd: string;
1840
- assumesParity: boolean;
1969
+ environment?: Environment;
1841
1970
  /**
1842
- * The fee DEDUCTED FROM the bridged amount, in USD, as a decimal string --
1843
- * Relay's relayer fee plus any app surcharge (upstream af35dd5). It is
1844
- * exactly what accounts for the gap between what the user sends and
1845
- * `expectedBscUsdt`.
1846
- *
1847
- * It deliberately EXCLUDES the user's own origin-chain gas: that is paid from
1848
- * their wallet in the origin chain's native token, the wallet already quotes
1849
- * it at signing time, and none of it comes out of the bridged amount.
1850
- *
1851
- * Absent means UNKNOWN, never free -- render absence as absence. "$0.00" for
1852
- * a fee nobody could compute is the one wrong reading. (A genuine zero, e.g.
1853
- * the direct BSC-USDT route with no Relay leg, is also absent rather than
1854
- * "0": no Relay leg means no relayer fee to report.)
1971
+ * Optional assertion of whose forwarder to check/recover. Recovery is always
1972
+ * pinned to the valid connected `walletAddress`; when this value is supplied
1973
+ * it must match that wallet. A missing/invalid wallet or mismatch renders a
1974
+ * short note and makes ZERO requests (no catalog, no recovery lookup).
1855
1975
  */
1856
- feeUsd?: string;
1976
+ recipient?: string;
1857
1977
  /**
1858
- * How many seconds this quote stays valid. Drives the refresh cadence in
1859
- * useDepositAddress -- the widget previously hardcoded 30s with no
1860
- * relationship to the quote's real lifetime. Absent when the backend has no
1861
- * TTL configured, in which case the client keeps its own default interval.
1862
- *
1863
- * There is deliberately no eta/duration field here. An earlier version of
1864
- * this type carried `etaSeconds` on the assumption that Relay's quote
1865
- * reports timing; it does not -- the response has no ETA field of any kind
1866
- * -- so it was removed rather than left permanently undefined.
1978
+ * Overrides the pinned factory allowlist recovery verifies against before
1979
+ * signing -- only needed by a self-hosted deployment running its own
1980
+ * factories. Same meaning (and the same fail-closed reasoning) as
1981
+ * `RelayDepositProps.trustedFactories`.
1867
1982
  */
1868
- ttl?: number;
1869
- }
1870
- /** GET /v1/deposit-address request query params -- no amount: a standing
1871
- * address is resolved purely from (user, originChainId, originCurrency),
1872
- * independent of any deposit size. */
1873
- interface DepositAddressRequest {
1874
- user: string;
1875
- originChainId: number;
1876
- originCurrency: string;
1983
+ trustedFactories?: readonly string[];
1984
+ /** Fired once after a recovery action receipt confirms successfully. */
1985
+ onRecoverySuccess?: (result: RecoverySuccessResult) => void;
1986
+ onError?: (e: Error) => void;
1987
+ /** Extra class name(s) for the modal/drawer content element. */
1988
+ className?: string;
1989
+ theme?: RelayTheme;
1990
+ mobileBreakpoint?: number;
1991
+ drawerDirection?: RelayDrawerDirection;
1992
+ dialogWidth?: string;
1993
+ drawerMaxWidth?: string;
1994
+ drawerMinWidth?: string;
1995
+ style?: CSSProperties;
1996
+ open?: boolean;
1997
+ onOpenChange?: (open: boolean) => void;
1998
+ children?: ReactNode;
1877
1999
  }
1878
2000
  /**
1879
- * GET /v1/deposit-address response body -- a stable, reusable deposit
1880
- * address for this (user, origin chain, origin token). The same request
1881
- * always resolves to the same address; no order/deposit is created by
1882
- * fetching it, and it accepts any number of deposits over time (see
1883
- * internal/standing.Service.GetOrCreateDepositAddress).
2001
+ * Props of the `<RelayHistory>` compound root (Task 12) — the standalone
2002
+ * transfer-history modal built on the shared `ResponsiveShell` +
2003
+ * `useRelayOrders`. `RelayDepositProps`'s simpler sibling: no wizard step,
2004
+ * no catalog/target picking, no wallet-injected send/write capabilities —
2005
+ * just an address to look up orders for and a list to render.
2006
+ *
2007
+ * `children` holds `<RelayHistory.Trigger>` / `<RelayHistory.Content>`.
1884
2008
  */
1885
- interface DepositAddressResult {
1886
- user: string;
1887
- forwarder: string;
1888
- version: number;
1889
- depositAddress: string;
1890
- originChainId: number;
1891
- originCurrency: string;
2009
+ interface RelayHistoryProps {
2010
+ /** Pre-built client. Takes precedence over apiBaseUrl. */
2011
+ client?: RelayClient;
2012
+ /** Used to build a client via createRelayClient when `client` isn't passed. */
2013
+ apiBaseUrl?: string;
2014
+ /**
2015
+ * Selects a built-in default relay API base URL (dev/stage/production) when
2016
+ * `apiBaseUrl` isn't passed. `client`/`apiBaseUrl` still take precedence --
2017
+ * this is only consulted when neither is provided. Omitted falls back to
2018
+ * the same global environment resolution every other dapp-ui feature uses
2019
+ * (see `resolveEnvironment`), defaulting to production.
2020
+ */
2021
+ environment?: Environment;
2022
+ /** History subject. Falls back to `walletAddress`; empty-state UI when
2023
+ * neither resolves to a valid address. */
2024
+ recipient?: string;
2025
+ walletAddress?: string;
2026
+ onError?: (e: Error) => void;
2027
+ /** Notified with the resolved explorer URL when a history row's tx link is
2028
+ * clicked. Fire-and-forget -- unlike `OnOutlink` elsewhere in dapp-ui, it
2029
+ * does not intercept navigation; the link still opens in a new tab as normal. */
2030
+ onOutlink?: (url: string) => void;
2031
+ /** Extra class name(s) for the modal/drawer content element. */
2032
+ className?: string;
2033
+ theme?: RelayTheme;
2034
+ mobileBreakpoint?: number;
2035
+ drawerDirection?: RelayDrawerDirection;
2036
+ dialogWidth?: string;
2037
+ drawerMaxWidth?: string;
2038
+ drawerMinWidth?: string;
2039
+ style?: CSSProperties;
2040
+ open?: boolean;
2041
+ onOpenChange?: (open: boolean) => void;
2042
+ children?: ReactNode;
2043
+ }
2044
+
2045
+ interface RelayDepositContentProps {
2046
+ /** Extra class name(s) for the dialog/drawer content element. Falls back to
2047
+ * `<RelayDeposit>`'s own `className`. */
2048
+ className?: string;
1892
2049
  }
1893
2050
  /**
1894
- * One row of GET /v1/orders?user=...'s "orders" array. A single order can
1895
- * aggregate several deposits made to the same reusable forwarder; `deposits[]`
1896
- * is the per-arrival identity. Amount fields are smallest-unit base-10 integer
1897
- * strings, "" when not yet known.
2051
+ * `<RelayDeposit.Content>` — the modal/drawer surface. The deposit body is a
2052
+ * child of `ShellContent`, i.e. of radix's `Dialog.Portal` / vaul's
2053
+ * `Drawer.Portal`, which render nothing while closed. The state it renders is
2054
+ * NOT its own any more: `<RelayDeposit>` mounts the wizard engine above the
2055
+ * shell for exactly as long as the modal is open, so "no request before open"
2056
+ * and "everything resets on close" still hold -- while a breakpoint crossing
2057
+ * mid-flow now only rebuilds this DOM, not the flow.
1898
2058
  */
1899
- interface OrderSummary {
1900
- orderId: string;
1901
- status: string;
1902
- source: string;
1903
- amountIn: string;
1904
- expectedOut: string;
1905
- bscBridgeTx: string;
1906
- originChainId: number;
1907
- originCurrency: string;
1908
- /** CROSS delivery-token symbol this order pays out as (a Catalog.targets
1909
- * symbol, e.g. "pONEUSD"); "" / omitted means the default target. Used to
1910
- * label the "out" side with the actual delivered token. */
1911
- target?: string;
1912
- forwarderVersion: number;
1913
- /** RFC3339 timestamp. */
1914
- createdAt: string;
1915
- /** What the user ACTUALLY received, observed from the CROSS delivery
1916
- * transfer. Distinct from expectedOut, which is the pre-delivery projection
1917
- * after fees -- the two differ by swap slippage and any executor fallback.
1918
- * "" until delivery, and for orders delivered before the backend recorded it. */
1919
- amountOut?: string;
1920
- /** The CROSS-side transaction that delivered the funds. "" until delivery. */
1921
- deliveryTxHash?: string;
1922
- /** RFC3339 timestamp of the COMPLETED transition -- when the user received
1923
- * the funds. Absent for orders that never completed. */
1924
- completedAt?: string;
1925
- /** The individual deposits this delivery paid out, oldest first. There can be
1926
- * SEVERAL: a user may top up a little at a time and the sweeper aggregates
1927
- * whatever has arrived into one order. Empty when the backend has not
1928
- * attributed the deposits to this order yet. */
1929
- deposits?: OrderDeposit[];
2059
+ declare function RelayDepositContent({ className }: RelayDepositContentProps): react_jsx_runtime.JSX.Element;
2060
+
2061
+ interface RelayDepositTriggerProps {
2062
+ /** Render the child as the trigger instead of wrapping it. Defaults to
2063
+ * `true` whenever a child is supplied, matching
2064
+ * `WalletConnectModalTrigger`'s `asChild ?? children != null`. */
2065
+ asChild?: boolean;
2066
+ children?: ReactNode;
1930
2067
  }
1931
- /** One deposit inside an order, as GET /v1/orders reports it.
2068
+ /**
2069
+ * Thin pass-through to `ShellTrigger` (radix `Dialog.Trigger` on desktop /
2070
+ * vaul `Drawer.Trigger` on mobile) so hosts write
2071
+ * `<RelayDeposit.Trigger><button>…</button></RelayDeposit.Trigger>` without
2072
+ * knowing which primitive is active. Falls back to a plain default button when
2073
+ * no child is given, same as `WalletConnectModalTrigger`.
1932
2074
  *
1933
- * originChainId/originCurrency are the chain and token the user ACTUALLY paid,
1934
- * which the order itself cannot report (one reusable deposit address serves
1935
- * every origin route, so the swept balance carries no memory of where it came
1936
- * from). They are absent when the backend has not attributed the deposit --
1937
- * for a DIRECT BSC deposit that is permanent and correct, since it has no
1938
- * cross-chain leg. */
1939
- interface OrderDeposit {
1940
- /** Amount that arrived at the forwarder, in BSC USDT base units. NOT the
1941
- * amount sent on the origin chain, which is larger by Relay's fees and
1942
- * denominated in the origin token's own decimals. */
1943
- amount: string;
1944
- blockNumber: number;
1945
- originChainId?: number;
1946
- originCurrency?: string;
1947
- /** The BSC-side arrival (transfer into the forwarder). */
1948
- txHash: string;
1949
- /** The user's own send on the ORIGIN chain -- what the "Deposit" step links
1950
- * to. Absent when unattributed. */
1951
- originTxHash?: string;
1952
- }
1953
- type StepStatus = 'done' | 'active' | 'pending';
1954
- interface OrderStep {
1955
- key: string;
1956
- label: string;
1957
- status: StepStatus;
2075
+ * Wrapped in `<TrackingBoundary feature="relay">` for the same reason
2076
+ * `WalletConnectModalTrigger` is: the `data-track="open"` attribute below (and
2077
+ * on any host-supplied child that carries one) is only picked up by the
2078
+ * analytics delegate a boundary installs. Without it the open click is silently
2079
+ * untracked, since the trigger lives OUTSIDE the portaled `<Content>` boundary.
2080
+ */
2081
+ declare function RelayDepositTrigger({ asChild, children }: RelayDepositTriggerProps): react_jsx_runtime.JSX.Element;
2082
+
2083
+ declare function RelayDepositRoot(props: RelayDepositProps): react_jsx_runtime.JSX.Element;
2084
+ declare const RelayDeposit: typeof RelayDepositRoot & {
2085
+ Trigger: typeof RelayDepositTrigger;
2086
+ Content: typeof RelayDepositContent;
2087
+ };
2088
+
2089
+ interface RelayHistoryContentProps {
2090
+ /** Extra class name(s) for the dialog/drawer content element. Falls back to
2091
+ * `<RelayHistory>`'s own `className`. */
2092
+ className?: string;
1958
2093
  }
1959
2094
  /**
1960
- * GET /v1/orders/{orderId} response body. "status" is the raw backend state
1961
- * (e.g. "AWAITING_DEPOSIT", "COMPLETED", "FAILED", ...); "steps" is the
1962
- * friendlier 3-stage deposit -> bridge -> deliver breakdown the UI renders.
2095
+ * `<RelayHistory.Content>` — the modal/drawer surface. Like
2096
+ * `RelayDepositContent`, this is a child of `ShellContent`, i.e. of radix's
2097
+ * `Dialog.Portal` / vaul's `Drawer.Portal`, which render nothing while
2098
+ * closed: no `listOrders` request happens before the modal is opened, and the
2099
+ * subtree unmounts on close -- there is no per-open state here to reset
2100
+ * explicitly (unlike `RelayDepositBody`'s step/panel state), so
2101
+ * unmount-by-portal is the whole story.
1963
2102
  */
1964
- interface Order {
1965
- orderId: string;
1966
- status: string;
1967
- steps: OrderStep[];
1968
- bridgeIndex: string;
1969
- txs: {
1970
- bscBridge: string;
1971
- crossFinalize: string;
1972
- crossExecute: string;
1973
- };
2103
+ declare function RelayHistoryContent({ className }: RelayHistoryContentProps): react_jsx_runtime.JSX.Element;
2104
+
2105
+ interface RelayHistoryTriggerProps {
2106
+ /** Render the child as the trigger instead of wrapping it. Defaults to
2107
+ * `true` whenever a child is supplied, matching `RelayDepositTrigger`'s
2108
+ * (and `WalletConnectModalTrigger`'s) `asChild ?? children != null` rule. */
2109
+ asChild?: boolean;
2110
+ children?: ReactNode;
1974
2111
  }
1975
2112
  /**
1976
- * GET /v1/recovery?user=... response body -- the permissionless self-recovery
1977
- * status for a user's standing forwarder on BSC. Task 1's endpoint; consumed
1978
- * by useRecovery (Task 2) to drive the settings-menu "Recover stuck funds"
1979
- * panel. Every recovery tx (factory.deploy, forwarder.execute/sweepToUser)
1980
- * takes no destination argument -- funds always route to `forwarder`'s
1981
- * immutable recipient, so this info is advisory/orientation only, never a
1982
- * capability check the UI should use to block the user.
2113
+ * Thin pass-through to `ShellTrigger` (radix `Dialog.Trigger` on desktop /
2114
+ * vaul `Drawer.Trigger` on mobile), mirroring `RelayDepositTrigger` so hosts
2115
+ * write `<RelayHistory.Trigger><button>…</button></RelayHistory.Trigger>`
2116
+ * without knowing which primitive is active. Falls back to a plain default
2117
+ * button when no child is given.
2118
+ *
2119
+ * Wrapped in `<TrackingBoundary feature="relay">` for the same reason
2120
+ * `RelayDepositTrigger`/`WalletConnectModalTrigger` are: `data-track="open"` is
2121
+ * only read by the delegate a boundary installs, and this trigger sits OUTSIDE
2122
+ * the portaled `<Content>`'s own boundary.
1983
2123
  */
1984
- interface RecoveryInfo {
1985
- user: string;
1986
- /** The user's forwarder address on BSC for the requested target (CREATE2, deterministic from
1987
- * user+version+target). */
1988
- forwarder: string;
1989
- /** Whether `forwarder` has been deployed on-chain yet. */
1990
- isDeployed: boolean;
1991
- /** BSC USDT token contract address -- always BSC USDT regardless of `target` (the forwarder
1992
- * holds BSC USDT pre-bridge in every case). */
1993
- token: string;
1994
- decimals: number;
1995
- /** Smallest-unit base-10 integer string -- the forwarder's current token balance. */
1996
- balance: string;
1997
- /** The factory that deploys/derives `forwarder` for the requested target: the
1998
- * DepositorForwarderFactory for a depositor-kind target, the StandingForwarderFactory
1999
- * otherwise (recovery follow-up, multi-target). */
2000
- factory: string;
2001
- version: number;
2002
- /** Smallest-unit base-10 integer string -- the bridge's configured minimum. */
2003
- bridgeMinWei: string;
2004
- /** Server's best-effort recommendation: "execute" (balance clears the bridge minimum, so a
2005
- * normal delivery can complete), "sweep" (below minimum -- recover directly instead), or
2006
- * "none" (no balance to act on). Advisory only -- never used to disable an action. */
2007
- suggestedAction: 'execute' | 'sweep' | 'none';
2008
- /** True when the backend sees this balance as possibly mid-flight (e.g. a sweep/bridge job
2009
- * already in progress) -- advisory caution only, must NOT disable either recovery action. */
2010
- inFlight: boolean;
2011
- inFlightReason?: string;
2012
- /**
2013
- * Task 6/7: every known BSC token held at `forwarder` (not just the primary `token`/`balance`
2014
- * pair above, which only ever reports BSC USDT) -- lets the UI surface a MISDEPOSITED token
2015
- * (e.g. someone sent BUSD to a USDT-swap forwarder) that the top-level fields alone can't
2016
- * represent. Optional/omitted for an older backend that predates this field -- back-compat,
2017
- * byte-identical to pre-Task-6 behavior when absent (the UI falls back to `token`/`balance`).
2018
- * Each entry's `suggestedAction` mirrors the top-level one's semantics, per-token.
2019
- */
2020
- tokens?: {
2021
- address: string;
2022
- symbol: string;
2023
- decimals: number;
2024
- /** Smallest-unit base-10 integer string -- this token's current balance at `forwarder`. */
2025
- balance: string;
2026
- /** Server's advisory recoverable flag for this token -- never used to disable the sweep
2027
- * action (see `recover`'s doc in useRecovery.ts), only to decide which tokens the UI lists. */
2028
- recoverable: boolean;
2029
- suggestedAction: 'execute' | 'sweep' | 'none';
2030
- }[];
2031
- }
2032
- /** GET /v1/recovery request query params. */
2033
- interface RecoveryRequest {
2034
- user: string;
2035
- /** Selected CROSS delivery target symbol (mirrors DepositAddressRequest's `target`) -- omitted
2036
- * (or empty) selects the configured default, preserving pre-multi-target behavior
2037
- * byte-for-byte. Passed through verbatim as "?target=" when set. */
2038
- target?: string;
2124
+ declare function RelayHistoryTrigger({ asChild, children }: RelayHistoryTriggerProps): react_jsx_runtime.JSX.Element;
2125
+
2126
+ declare function RelayHistoryRoot(props: RelayHistoryProps): react_jsx_runtime.JSX.Element;
2127
+ declare const RelayHistory: typeof RelayHistoryRoot & {
2128
+ Trigger: typeof RelayHistoryTrigger;
2129
+ Content: typeof RelayHistoryContent;
2130
+ };
2131
+
2132
+ interface RelayRecoveryContentProps {
2133
+ /** Extra class name(s) for the dialog/drawer content element. Falls back to
2134
+ * `<RelayRecovery>`'s own `className`. */
2135
+ className?: string;
2039
2136
  }
2137
+ /**
2138
+ * `<RelayRecovery.Content>` — the modal/drawer surface. Same portal-scoped
2139
+ * lifecycle as `<RelayHistory.Content>`: nothing is requested before the modal
2140
+ * is opened, and the whole subtree (including `useRecovery`'s state and any
2141
+ * in-flight recovery tracking) unmounts on close, so there is no per-open state
2142
+ * to reset explicitly.
2143
+ */
2144
+ declare function RelayRecoveryContent({ className }: RelayRecoveryContentProps): react_jsx_runtime.JSX.Element;
2040
2145
 
2041
- /** Thrown for any non-2xx API response. `status` is the HTTP status code. */
2042
- declare class RelayApiError extends Error {
2043
- status: number;
2044
- /** Parsed JSON error body when the response was valid JSON, else undefined. */
2045
- body?: unknown;
2046
- constructor(status: number, message: string, body?: unknown);
2146
+ interface RelayRecoveryTriggerProps {
2147
+ /** Render the child as the trigger instead of wrapping it. Defaults to
2148
+ * `true` whenever a child is supplied, matching `RelayHistoryTrigger`'s
2149
+ * (and `RelayDepositTrigger`'s) `asChild ?? children != null` rule. */
2150
+ asChild?: boolean;
2151
+ children?: ReactNode;
2047
2152
  }
2048
- interface RelayClientOptions {
2049
- /** API origin, e.g. "https://orchestrator.example.com". Trailing slashes are stripped. */
2050
- baseUrl: string;
2153
+ /**
2154
+ * Thin pass-through to `ShellTrigger` (radix `Dialog.Trigger` on desktop /
2155
+ * vaul `Drawer.Trigger` on mobile), mirroring `RelayHistoryTrigger` so hosts
2156
+ * write `<RelayRecovery.Trigger><button>…</button></RelayRecovery.Trigger>`
2157
+ * without knowing which primitive is active. Falls back to a plain-text
2158
+ * "Recover" button when no child is given -- unstyled like the sibling
2159
+ * `RelayDepositTrigger`/`RelayHistoryTrigger` defaults, so it inherits the
2160
+ * host's own button chrome instead of shipping a look of its own.
2161
+ *
2162
+ * The default button renders NO count badge (2026-07-30: removed on request --
2163
+ * the number read as an unread-notification alarm). The root's cross-target
2164
+ * recoverable count still reaches the trigger element as
2165
+ * `data-rd-recovery-count` (radix/vaul merge Trigger props onto the `asChild`
2166
+ * child too), so a host that WANTS a badge can opt in with its own CSS -- e.g.
2167
+ * `button[data-rd-recovery-count]:not([data-rd-recovery-count="0"])::after` --
2168
+ * without refetching anything.
2169
+ *
2170
+ * Wrapped in `<TrackingBoundary feature="relay">` for the same reason
2171
+ * `RelayHistoryTrigger` is: `data-track="open"` is only read by the delegate a
2172
+ * boundary installs, and this trigger sits OUTSIDE the portaled `<Content>`'s
2173
+ * own boundary.
2174
+ */
2175
+ declare function RelayRecoveryTrigger({ asChild, children }: RelayRecoveryTriggerProps): react_jsx_runtime.JSX.Element;
2176
+
2177
+ declare function RelayRecoveryRoot(props: RelayRecoveryProps): react_jsx_runtime.JSX.Element;
2178
+ declare const RelayRecovery: typeof RelayRecoveryRoot & {
2179
+ Trigger: typeof RelayRecoveryTrigger;
2180
+ Content: typeof RelayRecoveryContent;
2181
+ };
2182
+
2183
+ interface UseRelayOrdersOptions {
2184
+ client: RelayClient;
2185
+ /** Valid EVM address, or undefined -- undefined clears the list and stops polling. */
2186
+ recipient?: string;
2187
+ /** Gate: wait for truthy before the first fetch (RelayDeposit passes rawCatalog). Default true. */
2188
+ enabled?: boolean;
2189
+ /** Keep the snapshot live with SSE + fallback polling. Default true. */
2190
+ live?: boolean;
2191
+ /** REST safety-net cadence in milliseconds. Defaults to 30s; the open Deposit popup uses 1s
2192
+ * so completion still appears promptly when the SSE event is absent. */
2193
+ refetchInterval?: number;
2194
+ /** @deprecated Use `refetchInterval`. Retained for compatibility. */
2195
+ fallbackPollMs?: number;
2196
+ onError?: (e: Error) => void;
2051
2197
  }
2052
- interface RelayClient {
2053
- /** GET /v1/config -- the curated origin catalog + fixed crossd destination. */
2054
- getConfig(): Promise<Catalog>;
2055
- /** POST /v1/quote -- a price-only preview, no order/deposit is created. */
2056
- getQuote(req: QuoteRequest): Promise<QuoteResult>;
2057
- /**
2058
- * GET /v1/deposit-address -- resolves the stable, reusable deposit
2059
- * address for (user, originChainId, originCurrency). No amount is
2060
- * involved and no order is created; the same address can receive any
2061
- * number of deposits of any size. Several deposits can be aggregated into
2062
- * one order when they jointly fund the same reusable forwarder.
2063
- *
2064
- * `target` (Task 8) is the delivery asset's symbol from
2065
- * `Catalog.targets` -- sent as `&target=<symbol>` only when it's a
2066
- * non-empty string; omitted otherwise, in which case the backend
2067
- * resolves the default target (byte-identical to pre-Task-6 behavior).
2068
- */
2069
- getDepositAddress(req: DepositAddressRequest, target?: string): Promise<DepositAddressResult>;
2070
- /**
2071
- * GET /v1/orders/{orderId} -- current status + stepper progress for one
2072
- * order. Reads are public (unauthenticated).
2073
- */
2074
- getOrder(orderId: string): Promise<Order>;
2075
- /**
2076
- * GET /v1/orders?user=... -- every order swept from deposits to that
2077
- * user's standing address(es) (newest-first, capped server-side).
2078
- */
2079
- listOrders(user: string): Promise<OrderSummary[]>;
2080
- /** Absolute URL of the SSE order-change stream for `user`
2081
- * (GET /v1/orders/stream?user=...). Emits `event: connected` on open,
2082
- * `event: orders-changed` when that user's orders change, and `:
2083
- * heartbeat` comments -- it carries no order data itself, so consumers
2084
- * always follow up with `listOrders`. */
2085
- ordersStreamUrl(user: string): string;
2086
- /**
2087
- * GET /v1/recovery?user=... -- permissionless self-recovery status for a
2088
- * user's forwarder on BSC (Task 1). `req.target` (optional) selects which
2089
- * per-target forwarder/factory to report -- omitted selects the
2090
- * configured default, byte-identical to pre-multi-target behavior.
2091
- * Purely informational -- fetching it never triggers or blocks any
2092
- * on-chain action. The response's `tokens[]` (Task 6/7 -- every known BSC
2093
- * token held at the forwarder) flows through as-is: it's plain JSON, so no
2094
- * extra parsing/mapping is needed beyond RecoveryInfo's own typing, and
2095
- * it's simply absent/undefined for an older backend that predates it.
2096
- */
2097
- getRecovery(req: RecoveryRequest): Promise<RecoveryInfo>;
2198
+ interface UseRelayOrdersResult {
2199
+ /** Every order swept from deposits to this recipient so far, newest-first
2200
+ * as served by the API. Kept live unless `live: false` requests one snapshot. */
2201
+ orders: OrderSummary[];
2202
+ ordersLoading: boolean;
2203
+ ordersError?: Error;
2204
+ /** Recipient the current snapshot belongs to. Undefined while a new
2205
+ * subscription is waiting for its first accepted fetch, so consumers never
2206
+ * baseline a previous recipient's rows as fresh deposits. */
2207
+ ordersForRecipient?: string;
2208
+ /** Increments after every accepted fetch, even when the client returns the
2209
+ * same array reference or the request fails. Consumers use this as a
2210
+ * low-frequency refresh signal for related read models such as /recovery. */
2211
+ ordersRevision: number;
2212
+ /** True once at least one fetch has COMPLETED (success or failure) for the
2213
+ * current (recipient, enabled) subscription; false again when it resets.
2214
+ * Distinct from `!ordersLoading`, which is also true BEFORE the first fetch
2215
+ * has even started -- consumers that snapshot the list (e.g. the deposit
2216
+ * wizard's new-order watch) must wait for this, or they baseline against
2217
+ * the initial empty state and misread every existing order as new. */
2218
+ ordersInitialized: boolean;
2219
+ }
2220
+ declare function useRelayOrders(opts: UseRelayOrdersOptions): UseRelayOrdersResult;
2221
+
2222
+ interface UseRelayConfigOptions {
2223
+ /** Pre-built client. Takes precedence over apiBaseUrl. */
2224
+ client?: RelayClient;
2225
+ /** Used to build a client when `client` is not supplied. */
2226
+ apiBaseUrl?: string;
2227
+ /** Stops the request and clears the current snapshot. Defaults to true. */
2228
+ enabled?: boolean;
2229
+ /** Optional automatic REST refresh cadence in milliseconds. Disabled when omitted or <= 0. */
2230
+ refetchInterval?: number;
2231
+ onError?: (error: Error) => void;
2232
+ }
2233
+ interface UseRelayConfigResult {
2234
+ /** Latest GET /v1/config response. */
2235
+ config?: Catalog;
2236
+ loading: boolean;
2237
+ error?: Error;
2238
+ /** Re-fetches GET /v1/config using the current client. */
2239
+ refresh: () => void;
2098
2240
  }
2099
2241
  /**
2100
- * Builds a framework-agnostic Relay API client. Uses plain `fetch` only --
2101
- * no react-query, no RainbowKit/wagmi. `baseUrl` is passed in explicitly (no
2102
- * `import.meta.env` coupling) so the widget can be embedded in any host app's
2103
- * own config/env story.
2242
+ * Public read-only hook for Relay's origin/destination/target catalog.
2104
2243
  *
2105
- * No API key: the backend has no inbound key gate (upstream 83845fb removed
2106
- * the dead `apiKey`/X-API-Key plumbing -- a security control that does not
2107
- * exist must not appear in a public type).
2244
+ * The response is a normal REST snapshot, not an SSE stream. Use
2245
+ * `refetchInterval` for periodic refreshes or call `refresh` for an immediate
2246
+ * read without replacing the client or remounting the component.
2108
2247
  */
2109
- declare function createRelayClient(options: RelayClientOptions): RelayClient;
2110
-
2111
- interface DefaultToken {
2112
- chainId: number;
2113
- /** Token contract address, or the zero address for the chain's native asset. */
2114
- address: string;
2115
- }
2248
+ declare function useRelayConfig(opts?: UseRelayConfigOptions): UseRelayConfigResult;
2116
2249
 
2117
- type Hex = `0x${string}`;
2118
- interface RelayTxRequest {
2119
- chainId: number;
2120
- to: Hex;
2121
- value?: bigint;
2122
- data?: Hex;
2123
- }
2124
- interface RelayContractCall {
2125
- chainId: number;
2126
- address: Hex;
2127
- abi: readonly unknown[];
2128
- functionName: string;
2129
- args: readonly unknown[];
2130
- }
2131
- interface RelayBalance {
2132
- value: bigint;
2133
- decimals: number;
2134
- symbol: string;
2135
- }
2136
- type SendTransactionFn = (req: RelayTxRequest) => Promise<Hex>;
2137
- type WriteContractFn = (call: RelayContractCall) => Promise<Hex>;
2138
- type ReadContractFn = (call: RelayContractCall) => Promise<unknown>;
2139
- type SwitchChainFn = (chainId: number) => Promise<void>;
2140
- type WaitForReceiptFn = (p: {
2141
- chainId: number;
2142
- hash: Hex;
2143
- }) => Promise<{
2144
- status: "success" | "reverted";
2145
- }>;
2146
- type GetBalanceFn = (p: {
2147
- chainId: number;
2148
- address: Hex;
2149
- token?: Hex;
2150
- }) => Promise<RelayBalance>;
2151
- /** 지갑 주입 props — 전부 optional, 미주입 시 graceful degradation. */
2152
- interface RelayWalletProps {
2153
- walletAddress?: string;
2154
- walletChainId?: number;
2155
- sendTransaction?: SendTransactionFn;
2156
- writeContract?: WriteContractFn;
2157
- readContract?: ReadContractFn;
2158
- switchChain?: SwitchChainFn;
2159
- waitForReceipt?: WaitForReceiptFn;
2160
- getBalance?: GetBalanceFn;
2161
- }
2162
- /** A recovery transaction confirmed successfully on BNB Smart Chain. */
2163
- interface RecoverySuccessResult {
2164
- action: "execute" | "sweep";
2165
- forwarder: string;
2166
- actionTxHash: string;
2167
- /** Present only when this attempt first had to deploy the forwarder. */
2250
+ type RecoveryAction = "execute" | "sweep";
2251
+ /** Per-attempt progress for `recover()`. "switching" = prompting a chain switch to BSC;
2252
+ * "deploying" = the factory.deploy() write is in flight/confirming (only needed when the
2253
+ * forwarder wasn't deployed yet); "recovering" = the execute()/sweepToUser() write is in
2254
+ * flight/confirming; "done"/"error" are terminal for this attempt. */
2255
+ type RecoveryStep = "idle" | "switching" | "deploying" | "recovering" | "done" | "error";
2256
+ interface RecoveryState {
2257
+ step: RecoveryStep;
2258
+ /** Tx hash of the factory.deploy() write -- only set when this attempt needed one. */
2168
2259
  deployTxHash?: string;
2260
+ /** Tx hash of the execute()/sweepToUser() write. */
2261
+ actionTxHash?: string;
2262
+ error?: string;
2169
2263
  }
2170
- type RelayTheme = "dark" | "light";
2171
- type RelayDrawerDirection = "bottom" | "left" | "right" | "top";
2264
+
2265
+ type RelayRecoveryQueryKey = readonly [
2266
+ "relay",
2267
+ "recovery",
2268
+ number,
2269
+ string | null,
2270
+ string | null
2271
+ ];
2172
2272
  /**
2173
- * Props of the `<RelayDeposit>` compound root (Task 11) — the union of
2174
- *
2175
- * * `RelayWalletProps` (injected wallet capabilities, all optional),
2176
- * * the source widget's own configuration props (relay-protocol
2177
- * `packages/relay-widget/src/components/RelayDeposit.tsx`), minus its
2178
- * `theme: 'auto'` option, which the shared modal shell doesn't have, and
2179
- * * `ResponsiveShellProps`' modal/drawer knobs (theme/breakpoint/size/open),
2180
- * re-declared here rather than extended so the public surface reads as one
2181
- * flat prop list.
2182
- *
2183
- * `children` holds `<RelayDeposit.Trigger>` / `<RelayDeposit.Content>`.
2273
+ * React Query policies accepted by useRelayRecovery. The SDK owns the request
2274
+ * identity and response shape, so callers cannot replace queryKey/queryFn or
2275
+ * inject/select recovery balances.
2184
2276
  */
2185
- interface RelayDepositProps extends RelayWalletProps {
2277
+ type RelayRecoveryQueryOptions = Omit<UseQueryOptions<RecoveryInfo, Error, RecoveryInfo, RelayRecoveryQueryKey>, "queryKey" | "queryFn" | "select" | "initialData" | "initialDataUpdatedAt" | "placeholderData">;
2278
+ interface UseRelayRecoveryOptions {
2186
2279
  /** Pre-built client. Takes precedence over apiBaseUrl. */
2187
2280
  client?: RelayClient;
2188
- /** Used to build a client via createRelayClient when `client` isn't passed. */
2281
+ /** Used to build a client via createRelayClient when client isn't passed. */
2189
2282
  apiBaseUrl?: string;
2190
- /**
2191
- * Selects a built-in default relay API base URL (dev/stage/production) when
2192
- * `apiBaseUrl` isn't passed. `client`/`apiBaseUrl` still take precedence --
2193
- * this is only consulted when neither is provided. Omitted falls back to
2194
- * the same global environment resolution every other dapp-ui feature uses
2195
- * (see `resolveEnvironment`), defaulting to production.
2196
- */
2197
- environment?: Environment;
2198
- /** Restrict the catalog's origins to these chain ids. */
2199
- chains?: number[];
2200
- /** Controlled recipient; when provided the recipient input is hidden and no wallet
2201
- * connection is required to fetch a deposit address. Defaults to `walletAddress`. */
2283
+ /** Connected EVM wallet whose recoverable forwarder balances are queried. */
2202
2284
  recipient?: string;
2203
- /** Require a valid connected wallet before the deposit flow can issue an
2204
- * address, quote an amount, or start live order/recovery reads. When enabled,
2205
- * the recipient is pinned to `walletAddress`; a controlled `recipient` cannot
2206
- * redirect the connected user's deposit. Defaults to `true` when
2207
- * `showRecipientInput` is explicitly `false`, otherwise `false` for the
2208
- * low-level public-address integration. `CrossRelayDeposit` always enables
2209
- * this guard. */
2210
- requireWalletConnection?: boolean;
2211
- /** Hide the editable recipient input even when `recipient` is NOT controlled
2212
- * (default `true` = original behavior). Hosts that lock the recipient to the
2213
- * connected wallet set this `false` so a disconnected user sees a connect
2214
- * prompt instead of a free-form address field — the deposit address can then
2215
- * only ever resolve to the logged-in wallet. */
2216
- showRecipientInput?: boolean;
2217
- /** Controlled human-decimal amount; when provided the amount input is hidden. Optional —
2218
- * it only drives the quote preview, and never blocks the deposit address. */
2219
- amount?: string;
2220
- /** Hide the amount input entirely (address-only, send-any-amount). Independent of `amount`. */
2221
- hideAmount?: boolean;
2222
- /** Render the EVM one-click deposit button (default `false`: the modal only
2223
- * offers the QR / copy-address manual deposit path). Opt in with `true` for
2224
- * hosts whose users connect external wallets that can sign on the origin
2225
- * chains — CROSS embedded-wallet users never can, hence the off default. */
2226
- showOneClickDeposit?: boolean;
2227
- /** Render the recovery gear menu ("Recover stuck funds", default `false`).
2228
- * Recovery signs on BSC with the connected wallet, which CROSS embedded-wallet
2229
- * users can never do — so the gear is hidden unless a host serving external
2230
- * wallets opts in. Even opted in, it still requires the injected
2231
- * `writeContract`/`readContract`/`waitForReceipt` capability trio. */
2232
- showRecovery?: boolean;
2233
- /** Which (chainId, token address) to default-select once the catalog loads. */
2234
- defaultToken?: DefaultToken;
2235
- /** Restricts the delivery-token picker to these symbols from `Catalog.targets`. */
2236
- targetTokens?: string[];
2237
- /** Which delivery-token symbol to select initially, instead of the catalog's own default. */
2238
- defaultTarget?: string;
2239
- /** Whether to render the delivery-token picker at all. Default `true`; the picker only
2240
- * ever renders when there is more than one target to choose from either way. */
2241
- showTargetSelector?: boolean;
2242
- /** Overrides the pinned factory set the one-click deposit verifies the forwarder against. */
2243
- trustedFactories?: readonly string[];
2244
- onDepositAddress?: (result: DepositAddressResult) => void;
2245
- /** Fired once per one-click deposit that CONFIRMED successfully, with the tx
2246
- * hash. NOT fired on submission, and NOT fired for a tx that reverted --
2247
- * watch `depositState` (phase/txHash/reverted) for those. Safe to treat as
2248
- * "the funds moved" (upstream 83845fb). */
2249
- onDeposited?: (txHash: string) => void;
2250
- /** Fired once after a recovery action receipt confirms successfully. */
2251
- onRecoverySuccess?: (result: RecoverySuccessResult) => void;
2285
+ /** Optional CROSS delivery target passed to GET /v1/recovery. */
2286
+ target?: string;
2287
+ /** React Query lifecycle, cache, retry, and refetch policies. */
2288
+ query?: RelayRecoveryQueryOptions;
2289
+ /** Optional wallet capabilities. Read-only consumers may omit this. */
2290
+ wallet?: RelayWalletProps;
2291
+ /** Called when GET /v1/recovery returns 401. */
2292
+ onUnauthorized?: () => void;
2293
+ /** Called after a terminal query or recovery-action error. */
2252
2294
  onError?: (error: Error) => void;
2253
- /** Called by the `Connect Wallet` CTA under the locked card that stands in for the QR
2254
- * while the required connected wallet (or, in low-level public-address mode,
2255
- * a usable recipient) is absent. Omitted — the locked card renders as text
2256
- * only, with no button. */
2257
- onRequestConnect?: () => void;
2258
- /** @deprecated The Deposit footer entry was removed. Retained as a no-op
2259
- * compatibility prop so existing hosts do not need an immediate migration. */
2260
- onOpenHistory?: () => void;
2261
- /** Extra class name(s) for the modal/drawer content element. */
2262
- className?: string;
2263
- theme?: RelayTheme;
2264
- mobileBreakpoint?: number;
2265
- drawerDirection?: RelayDrawerDirection;
2266
- dialogWidth?: string;
2267
- drawerMaxWidth?: string;
2268
- drawerMinWidth?: string;
2269
- style?: CSSProperties;
2270
- open?: boolean;
2271
- onOpenChange?: (open: boolean) => void;
2272
- children?: ReactNode;
2295
+ /** Called once after a recovery transaction confirms successfully. */
2296
+ onRecoverySuccess?: (result: RecoverySuccessResult) => void;
2297
+ /** Trusted factory override for a self-hosted deployment. */
2298
+ trustedFactories?: readonly string[];
2299
+ }
2300
+ interface UseRelayRecoveryResult {
2301
+ info?: RecoveryInfo;
2302
+ loading: boolean;
2303
+ error?: Error;
2304
+ /** True for background refetches as well as the first request. */
2305
+ isFetching: boolean;
2306
+ /** Invalidates no identities; immediately refetches this hook's fixed query. */
2307
+ refresh: () => void;
2308
+ /** Signs a recovery transaction for the currently fetched info. */
2309
+ recover: (action: RecoveryAction, tokenAddress?: string) => Promise<void>;
2310
+ recoveryState: RecoveryState;
2273
2311
  }
2274
2312
  /**
2275
- * Props of the `<RelayRecovery>` compound root — the standalone
2276
- * "Recover stuck funds" modal, i.e. the deposit wizard's gear panel lifted out
2277
- * into a modal of its own so a host can offer recovery WITHOUT the deposit
2278
- * flow (the gear inside `<RelayDeposit>` is unaffected and still opt-in via
2279
- * `showRecovery`).
2313
+ * Public Recovery API hook. Unlike the widget-internal useRecovery fetch, this
2314
+ * hook uses the host QueryClient and accepts React Query policies through
2315
+ * `query`. queryKey/queryFn and balance-shaping options remain SDK-owned.
2316
+ */
2317
+ declare function useRelayRecovery(opts?: UseRelayRecoveryOptions): UseRelayRecoveryResult;
2318
+
2319
+ interface StatusTrackerProps {
2320
+ orderId: string;
2321
+ /** Latest polled order (steps/txs) from GET /v1/orders/{orderId}, owned by the caller. */
2322
+ order?: Order;
2323
+ /** Latest poll error, owned by the caller. */
2324
+ error?: Error;
2325
+ }
2326
+ declare function StatusTracker({ orderId, order, error }: StatusTrackerProps): react_jsx_runtime.JSX.Element;
2327
+
2328
+ /** Every StandingForwarderFactory / DepositorForwarderFactory this deployment
2329
+ * has issued deposit addresses from, on BSC.
2280
2330
  *
2281
- * Extends `RelayWalletProps` because recovery is signing-first: unlike
2282
- * `<RelayHistory>` (read-only, no wallet capabilities at all), the whole point
2283
- * of this modal is that the USER signs the permissionless recovery tx on BSC.
2284
- * A wallet missing the `writeContract`/`readContract`/`waitForReceipt` trio
2285
- * gets a short note instead of a dead panel.
2331
+ * Superseded factories stay listed on purpose. A forwarder's factory is pinned
2332
+ * per address at issuance time (`standing_addresses.factory`, copied onto each
2333
+ * order), so a user recovering an address minted before a rotation legitimately
2334
+ * gets an older factory back from the API -- dropping it here would block that
2335
+ * user from recovering their own funds, which is a worse outcome than the
2336
+ * narrow trust gain. Every entry is one of ours either way.
2286
2337
  *
2287
- * `children` holds `<RelayRecovery.Trigger>` / `<RelayRecovery.Content>`.
2288
- */
2289
- interface RelayRecoveryProps extends RelayWalletProps {
2290
- /** Pre-built client. Takes precedence over apiBaseUrl. */
2291
- client?: RelayClient;
2292
- /** Used to build a client via createRelayClient when `client` isn't passed. */
2293
- apiBaseUrl?: string;
2294
- /**
2295
- * Selects a built-in default relay API base URL (dev/stage/production) when
2296
- * `apiBaseUrl` isn't passed. `client`/`apiBaseUrl` still take precedence --
2297
- * this is only consulted when neither is provided. Omitted falls back to
2298
- * the same global environment resolution every other dapp-ui feature uses
2299
- * (see `resolveEnvironment`), defaulting to production.
2300
- */
2301
- environment?: Environment;
2302
- /**
2303
- * Optional assertion of whose forwarder to check/recover. Recovery is always
2304
- * pinned to the valid connected `walletAddress`; when this value is supplied
2305
- * it must match that wallet. A missing/invalid wallet or mismatch renders a
2306
- * short note and makes ZERO requests (no catalog, no recovery lookup).
2307
- */
2308
- recipient?: string;
2309
- /**
2310
- * Overrides the pinned factory allowlist recovery verifies against before
2311
- * signing -- only needed by a self-hosted deployment running its own
2312
- * factories. Same meaning (and the same fail-closed reasoning) as
2313
- * `RelayDepositProps.trustedFactories`.
2314
- */
2315
- trustedFactories?: readonly string[];
2316
- /** Fired once after a recovery action receipt confirms successfully. */
2317
- onRecoverySuccess?: (result: RecoverySuccessResult) => void;
2318
- onError?: (e: Error) => void;
2319
- /** Extra class name(s) for the modal/drawer content element. */
2320
- className?: string;
2338
+ * Rotation (see backends/deploy/RUNBOOK-canary.md): ADD the new factory, keep
2339
+ * the old ones. */
2340
+ declare const DEFAULT_TRUSTED_FACTORIES: readonly string[];
2341
+
2342
+ type GetOneUsdActionId = "swap" | "bridge" | "transfer";
2343
+ type GetOneUsdMode = "floating" | "button";
2344
+ type GetOneUsdButtonComponent = ElementType<ButtonHTMLAttributes<HTMLButtonElement>>;
2345
+ type GetOneUsdWaitForTransaction = (info: BridgeSubmittedInfo) => Promise<void>;
2346
+ interface GetOneUsdTokenRef {
2347
+ chainId: number;
2348
+ address: string;
2349
+ }
2350
+ interface GetOneUsdPairs {
2351
+ target: GetOneUsdTokenRef;
2352
+ swap: {
2353
+ from: GetOneUsdTokenRef;
2354
+ feeDelegated?: boolean;
2355
+ };
2356
+ bridge: {
2357
+ from: GetOneUsdTokenRef[];
2358
+ feeDelegated?: boolean;
2359
+ };
2360
+ }
2361
+ type GetOneUsdBridgeProps = Omit<BridgeFlowProps, "walletAddress" | "tokens" | "initialFromToken" | "initialToToken" | "env" | "onClose" | "onBackToWallet" | "className" | "title" | "variant" | "isConnected" | "onRequestConnect">;
2362
+ type GetOneUsdRelayProps = Omit<RelayDepositProps, "walletAddress" | "children" | "open" | "onOpenChange" | "requireWalletConnection" | "showRecipientInput" | "hideAmount" | "targetTokens" | "defaultTarget" | "onRequestConnect">;
2363
+ type GetOneUsdEvent = {
2364
+ name: "fab_click";
2365
+ state: "expanded" | "icon_only";
2366
+ } | {
2367
+ name: "action_select";
2368
+ action: GetOneUsdActionId;
2369
+ } | {
2370
+ name: "connect_click";
2371
+ action: GetOneUsdActionId;
2372
+ } | {
2373
+ name: "success";
2374
+ action: GetOneUsdActionId;
2375
+ txHash: string;
2376
+ } | {
2377
+ name: "failure";
2378
+ action: GetOneUsdActionId;
2379
+ message: string;
2380
+ };
2381
+ interface GetOneUsdProps {
2382
+ /** Connected wallet. A missing address renders a connect CTA in execution views. */
2383
+ walletAddress?: string;
2384
+ /** Full token list supplied by a bridge adapter. It is never mutated. */
2385
+ tokens: BridgeToken[];
2386
+ /** Exact source/target token allowlist. May arrive after remote config loads. */
2387
+ pairs?: GetOneUsdPairs;
2388
+ /** True while the bridge adapter is resolving contracts/tokens. */
2389
+ loading?: boolean;
2390
+ /** View-only BridgeFlow transaction ports. */
2391
+ bridge: GetOneUsdBridgeProps;
2392
+ /** Relay configuration and low-level wallet ports. Built-in env URL is used when omitted. */
2393
+ relay?: GetOneUsdRelayProps;
2394
+ env?: Environment;
2395
+ targetSymbol?: string;
2396
+ /** Relay catalog delivery symbol. Defaults to the canonical `ONEUSD`. */
2397
+ relayTargetSymbol?: string;
2398
+ targetIconUrl?: string;
2399
+ /** Trigger layout. Transaction status always renders as a floating pill. */
2400
+ mode?: GetOneUsdMode;
2401
+ /** Custom styled trigger element used only in button mode. Must forward button props. */
2402
+ buttonComponent?: GetOneUsdButtonComponent;
2321
2403
  theme?: RelayTheme;
2322
2404
  mobileBreakpoint?: number;
2323
2405
  drawerDirection?: RelayDrawerDirection;
2324
2406
  dialogWidth?: string;
2325
2407
  drawerMaxWidth?: string;
2326
2408
  drawerMinWidth?: string;
2409
+ /** CSS variables/styles applied to the selected trigger. */
2327
2410
  style?: CSSProperties;
2328
- open?: boolean;
2329
- onOpenChange?: (open: boolean) => void;
2330
- children?: ReactNode;
2411
+ className?: string;
2412
+ contentClassName?: string;
2413
+ hidden?: boolean;
2414
+ /** Force the floating trigger to icon-only. Ignored in button mode. */
2415
+ compactTrigger?: boolean;
2416
+ collapseOnScroll?: boolean;
2417
+ scrollThreshold?: number;
2418
+ /**
2419
+ * Waits for an already-submitted Swap/Bridge transaction to confirm.
2420
+ * While pending, a non-interactive floating status pill is shown.
2421
+ * Omit only when submission itself is the final confirmation boundary.
2422
+ */
2423
+ waitForTransaction?: GetOneUsdWaitForTransaction;
2424
+ /** How long a confirmed/failed result stays on the floating button. Default 4000ms. */
2425
+ transactionResultDurationMs?: number;
2426
+ onRequestConnect?: () => void | Promise<void>;
2427
+ onEvent?: (event: GetOneUsdEvent) => void;
2331
2428
  }
2429
+ interface ResolvedGetOneUsdRoute {
2430
+ fromTokens: BridgeToken[];
2431
+ targetToken?: BridgeToken;
2432
+ }
2433
+
2434
+ declare function GetOneUsd({ walletAddress, tokens, pairs, loading, bridge, relay, env, targetSymbol: targetSymbolProp, relayTargetSymbol, targetIconUrl, mode, buttonComponent, theme, mobileBreakpoint, drawerDirection, dialogWidth, drawerMaxWidth, drawerMinWidth, style, className, contentClassName, hidden, compactTrigger, collapseOnScroll, scrollThreshold, waitForTransaction, transactionResultDurationMs, onRequestConnect, onEvent, }: GetOneUsdProps): react_jsx_runtime.JSX.Element;
2435
+
2436
+ type GetOneUsdRemoteModes = NonNullable<NonNullable<AppsConfig["getOneUsd"]>["modes"]>;
2437
+ type GetOneUsdRemoteMinVersions = NonNullable<NonNullable<AppsConfig["getOneUsd"]>["minVersions"]>;
2332
2438
  /**
2333
- * Props of the `<RelayHistory>` compound root (Task 12) — the standalone
2334
- * transfer-history modal built on the shared `ResponsiveShell` +
2335
- * `useRelayOrders`. `RelayDepositProps`'s simpler sibling: no wizard step,
2336
- * no catalog/target picking, no wallet-injected send/write capabilities —
2337
- * just an address to look up orders for and a list to render.
2439
+ * 목록에 보일지 여부. Swap/Bridge stay enabled when config is unavailable.
2440
+ * Transfer Crypto is opt-in and stays hidden until S3 explicitly enables it.
2441
+ */
2442
+ declare function isGetOneUsdActionVisible(action: GetOneUsdActionId, modes?: GetOneUsdRemoteModes): boolean;
2443
+ /**
2444
+ * 이 dapp-ui 버전에서 실행 가능한지. 미달이면 **숨기지 않고 비활성**으로 둔다 —
2445
+ * 항목이 조용히 사라지면 사용자는 기능이 없어진 줄 알지만, 비활성 + 안내면
2446
+ * "업데이트하면 쓸 수 있다"가 전달된다.
2447
+ */
2448
+ declare function isGetOneUsdActionSupported(action: GetOneUsdActionId, minVersions?: GetOneUsdRemoteMinVersions): boolean;
2449
+ /** 노출 + 실행 가능(= 실제로 선택할 수 있는지). */
2450
+ declare function isGetOneUsdActionEnabled(action: GetOneUsdActionId, modes?: GetOneUsdRemoteModes, minVersions?: GetOneUsdRemoteMinVersions): boolean;
2451
+
2452
+ declare function getOneUsdTokenKey(token: GetOneUsdTokenRef): string;
2453
+ declare function matchesGetOneUsdToken(token: BridgeToken, ref: GetOneUsdTokenRef): boolean;
2454
+ declare function findGetOneUsdToken(tokens: BridgeToken[], ref?: GetOneUsdTokenRef): BridgeToken | undefined;
2455
+ /** Resolve an action's exact token allowlist without mutating adapter data. */
2456
+ declare function resolveGetOneUsdRoute(tokens: BridgeToken[], pairs: GetOneUsdPairs | undefined, action: Exclude<GetOneUsdActionId, "transfer">): ResolvedGetOneUsdRoute;
2457
+ declare function isGetOneUsdTargetAvailable(available: BridgeToken[], target: BridgeToken): boolean;
2458
+
2459
+ declare function CROSSxIcon(): react_jsx_runtime.JSX.Element;
2460
+ declare function MetaMaskIcon(): react_jsx_runtime.JSX.Element;
2461
+ declare function BinanceIcon(): react_jsx_runtime.JSX.Element;
2462
+ declare function Verse8Icon(): react_jsx_runtime.JSX.Element;
2463
+ declare function TronIcon(): react_jsx_runtime.JSX.Element;
2464
+ declare function GoogleIcon(): react_jsx_runtime.JSX.Element;
2465
+ declare function AppleIcon(): react_jsx_runtime.JSX.Element;
2466
+
2467
+ declare const WALLET_REGISTRY: {
2468
+ cross_embedded: {
2469
+ id: string;
2470
+ name: "ONEpocket with Social";
2471
+ description: string;
2472
+ icon: typeof CROSSxIcon;
2473
+ };
2474
+ cross_wallet: {
2475
+ id: string;
2476
+ name: "ONEpocket";
2477
+ description: string;
2478
+ icon: typeof CROSSxIcon;
2479
+ featured: true;
2480
+ };
2481
+ cross_extension: {
2482
+ id: string;
2483
+ name: "ONEpocket Extension";
2484
+ description: string;
2485
+ icon: typeof CROSSxIcon;
2486
+ rdns: string;
2487
+ installUrl: string;
2488
+ visibility: "desktop-only";
2489
+ };
2490
+ metamask: {
2491
+ id: string;
2492
+ name: string;
2493
+ description: string;
2494
+ icon: typeof MetaMaskIcon;
2495
+ rdns: string;
2496
+ };
2497
+ binance: {
2498
+ id: string;
2499
+ name: string;
2500
+ description: string;
2501
+ icon: typeof BinanceIcon;
2502
+ };
2503
+ verse8: {
2504
+ id: string;
2505
+ name: string;
2506
+ description: string;
2507
+ icon: typeof Verse8Icon;
2508
+ badge: string;
2509
+ };
2510
+ tron: {
2511
+ id: string;
2512
+ name: string;
2513
+ description: string;
2514
+ icon: typeof TronIcon;
2515
+ badge: string;
2516
+ };
2517
+ };
2518
+ type WalletId = keyof typeof WALLET_REGISTRY;
2519
+ declare const SOCIAL_REGISTRY: {
2520
+ google: {
2521
+ id: string;
2522
+ name: string;
2523
+ icon: typeof GoogleIcon;
2524
+ };
2525
+ apple: {
2526
+ id: string;
2527
+ name: string;
2528
+ icon: typeof AppleIcon;
2529
+ };
2530
+ };
2531
+ type SocialId = keyof typeof SOCIAL_REGISTRY;
2532
+
2533
+ /**
2534
+ * Per-instance layout overrides applied as inline CSS variables.
2338
2535
  *
2339
- * `children` holds `<RelayHistory.Trigger>` / `<RelayHistory.Content>`.
2536
+ * Colors / typography are driven by the design system (`--ds-*`, published
2537
+ * by `CrossConnectKitProvider` from `@nexus-cross/crossx-design-system`) —
2538
+ * retheme there, not per modal. Only layout knobs remain here.
2340
2539
  */
2341
- interface RelayHistoryProps {
2342
- /** Pre-built client. Takes precedence over apiBaseUrl. */
2343
- client?: RelayClient;
2344
- /** Used to build a client via createRelayClient when `client` isn't passed. */
2345
- apiBaseUrl?: string;
2540
+ interface WalletConnectModalStyle extends CSSProperties {
2541
+ "--wcm-dialog-width"?: string;
2542
+ "--wcm-drawer-max-width"?: string;
2543
+ "--wcm-drawer-min-width"?: string;
2544
+ }
2545
+ type WalletVisibility = "always" | "mobile-only" | "desktop-only";
2546
+ interface WalletConfig {
2547
+ id: string;
2548
+ name: string;
2549
+ description: string;
2550
+ icon: () => ReactNode;
2551
+ rdns?: string;
2552
+ featured?: boolean;
2553
+ badge?: string;
2554
+ installUrl?: string;
2555
+ visibility?: WalletVisibility;
2556
+ }
2557
+ type WalletHandlers = Partial<Record<WalletId, () => void | Promise<void>>>;
2558
+ interface SocialConfig {
2559
+ id: string;
2560
+ name: string;
2561
+ icon: () => ReactNode;
2562
+ }
2563
+ type SocialHandlers = Partial<Record<SocialId, () => void | Promise<void>>>;
2564
+ type DrawerDirection = "bottom" | "left" | "right" | "top";
2565
+ interface WalletConnectModalProps {
2566
+ wallets: WalletHandlers;
2567
+ socialProviders?: SocialHandlers;
2346
2568
  /**
2347
- * Selects a built-in default relay API base URL (dev/stage/production) when
2348
- * `apiBaseUrl` isn't passed. `client`/`apiBaseUrl` still take precedence --
2349
- * this is only consulted when neither is provided. Omitted falls back to
2350
- * the same global environment resolution every other dapp-ui feature uses
2351
- * (see `resolveEnvironment`), defaulting to production.
2569
+ * URL the "Terms of Service" link in the footer points to. When
2570
+ * omitted the text is rendered without an anchor (still styled in the
2571
+ * primary color to match the design).
2352
2572
  */
2353
- environment?: Environment;
2354
- /** History subject. Falls back to `walletAddress`; empty-state UI when
2355
- * neither resolves to a valid address. */
2356
- recipient?: string;
2357
- walletAddress?: string;
2358
- onError?: (e: Error) => void;
2359
- /** Notified with the resolved explorer URL when a history row's tx link is
2360
- * clicked. Fire-and-forget -- unlike `OnOutlink` elsewhere in dapp-ui, it
2361
- * does not intercept navigation; the link still opens in a new tab as normal. */
2362
- onOutlink?: (url: string) => void;
2363
- /** Extra class name(s) for the modal/drawer content element. */
2364
- className?: string;
2365
- theme?: RelayTheme;
2573
+ termsUrl?: string;
2574
+ /** URL the "Privacy Policy" link in the footer points to. */
2575
+ privacyUrl?: string;
2576
+ theme?: "dark" | "light";
2366
2577
  mobileBreakpoint?: number;
2367
- drawerDirection?: RelayDrawerDirection;
2578
+ drawerDirection?: DrawerDirection;
2368
2579
  dialogWidth?: string;
2369
2580
  drawerMaxWidth?: string;
2370
2581
  drawerMinWidth?: string;
2371
- style?: CSSProperties;
2582
+ style?: WalletConnectModalStyle;
2372
2583
  open?: boolean;
2373
2584
  onOpenChange?: (open: boolean) => void;
2374
- children?: ReactNode;
2375
- }
2376
-
2377
- interface RelayDepositContentProps {
2378
- /** Extra class name(s) for the dialog/drawer content element. Falls back to
2379
- * `<RelayDeposit>`'s own `className`. */
2380
- className?: string;
2381
- }
2382
- /**
2383
- * `<RelayDeposit.Content>` — the modal/drawer surface. The deposit body is a
2384
- * child of `ShellContent`, i.e. of radix's `Dialog.Portal` / vaul's
2385
- * `Drawer.Portal`, which render nothing while closed. The state it renders is
2386
- * NOT its own any more: `<RelayDeposit>` mounts the wizard engine above the
2387
- * shell for exactly as long as the modal is open, so "no request before open"
2388
- * and "everything resets on close" still hold -- while a breakpoint crossing
2389
- * mid-flow now only rebuilds this DOM, not the flow.
2390
- */
2391
- declare function RelayDepositContent({ className }: RelayDepositContentProps): react_jsx_runtime.JSX.Element;
2392
-
2393
- interface RelayDepositTriggerProps {
2394
- /** Render the child as the trigger instead of wrapping it. Defaults to
2395
- * `true` whenever a child is supplied, matching
2396
- * `WalletConnectModalTrigger`'s `asChild ?? children != null`. */
2585
+ children: ReactNode;
2586
+ }
2587
+ interface WalletConnectModalTriggerProps {
2397
2588
  asChild?: boolean;
2398
2589
  children?: ReactNode;
2399
2590
  }
2400
- /**
2401
- * Thin pass-through to `ShellTrigger` (radix `Dialog.Trigger` on desktop /
2402
- * vaul `Drawer.Trigger` on mobile) so hosts write
2403
- * `<RelayDeposit.Trigger><button>…</button></RelayDeposit.Trigger>` without
2404
- * knowing which primitive is active. Falls back to a plain default button when
2405
- * no child is given, same as `WalletConnectModalTrigger`.
2406
- *
2407
- * Wrapped in `<TrackingBoundary feature="relay">` for the same reason
2408
- * `WalletConnectModalTrigger` is: the `data-track="open"` attribute below (and
2409
- * on any host-supplied child that carries one) is only picked up by the
2410
- * analytics delegate a boundary installs. Without it the open click is silently
2411
- * untracked, since the trigger lives OUTSIDE the portaled `<Content>` boundary.
2412
- */
2413
- declare function RelayDepositTrigger({ asChild, children }: RelayDepositTriggerProps): react_jsx_runtime.JSX.Element;
2591
+ interface WalletConnectModalContentProps {
2592
+ className?: string;
2593
+ }
2414
2594
 
2415
- declare function RelayDepositRoot(props: RelayDepositProps): react_jsx_runtime.JSX.Element;
2416
- declare const RelayDeposit: typeof RelayDepositRoot & {
2417
- Trigger: typeof RelayDepositTrigger;
2418
- Content: typeof RelayDepositContent;
2595
+ declare function WalletConnectModalTrigger({ asChild, children, }: WalletConnectModalTriggerProps): react_jsx_runtime.JSX.Element;
2596
+
2597
+ declare function WalletConnectModalContent({ className, }: WalletConnectModalContentProps): react_jsx_runtime.JSX.Element;
2598
+
2599
+ declare function WalletConnectModalRoot({ wallets, socialProviders, termsUrl, privacyUrl, theme, mobileBreakpoint, drawerDirection, dialogWidth, drawerMaxWidth, drawerMinWidth, style, open: openProp, onOpenChange, children, }: WalletConnectModalProps): react_jsx_runtime.JSX.Element;
2600
+ declare const WalletConnectModal: typeof WalletConnectModalRoot & {
2601
+ Trigger: typeof WalletConnectModalTrigger;
2602
+ Content: typeof WalletConnectModalContent;
2419
2603
  };
2420
2604
 
2421
- interface RelayHistoryContentProps {
2422
- /** Extra class name(s) for the dialog/drawer content element. Falls back to
2423
- * `<RelayHistory>`'s own `className`. */
2424
- className?: string;
2605
+ interface DetectedWallet {
2606
+ rdns: string;
2607
+ name: string;
2608
+ icon?: string;
2425
2609
  }
2610
+ interface WalletDetectResult {
2611
+ wallets: DetectedWallet[];
2612
+ isDetected: (rdns: string) => boolean;
2613
+ isLoading: boolean;
2614
+ }
2615
+ declare function useWalletDetect(): WalletDetectResult;
2616
+
2426
2617
  /**
2427
- * `<RelayHistory.Content>` — the modal/drawer surface. Like
2428
- * `RelayDepositContent`, this is a child of `ShellContent`, i.e. of radix's
2429
- * `Dialog.Portal` / vaul's `Drawer.Portal`, which render nothing while
2430
- * closed: no `listOrders` request happens before the modal is opened, and the
2431
- * subtree unmounts on close -- there is no per-open state here to reset
2432
- * explicitly (unlike `RelayDepositBody`'s step/panel state), so
2433
- * unmount-by-portal is the whole story.
2618
+ * `ConnectButton`의 `style` prop 타입. 표준 `CSSProperties` 위에
2619
+ * `--cb-*` CSS 커스텀 변수 키를 추가해 자동완성을 지원한다.
2620
+ *
2621
+ * 사용 예: `style={{ "--cb-bg": "#7346f3", "--cb-pill-bg": "#1a1a2e" }}`
2622
+ *
2623
+ * 변수는 ConnectButton 의 모든 상태(disconnected / connecting / connected
2624
+ * pill)에 cascading 된다. WalletInfo popover 의 스타일은 별도
2625
+ * `walletInfoStyle` prop 으로 분리되어 있다.
2434
2626
  */
2435
- declare function RelayHistoryContent({ className }: RelayHistoryContentProps): react_jsx_runtime.JSX.Element;
2436
-
2437
- interface RelayHistoryTriggerProps {
2438
- /** Render the child as the trigger instead of wrapping it. Defaults to
2439
- * `true` whenever a child is supplied, matching `RelayDepositTrigger`'s
2440
- * (and `WalletConnectModalTrigger`'s) `asChild ?? children != null` rule. */
2441
- asChild?: boolean;
2442
- children?: ReactNode;
2627
+ interface ConnectButtonStyle extends CSSProperties {
2628
+ "--cb-bg"?: string;
2629
+ "--cb-bg-hover"?: string;
2630
+ "--cb-color"?: string;
2631
+ "--cb-border"?: string;
2632
+ "--cb-radius"?: string;
2633
+ "--cb-height"?: string;
2634
+ "--cb-padding"?: string;
2635
+ "--cb-font-family"?: string;
2636
+ "--cb-font-size"?: string;
2637
+ "--cb-font-weight"?: string | number;
2638
+ "--cb-line-height"?: string | number;
2639
+ "--cb-letter-spacing"?: string;
2640
+ "--cb-gap"?: string;
2641
+ "--cb-transition"?: string;
2642
+ "--cb-loading-opacity"?: string | number;
2643
+ "--cb-press-scale"?: string | number;
2644
+ "--cb-icon-size"?: string;
2645
+ "--cb-spinner-size"?: string;
2646
+ "--cb-spinner-thumb"?: string;
2647
+ "--cb-spinner-track"?: string;
2648
+ "--cb-pill-bg"?: string;
2649
+ "--cb-pill-bg-hover"?: string;
2650
+ "--cb-pill-color"?: string;
2651
+ "--cb-pill-border"?: string;
2652
+ "--cb-pill-radius"?: string;
2653
+ "--cb-pill-height"?: string;
2654
+ "--cb-pill-padding"?: string;
2655
+ "--cb-pill-press-scale"?: string | number;
2656
+ "--cb-pill-font-family"?: string;
2657
+ "--cb-pill-font-size"?: string;
2658
+ "--cb-pill-font-weight"?: string | number;
2659
+ "--cb-pill-line-height"?: string | number;
2660
+ "--cb-pill-gap"?: string;
2661
+ "--cb-pill-icon-size"?: string;
2662
+ "--cb-pill-icon-placeholder-bg"?: string;
2663
+ "--cb-pill-address-font"?: string;
2664
+ "--cb-pill-address-font-size"?: string;
2665
+ "--cb-pill-address-letter-spacing"?: string;
2443
2666
  }
2444
2667
  /**
2445
- * Thin pass-through to `ShellTrigger` (radix `Dialog.Trigger` on desktop /
2446
- * vaul `Drawer.Trigger` on mobile), mirroring `RelayDepositTrigger` so hosts
2447
- * write `<RelayHistory.Trigger><button>…</button></RelayHistory.Trigger>`
2448
- * without knowing which primitive is active. Falls back to a plain default
2449
- * button when no child is given.
2668
+ * Resolved wallet provider — determines which icon + display name appears
2669
+ * in the connected pill.
2450
2670
  *
2451
- * Wrapped in `<TrackingBoundary feature="relay">` for the same reason
2452
- * `RelayDepositTrigger`/`WalletConnectModalTrigger` are: `data-track="open"` is
2453
- * only read by the delegate a boundary installs, and this trigger sits OUTSIDE
2454
- * the portaled `<Content>`'s own boundary.
2671
+ * - `google` / `apple`: crossy-sdk 2.0 OAuth login types (embedded wallet)
2672
+ * - `cross`: generic CROSSx mark (covers CROSSx 1.0 extension/app + 2.0
2673
+ * embedded when no OAuth provider is attached)
2674
+ * - `metamask` / `binance`: external wallets
2455
2675
  */
2456
- declare function RelayHistoryTrigger({ asChild, children }: RelayHistoryTriggerProps): react_jsx_runtime.JSX.Element;
2457
-
2458
- declare function RelayHistoryRoot(props: RelayHistoryProps): react_jsx_runtime.JSX.Element;
2459
- declare const RelayHistory: typeof RelayHistoryRoot & {
2460
- Trigger: typeof RelayHistoryTrigger;
2461
- Content: typeof RelayHistoryContent;
2462
- };
2463
-
2464
- interface RelayRecoveryContentProps {
2465
- /** Extra class name(s) for the dialog/drawer content element. Falls back to
2466
- * `<RelayRecovery>`'s own `className`. */
2676
+ type WalletProvider = "google" | "apple" | "cross" | "metamask" | "binance";
2677
+ interface ConnectButtonProps {
2678
+ /** 사용자가 Connect 버튼을 눌러 연결이 진행 중. 스피너 버튼으로 전환된다. */
2679
+ isConnecting?: boolean;
2680
+ /**
2681
+ * 0x… 지갑 주소. 지정되면 connected pill로 렌더링된다. 없으면
2682
+ * disconnected 버튼("Connect Wallet")으로 떨어진다.
2683
+ */
2684
+ address?: string;
2685
+ /**
2686
+ * 트리거 pill에 표시될 provider 아이콘 키.
2687
+ *
2688
+ * `address`가 있는데 `provider`가 `undefined`면 SDK 조회 중인 전이
2689
+ * 상태로 취급해 placeholder 원을 띄운다(`pending` 플래시 방지).
2690
+ */
2691
+ provider?: WalletProvider;
2692
+ /**
2693
+ * 트리거 버튼 aria-label에 포함될 provider 표시 이름. 미지정 시
2694
+ * `provider`로부터 기본값이 유추된다 (예: 'Google', 'CROSSx').
2695
+ */
2696
+ providerName?: string;
2697
+ /** WalletInfo 헤더에 노출될 계정 라벨 (예: "Account 1", 사용자 지정 이름). */
2698
+ accountName?: string;
2699
+ /** Send 주소록의 My Account 탭에 노출할 계정 목록. */
2700
+ sendAccounts?: SendAccount[];
2701
+ /** disconnected 상태에서 버튼 클릭 핸들러. */
2702
+ onConnect?: () => void;
2703
+ /** connected 상태에서 WalletInfo 하단 Disconnect 클릭 핸들러. */
2704
+ onDisconnect?: () => void;
2705
+ /**
2706
+ * 주소 복사 성공 콜백. WalletInfo의 `onCopyAddress(address, success)` 에서
2707
+ * `success === true`일 때만 호출된다.
2708
+ */
2709
+ onCopy?: () => void;
2710
+ /** 지갑 변경 chevron 클릭 핸들러. 지정하지 않으면 chevron이 숨김 처리된다. */
2711
+ onSelectWallet?: () => void;
2712
+ /**
2713
+ * WalletInfo 기본 액션 row의 Buy 클릭 핸들러. Promise를 반환하면 reject 시
2714
+ * Buy 카드가 `onBuyDisabledMessage`와 동일한 토스트로 실패를 안내한다.
2715
+ */
2716
+ onBuy?: () => void | Promise<void>;
2717
+ /**
2718
+ * Buy 카드를 시각적으로 비활성 상태로 표시하고, 사용자가 클릭하면 이 메시지를
2719
+ * 토스트로 띄운다. `onBuy`보다 우선. WalletInfoProps의 동일 prop으로 그대로
2720
+ * 전달된다.
2721
+ */
2722
+ onBuyDisabledMessage?: string;
2723
+ /**
2724
+ * disconnected 버튼 라벨. 기본 'Connect Wallet'.
2725
+ * 문자열 외에 ReactNode를 넘겨 아이콘-only / 커스텀 마크업을 렌더할 수 있다
2726
+ * (모바일에서 아이콘만 보여주고 싶을 때 등).
2727
+ */
2728
+ label?: ReactNode;
2729
+ /** isConnecting 상태 라벨. 기본 'Connecting...'. */
2730
+ connectingLabel?: ReactNode;
2731
+ /** WalletInfo 내장 Disconnect 버튼 라벨. 기본 'Disconnect'. */
2732
+ disconnectLabel?: string;
2733
+ /**
2734
+ * 외부(호출부)에서 주입하는 className. disconnected / connecting /
2735
+ * connected(트리거 pill)에 공통으로 추가된다 (기본 `cb-button` /
2736
+ * `cb-pill` 클래스에 병합).
2737
+ */
2467
2738
  className?: string;
2739
+ /**
2740
+ * 버튼 자체(`disconnected` / `connecting` / `connected pill`)의
2741
+ * CSS 커스텀 변수 오버라이드. WalletInfo popover 스타일은 별도
2742
+ * `walletInfoStyle` 로 분리되어 있다.
2743
+ */
2744
+ style?: ConnectButtonStyle;
2745
+ /**
2746
+ * 트리거 pill 을 눌러 열리는 WalletInfo popover/drawer 의 CSS
2747
+ * 커스텀 변수 오버라이드 (`WalletInfoStyle`).
2748
+ */
2749
+ walletInfoStyle?: WalletInfoStyle;
2750
+ theme?: Theme;
2751
+ env?: Environment;
2752
+ showBalance?: boolean;
2753
+ showPortfolio?: boolean;
2754
+ drawerDirection?: DrawerDirection$1;
2755
+ modal?: boolean;
2756
+ connectorId?: ConnectorId;
2757
+ /** Send 페이지의 일반 토큰 전송에 사용할 외부 트랜잭션 전송 함수. */
2758
+ sendTransaction?: SendTransactionFn$1;
2759
+ getTransactionReceipt?: GetTransactionReceiptFn;
2760
+ /**
2761
+ * Send 확인 단계의 가스/수수료 추정 함수. 미주입 시 SendPage Confirm 화면의
2762
+ * Est. Tx Fee / Gas Limit / Max. Total Amount 행이 "—"로 표시된다.
2763
+ */
2764
+ estimateGas?: EstimateGasFn;
2765
+ /**
2766
+ * 상단 QR 버튼 / 기본 액션 row의 Receive / Send 콜백. (Buy는 위 onBuy로
2767
+ * 정의됨.)
2768
+ */
2769
+ onReceive?: () => void;
2770
+ /**
2771
+ * @deprecated Bridge 버튼은 항상 apps.json(gametokenBridge) 웹으로
2772
+ * 이동한다. 이 콜백은 더 이상 호출되지 않는다.
2773
+ */
2774
+ onBridge?: () => void;
2775
+ onSend?: () => void;
2776
+ bridgeTokens?: BridgeToken[];
2777
+ bridgeHistory?: BridgeHistoryItem[];
2778
+ getBridgeQuote?: BridgeQuoteFn;
2779
+ getBridgeToTokens?: BridgeGetToTokensFn;
2780
+ getBridgeApproval?: BridgeGetApprovalFn;
2781
+ approveBridge?: BridgeApproveFn;
2782
+ submitBridge?: BridgeSubmitFn;
2468
2783
  }
2469
- /**
2470
- * `<RelayRecovery.Content>` — the modal/drawer surface. Same portal-scoped
2471
- * lifecycle as `<RelayHistory.Content>`: nothing is requested before the modal
2472
- * is opened, and the whole subtree (including `useRecovery`'s state and any
2473
- * in-flight recovery tracking) unmounts on close, so there is no per-open state
2474
- * to reset explicitly.
2475
- */
2476
- declare function RelayRecoveryContent({ className }: RelayRecoveryContentProps): react_jsx_runtime.JSX.Element;
2477
2784
 
2478
- interface RelayRecoveryTriggerProps {
2479
- /** Render the child as the trigger instead of wrapping it. Defaults to
2480
- * `true` whenever a child is supplied, matching `RelayHistoryTrigger`'s
2481
- * (and `RelayDepositTrigger`'s) `asChild ?? children != null` rule. */
2482
- asChild?: boolean;
2483
- children?: ReactNode;
2484
- }
2485
2785
  /**
2486
- * Thin pass-through to `ShellTrigger` (radix `Dialog.Trigger` on desktop /
2487
- * vaul `Drawer.Trigger` on mobile), mirroring `RelayHistoryTrigger` so hosts
2488
- * write `<RelayRecovery.Trigger><button>…</button></RelayRecovery.Trigger>`
2489
- * without knowing which primitive is active. Falls back to a plain-text
2490
- * "Recover" button when no child is given -- unstyled like the sibling
2491
- * `RelayDepositTrigger`/`RelayHistoryTrigger` defaults, so it inherits the
2492
- * host's own button chrome instead of shipping a look of its own.
2786
+ * 3-state wallet connect button. Caller drives the visual state:
2493
2787
  *
2494
- * The default button renders NO count badge (2026-07-30: removed on request --
2495
- * the number read as an unread-notification alarm). The root's cross-target
2496
- * recoverable count still reaches the trigger element as
2497
- * `data-rd-recovery-count` (radix/vaul merge Trigger props onto the `asChild`
2498
- * child too), so a host that WANTS a badge can opt in with its own CSS -- e.g.
2499
- * `button[data-rd-recovery-count]:not([data-rd-recovery-count="0"])::after` --
2500
- * without refetching anything.
2788
+ * - `isConnecting === true` → 스피너 disabled 버튼
2789
+ * - `address` 있음 → WalletInfo + connected pill
2790
+ * - `address`가 있는데 `provider` 없음 → SDK 조회 전이 상태, placeholder 원
2791
+ * - 둘 다 없음 → "Connect Wallet" 버튼
2501
2792
  *
2502
- * Wrapped in `<TrackingBoundary feature="relay">` for the same reason
2503
- * `RelayHistoryTrigger` is: `data-track="open"` is only read by the delegate a
2504
- * boundary installs, and this trigger sits OUTSIDE the portaled `<Content>`'s
2505
- * own boundary.
2793
+ * view-only: wagmi / connect-kit 같은 web3 의존성은 갖지 않으며 모든
2794
+ * 상태/데이터/콜백은 props로 주입받는다. 실제 wagmi 연결 로직은
2795
+ * `@nexus-cross/connect-kit-react`의 상위 래퍼에서 수행한다.
2506
2796
  */
2507
- declare function RelayRecoveryTrigger({ asChild, children }: RelayRecoveryTriggerProps): react_jsx_runtime.JSX.Element;
2508
-
2509
- declare function RelayRecoveryRoot(props: RelayRecoveryProps): react_jsx_runtime.JSX.Element;
2510
- declare const RelayRecovery: typeof RelayRecoveryRoot & {
2511
- Trigger: typeof RelayRecoveryTrigger;
2512
- Content: typeof RelayRecoveryContent;
2513
- };
2514
-
2515
- interface UseRelayOrdersOptions {
2516
- client: RelayClient;
2517
- /** Valid EVM address, or undefined -- undefined clears the list and stops polling. */
2518
- recipient?: string;
2519
- /** Gate: wait for truthy before the first fetch (RelayDeposit passes rawCatalog). Default true. */
2520
- enabled?: boolean;
2521
- /** REST safety-net cadence in milliseconds. Defaults to 30s; the open Deposit popup uses 1s
2522
- * so completion still appears promptly when the SSE event is absent. */
2523
- refetchInterval?: number;
2524
- /** @deprecated Use `refetchInterval`. Retained for compatibility. */
2525
- fallbackPollMs?: number;
2526
- onError?: (e: Error) => void;
2527
- }
2528
- interface UseRelayOrdersResult {
2529
- /** Every order swept from deposits to this recipient so far, newest-first
2530
- * as served by the API. Polled continuously once `recipient` is a valid address. */
2531
- orders: OrderSummary[];
2532
- ordersLoading: boolean;
2533
- ordersError?: Error;
2534
- /** Recipient the current snapshot belongs to. Undefined while a new
2535
- * subscription is waiting for its first accepted fetch, so consumers never
2536
- * baseline a previous recipient's rows as fresh deposits. */
2537
- ordersForRecipient?: string;
2538
- /** Increments after every accepted fetch, even when the client returns the
2539
- * same array reference or the request fails. Consumers use this as a
2540
- * low-frequency refresh signal for related read models such as /recovery. */
2541
- ordersRevision: number;
2542
- /** True once at least one fetch has COMPLETED (success or failure) for the
2543
- * current (recipient, enabled) subscription; false again when it resets.
2544
- * Distinct from `!ordersLoading`, which is also true BEFORE the first fetch
2545
- * has even started -- consumers that snapshot the list (e.g. the deposit
2546
- * wizard's new-order watch) must wait for this, or they baseline against
2547
- * the initial empty state and misread every existing order as new. */
2548
- ordersInitialized: boolean;
2549
- }
2550
- declare function useRelayOrders(opts: UseRelayOrdersOptions): UseRelayOrdersResult;
2797
+ declare function ConnectButton({ isConnecting, address, provider, providerName, accountName, sendAccounts, onConnect, onDisconnect, onCopy, onSelectWallet, onBuy, onBuyDisabledMessage, label, connectingLabel, disconnectLabel, className, theme, env, showBalance, showPortfolio, drawerDirection, modal, connectorId, style, walletInfoStyle, sendTransaction, getTransactionReceipt, estimateGas, onReceive, onBridge, onSend, bridgeTokens, bridgeHistory, getBridgeQuote, getBridgeToTokens, getBridgeApproval, approveBridge, submitBridge, }: ConnectButtonProps): react_jsx_runtime.JSX.Element;
2551
2798
 
2552
- interface UseRelayConfigOptions {
2553
- /** Pre-built client. Takes precedence over apiBaseUrl. */
2554
- client?: RelayClient;
2555
- /** Used to build a client when `client` is not supplied. */
2556
- apiBaseUrl?: string;
2557
- /** Stops the request and clears the current snapshot. Defaults to true. */
2558
- enabled?: boolean;
2559
- /** Optional automatic REST refresh cadence in milliseconds. Disabled when omitted or <= 0. */
2560
- refetchInterval?: number;
2561
- onError?: (error: Error) => void;
2562
- }
2563
- interface UseRelayConfigResult {
2564
- /** Latest GET /v1/config response. */
2565
- config?: Catalog;
2566
- loading: boolean;
2567
- error?: Error;
2568
- /** Re-fetches GET /v1/config using the current client. */
2569
- refresh: () => void;
2570
- }
2571
2799
  /**
2572
- * Public read-only hook for Relay's origin/destination/target catalog.
2800
+ * Wallet provider icons used by `ConnectButton`. Ported from
2801
+ * `@nexus-cross/connect-kit-wagmi` so dapp-ui stays a self-contained,
2802
+ * bundler-agnostic module (no SVG loader required) and doesn't pull in a
2803
+ * web3 dependency for icon assets.
2573
2804
  *
2574
- * The response is a normal REST snapshot, not an SSE stream. Use
2575
- * `refetchInterval` for periodic refreshes or call `refresh` for an immediate
2576
- * read without replacing the client or remounting the component.
2805
+ * Each icon is an inline `data:image/svg+xml` URI so it can be consumed
2806
+ * directly by `<img src={...}>`.
2807
+ *
2808
+ * Source references mirror the ones in `connect-kit-wagmi/src/wallets/icons.ts`:
2809
+ * wallet-crossx.svg → CROSSX_ICON (cross / cross-extension / cross-embedded fallback)
2810
+ * wallet-metamask.svg → METAMASK_ICON
2811
+ * wallet-binance.svg → BINANCE_ICON
2577
2812
  */
2578
- declare function useRelayConfig(opts?: UseRelayConfigOptions): UseRelayConfigResult;
2579
-
2580
- type RecoveryAction = "execute" | "sweep";
2581
- /** Per-attempt progress for `recover()`. "switching" = prompting a chain switch to BSC;
2582
- * "deploying" = the factory.deploy() write is in flight/confirming (only needed when the
2583
- * forwarder wasn't deployed yet); "recovering" = the execute()/sweepToUser() write is in
2584
- * flight/confirming; "done"/"error" are terminal for this attempt. */
2585
- type RecoveryStep = "idle" | "switching" | "deploying" | "recovering" | "done" | "error";
2586
- interface RecoveryState {
2587
- step: RecoveryStep;
2588
- /** Tx hash of the factory.deploy() write -- only set when this attempt needed one. */
2589
- deployTxHash?: string;
2590
- /** Tx hash of the execute()/sweepToUser() write. */
2591
- actionTxHash?: string;
2592
- error?: string;
2593
- }
2813
+ declare const CROSSX_ICON: string;
2814
+ declare const METAMASK_ICON: string;
2815
+ declare const BINANCE_ICON: string;
2816
+ declare const GOOGLE_ICON: string;
2817
+ declare const APPLE_ICON: string;
2594
2818
 
2595
- type RelayRecoveryQueryKey = readonly [
2596
- "relay",
2597
- "recovery",
2598
- number,
2599
- string | null,
2600
- string | null
2601
- ];
2602
2819
  /**
2603
- * React Query policies accepted by useRelayRecovery. The SDK owns the request
2604
- * identity and response shape, so callers cannot replace queryKey/queryFn or
2605
- * inject/select recovery balances.
2820
+ * `SkillsButton`의 `style` prop 타입. 표준 `CSSProperties` 위에
2821
+ * `--sb-*` CSS 커스텀 변수 키를 추가해 자동완성을 지원한다.
2822
+ *
2823
+ * 사용 예: `style={{ "--sb-color": "white", "--sb-bg": "rgba(0,0,0,0.4)" }}`
2824
+ *
2825
+ * CSS 변수는 자식 요소(아이콘, 스피너)로 cascading 되므로, `--sb-color`
2826
+ * 하나만 바꿔도 텍스트·아이콘·스피너가 모두 같은 색을 따라간다.
2606
2827
  */
2607
- type RelayRecoveryQueryOptions = Omit<UseQueryOptions<RecoveryInfo, Error, RecoveryInfo, RelayRecoveryQueryKey>, "queryKey" | "queryFn" | "select" | "initialData" | "initialDataUpdatedAt" | "placeholderData">;
2608
- interface UseRelayRecoveryOptions {
2609
- /** Pre-built client. Takes precedence over apiBaseUrl. */
2610
- client?: RelayClient;
2611
- /** Used to build a client via createRelayClient when client isn't passed. */
2612
- apiBaseUrl?: string;
2613
- /** Connected EVM wallet whose recoverable forwarder balances are queried. */
2614
- recipient?: string;
2615
- /** Optional CROSS delivery target passed to GET /v1/recovery. */
2616
- target?: string;
2617
- /** React Query lifecycle, cache, retry, and refetch policies. */
2618
- query?: RelayRecoveryQueryOptions;
2619
- /** Optional wallet capabilities. Read-only consumers may omit this. */
2620
- wallet?: RelayWalletProps;
2621
- /** Called when GET /v1/recovery returns 401. */
2622
- onUnauthorized?: () => void;
2623
- /** Called after a terminal query or recovery-action error. */
2624
- onError?: (error: Error) => void;
2625
- /** Called once after a recovery transaction confirms successfully. */
2626
- onRecoverySuccess?: (result: RecoverySuccessResult) => void;
2627
- /** Trusted factory override for a self-hosted deployment. */
2628
- trustedFactories?: readonly string[];
2828
+ interface SkillsButtonStyle extends CSSProperties {
2829
+ "--sb-bg"?: string;
2830
+ "--sb-border"?: string;
2831
+ "--sb-border-hover"?: string;
2832
+ "--sb-color"?: string;
2833
+ "--sb-color-hover"?: string;
2834
+ "--sb-radius"?: string;
2835
+ "--sb-height"?: string;
2836
+ "--sb-padding"?: string;
2837
+ "--sb-gap"?: string;
2838
+ "--sb-font-size"?: string;
2839
+ "--sb-font-weight"?: string | number;
2840
+ "--sb-line-height"?: string | number;
2841
+ "--sb-letter-spacing"?: string;
2842
+ "--sb-blur"?: string;
2843
+ "--sb-border-width"?: string;
2844
+ "--sb-icon-size"?: string;
2845
+ "--sb-icon-hover-rotation"?: string;
2846
+ "--sb-spinner-size"?: string;
2847
+ "--sb-spinner-thumb"?: string;
2848
+ "--sb-spinner-track"?: string;
2849
+ "--sb-disabled-opacity"?: string | number;
2850
+ "--sb-press-scale"?: string | number;
2851
+ "--sb-hover-duration"?: string;
2852
+ "--sb-icon-duration"?: string;
2853
+ "--sb-easing"?: string;
2629
2854
  }
2630
- interface UseRelayRecoveryResult {
2631
- info?: RecoveryInfo;
2632
- loading: boolean;
2633
- error?: Error;
2634
- /** True for background refetches as well as the first request. */
2635
- isFetching: boolean;
2636
- /** Invalidates no identities; immediately refetches this hook's fixed query. */
2637
- refresh: () => void;
2638
- /** Signs a recovery transaction for the currently fetched info. */
2639
- recover: (action: RecoveryAction, tokenAddress?: string) => Promise<void>;
2640
- recoveryState: RecoveryState;
2855
+ interface SkillsButtonProps {
2856
+ /** Button text label */
2857
+ label?: string;
2858
+ /** Skills service URL or path to navigate to */
2859
+ href?: string;
2860
+ /** Called when button is clicked (instead of navigation if provided) */
2861
+ onClick?: () => void | Promise<void>;
2862
+ /** Optional CSS class name (merged with built-in `.sb-button`) */
2863
+ className?: string;
2864
+ /** Inline style + CSS custom property overrides (`SkillsButtonStyle`) */
2865
+ style?: SkillsButtonStyle;
2866
+ /** Light/dark surface preset (sets `data-theme`). Defaults to no preset. */
2867
+ theme?: Theme;
2868
+ /** Disable the button */
2869
+ disabled?: boolean;
2870
+ /** Whether button is in loading state */
2871
+ isLoading?: boolean;
2872
+ /** Label shown while loading */
2873
+ loadingLabel?: string;
2874
+ /** Open link in new tab */
2875
+ openInNewTab?: boolean;
2876
+ /** Button type attribute */
2877
+ type?: "button" | "submit" | "reset";
2641
2878
  }
2879
+
2642
2880
  /**
2643
- * Public Recovery API hook. Unlike the widget-internal useRecovery fetch, this
2644
- * hook uses the host QueryClient and accepts React Query policies through
2645
- * `query`. queryKey/queryFn and balance-shaping options remain SDK-owned.
2881
+ * @deprecated 이동 대상은 apps.json(skills)이 단일 소스다. 이 상수는 더 이상
2882
+ * 폴백으로 쓰이지 않으며 하위 호환(공개 export)용으로만 남아 있다.
2646
2883
  */
2647
- declare function useRelayRecovery(opts?: UseRelayRecoveryOptions): UseRelayRecoveryResult;
2648
-
2649
- interface StatusTrackerProps {
2650
- orderId: string;
2651
- /** Latest polled order (steps/txs) from GET /v1/orders/{orderId}, owned by the caller. */
2652
- order?: Order;
2653
- /** Latest poll error, owned by the caller. */
2654
- error?: Error;
2655
- }
2656
- declare function StatusTracker({ orderId, order, error }: StatusTrackerProps): react_jsx_runtime.JSX.Element;
2657
-
2658
- /** Every StandingForwarderFactory / DepositorForwarderFactory this deployment
2659
- * has issued deposit addresses from, on BSC.
2660
- *
2661
- * Superseded factories stay listed on purpose. A forwarder's factory is pinned
2662
- * per address at issuance time (`standing_addresses.factory`, copied onto each
2663
- * order), so a user recovering an address minted before a rotation legitimately
2664
- * gets an older factory back from the API -- dropping it here would block that
2665
- * user from recovering their own funds, which is a worse outcome than the
2666
- * narrow trust gain. Every entry is one of ours either way.
2667
- *
2668
- * Rotation (see backends/deploy/RUNBOOK-canary.md): ADD the new factory, keep
2669
- * the old ones. */
2670
- declare const DEFAULT_TRUSTED_FACTORIES: readonly string[];
2884
+ declare const DEFAULT_SKILLS_HREF = "https://www.onechain.nexus/skills";
2885
+ declare function SkillsButton({ label, href, onClick, className, style, theme, disabled, isLoading, loadingLabel, openInNewTab, type, }: SkillsButtonProps): react_jsx_runtime.JSX.Element;
2671
2886
 
2672
- export { APPLE_ICON, AppLauncher, AppLauncherContent, type AppLauncherContentProps, type AppLauncherProps, AppLauncherTrigger, type AppLauncherTriggerProps, type AppLauncherTriggerStyle, type AppLauncherUsageMode, BINANCE_ICON, type BridgeAmountSource, type BridgeApprovalInfo, type BridgeApproveFn, type BridgeFailedInfo, BridgeFlow, type BridgeFlowProps, type BridgeGetApprovalFn, type BridgeGetToTokensFn, type BridgeHistoryItem, type BridgeInfoRow, type BridgeInfoTokenRef, type BridgeLiquidityInfo, type BridgePathType, type BridgeQuoteFn, type BridgeQuoteInput, type BridgeQuoteResult, type BridgeStatus, type BridgeStep, type BridgeSubmitFn, type BridgeSubmittedInfo, type BridgeToken, type BridgeTxSummary, CHAINS_CONFIG_FILE, CONNECTOR_REGISTRY, CROSSX_ICON, type Catalog, type ChainDisplayMeta, type ChainId, type ChainsConfig, ConnectButton, type ConnectButtonProps, type ConnectButtonStyle, ConnectorId, type ConnectorMeta, type CrossdPosition, type CrossdPositionDetail, type CrossdPositionPoolRef, type CrossdPositionTokenRef, DEFAULT_SKILLS_HREF, DEFAULT_TRUSTED_FACTORIES, DappUiErrorBoundary, type DappUiErrorBoundaryProps, type DappUiFailureReason, type DappUiFeature, type DappUiFlow, type DepositAddressResult, type DrawerDirection$1 as DrawerDirection, type Environment, type EstimateGasArgs, type EstimateGasFn, GOOGLE_ICON, type GameSwapPool, type GameSwapTokenRef, type GasEstimate, type GetBalanceFn, type GetTransactionReceiptArgs, type GetTransactionReceiptFn, type GlobalMenu, type GlobalMenuItem, type GlobalMenuItemAssetUrl, type GlobalMenuItemServiceStatus, type GlobalMenuItemUrl, type InitDappUiSentryOptions, type LpBalanceInfo, type LpBalanceReaderFn, METAMASK_ICON, type OnOutlink, type OrderSummary, type OriginOption, type OutlinkCategory, type OutlinkContext, type OutlinkOrigin, PORTFOLIO_SECTIONS, type PortfolioSection, type PreferredToken, type QuoteResult, type ReadContractFn, type RecentSendAddress, type RecoveryInfo, type RecoverySuccessResult, RelayApiError, type RelayBalance, type RelayClient, type RelayClientOptions, type RelayContractCall, RelayDeposit, type RelayDepositContentProps, type RelayDepositProps, type RelayDepositTriggerProps, type RelayDrawerDirection, type Hex as RelayHex, RelayHistory, type RelayHistoryContentProps, type RelayHistoryProps, type RelayHistoryTriggerProps, RelayRecovery, type RecoveryAction as RelayRecoveryAction, type RelayRecoveryContentProps, type RelayRecoveryProps, type RelayRecoveryQueryKey, type RelayRecoveryQueryOptions, type RecoveryState as RelayRecoveryState, type RecoveryStep as RelayRecoveryStep, type RelayRecoveryTriggerProps, type SendTransactionFn as RelaySendTransactionFn, type RelayTheme, type RelayTxRequest, type RelayWalletProps, SOCIAL_REGISTRY, type SendAccount, type SendAsset, SendFlow, type SendFlowProps, type SendPageProps, type SendStatus, type SendTransactionArgs, type SendTransactionFn$1 as SendTransactionFn, SkillsButton, type SkillsButtonProps, type SkillsButtonStyle, type SocialConfig, type SocialHandlers, type SocialId, type StakingRewardsInfo, type StakingRewardsReaderFn, StatusTracker, type StatusTrackerProps, type SwitchChainFn, TOKEN_STATS_QUERY_KEY, type Theme, type TokenBalance, type TokenBalanceResponse, type TokenStats, type TokenStatsResponse, type TrackDappUiFunnelOptions, type TransactionReceiptResult, USER_BALANCE_QUERY_KEY, type UseRelayConfigOptions, type UseRelayConfigResult, type UseRelayOrdersOptions, type UseRelayOrdersResult, type UseRelayRecoveryOptions, type UseRelayRecoveryResult, WALLET_REGISTRY, type WaitForReceiptFn, type WalletConfig, WalletConnectModal, type WalletConnectModalContentProps, type WalletConnectModalProps, type WalletConnectModalStyle, type WalletConnectModalTriggerProps, type WalletHandlers, type WalletId, WalletInfo, type WalletInfoContentProps, type WalletInfoFooterProps, type WalletInfoNavProps, type WalletInfoProps, type WalletInfoStyle, type WalletInfoTriggerProps, WalletPortfolio, WalletPortfolioBody, type WalletPortfolioBodyProps, type WalletPortfolioContentProps, type WalletPortfolioProps, type WalletPortfolioTriggerProps, type WalletProvider, type WriteContractFn, announceAppLauncherUsage, captureDappUiException, createRelayClient, getChainDisplay, getDappUiSentryScope, initDappUiSentry, normalizeFailureReason, resolveEnvironment, setDappUiAnalyticsUser, trackDappUiEvent, trackDappUiFunnel, useChainDisplay, useChainsConfig, useGlobalMenu, useRelayConfig, useRelayOrders, useRelayRecovery, useTokenBalance, useTokenStats, useWalletDetect };
2887
+ export { APPLE_ICON, AppLauncher, AppLauncherContent, type AppLauncherContentProps, type AppLauncherProps, AppLauncherTrigger, type AppLauncherTriggerProps, type AppLauncherTriggerStyle, type AppLauncherUsageMode, BINANCE_ICON, type BridgeAmountSource, type BridgeApprovalInfo, type BridgeApproveFn, type BridgeFailedInfo, BridgeFlow, type BridgeFlowProps, type BridgeGetApprovalFn, type BridgeGetToTokensFn, type BridgeHistoryItem, type BridgeInfoRow, type BridgeInfoTokenRef, type BridgeLiquidityInfo, type BridgePathType, type BridgeQuoteFn, type BridgeQuoteInput, type BridgeQuoteResult, type BridgeStatus, type BridgeStep, type BridgeSubmitFn, type BridgeSubmittedInfo, type BridgeToken, type BridgeTxSummary, CHAINS_CONFIG_FILE, CONNECTOR_REGISTRY, CROSSX_ICON, type Catalog, type ChainDisplayMeta, type ChainId, type ChainsConfig, ConnectButton, type ConnectButtonProps, type ConnectButtonStyle, ConnectorId, type ConnectorMeta, type CrossdPosition, type CrossdPositionDetail, type CrossdPositionPoolRef, type CrossdPositionTokenRef, DEFAULT_SKILLS_HREF, DEFAULT_TRUSTED_FACTORIES, DappUiErrorBoundary, type DappUiErrorBoundaryProps, type DappUiFailureReason, type DappUiFeature, type DappUiFlow, type DepositAddressResult, type DrawerDirection$1 as DrawerDirection, type Environment, type EstimateGasArgs, type EstimateGasFn, GOOGLE_ICON, type GameSwapPool, type GameSwapTokenRef, type GasEstimate, type GetBalanceFn, GetOneUsd, type GetOneUsdActionId, type GetOneUsdBridgeProps, type GetOneUsdButtonComponent, type GetOneUsdEvent, type GetOneUsdMode, type GetOneUsdPairs, type GetOneUsdProps, type GetOneUsdRelayProps, type GetOneUsdRemoteModes, type GetOneUsdTokenRef, type GetOneUsdWaitForTransaction, type GetTransactionReceiptArgs, type GetTransactionReceiptFn, type GlobalMenu, type GlobalMenuItem, type GlobalMenuItemAssetUrl, type GlobalMenuItemServiceStatus, type GlobalMenuItemUrl, type InitDappUiSentryOptions, type LpBalanceInfo, type LpBalanceReaderFn, METAMASK_ICON, type OnOutlink, type OrderSummary, type OriginOption, type OutlinkCategory, type OutlinkContext, type OutlinkOrigin, PORTFOLIO_SECTIONS, type PortfolioSection, type PreferredToken, type QuoteResult, type ReadContractFn, type RecentSendAddress, type RecoveryInfo, type RecoverySuccessResult, RelayApiError, type RelayBalance, type RelayClient, type RelayClientOptions, type RelayContractCall, RelayDeposit, type RelayDepositContentProps, type RelayDepositProps, type RelayDepositTriggerProps, type RelayDrawerDirection, type Hex as RelayHex, RelayHistory, type RelayHistoryContentProps, type RelayHistoryProps, type RelayHistoryTriggerProps, RelayRecovery, type RecoveryAction as RelayRecoveryAction, type RelayRecoveryContentProps, type RelayRecoveryProps, type RelayRecoveryQueryKey, type RelayRecoveryQueryOptions, type RecoveryState as RelayRecoveryState, type RecoveryStep as RelayRecoveryStep, type RelayRecoveryTriggerProps, type SendTransactionFn as RelaySendTransactionFn, type RelayTheme, type RelayTxRequest, type RelayWalletProps, type ResolvedGetOneUsdRoute, SOCIAL_REGISTRY, type SendAccount, type SendAsset, SendFlow, type SendFlowProps, type SendPageProps, type SendStatus, type SendTransactionArgs, type SendTransactionFn$1 as SendTransactionFn, SkillsButton, type SkillsButtonProps, type SkillsButtonStyle, type SocialConfig, type SocialHandlers, type SocialId, type StakingRewardsInfo, type StakingRewardsReaderFn, StatusTracker, type StatusTrackerProps, type SwitchChainFn, TOKEN_STATS_QUERY_KEY, type Theme, type TokenBalance, type TokenBalanceResponse, type TokenStats, type TokenStatsResponse, type TrackDappUiFunnelOptions, type TransactionReceiptResult, USER_BALANCE_QUERY_KEY, type UseRelayConfigOptions, type UseRelayConfigResult, type UseRelayOrdersOptions, type UseRelayOrdersResult, type UseRelayRecoveryOptions, type UseRelayRecoveryResult, WALLET_REGISTRY, type WaitForReceiptFn, type WalletConfig, WalletConnectModal, type WalletConnectModalContentProps, type WalletConnectModalProps, type WalletConnectModalStyle, type WalletConnectModalTriggerProps, type WalletHandlers, type WalletId, WalletInfo, type WalletInfoContentProps, type WalletInfoFooterProps, type WalletInfoNavProps, type WalletInfoProps, type WalletInfoStyle, type WalletInfoTriggerProps, WalletPortfolio, WalletPortfolioBody, type WalletPortfolioBodyProps, type WalletPortfolioContentProps, type WalletPortfolioProps, type WalletPortfolioTriggerProps, type WalletProvider, type WriteContractFn, announceAppLauncherUsage, captureDappUiException, createRelayClient, findGetOneUsdToken, getChainDisplay, getDappUiSentryScope, getOneUsdTokenKey, initDappUiSentry, isGetOneUsdActionEnabled, isGetOneUsdActionSupported, isGetOneUsdActionVisible, isGetOneUsdTargetAvailable, matchesGetOneUsdToken, normalizeFailureReason, resolveEnvironment, resolveGetOneUsdRoute, setDappUiAnalyticsUser, trackDappUiEvent, trackDappUiFunnel, useChainDisplay, useChainsConfig, useGlobalMenu, useRelayConfig, useRelayOrders, useRelayRecovery, useTokenBalance, useTokenStats, useWalletDetect };