@funkit/connect 9.14.0 → 9.15.0

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.
Files changed (64) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/dist/__generated__/default_configs.d.ts +5 -11
  3. package/dist/__generated__/default_feature_gates.d.ts +3 -2
  4. package/dist/clients/aave.d.ts +92 -0
  5. package/dist/clients/aave.js +156 -0
  6. package/dist/clients/{chunk-LMEQD56M.js → chunk-PLDXBAAH.js} +2 -1
  7. package/dist/clients/fanatics.js +1 -1
  8. package/dist/clients/lighter.d.ts +33 -2
  9. package/dist/clients/lighter.js +121 -2
  10. package/dist/clients/polymarket.d.ts +30 -1
  11. package/dist/clients/polymarket.js +147 -4
  12. package/dist/components/CopyAddress/CopyInputDisplayedAddress.css.d.ts +1 -0
  13. package/dist/components/CopyAddress/CopyInputDisplayedAddress.d.ts +6 -0
  14. package/dist/components/FreeUsdcBanner/FreeUsdcBanner.d.ts +5 -0
  15. package/dist/consts/polymarket.d.ts +7 -0
  16. package/dist/domains/quote.d.ts +11 -0
  17. package/dist/index.css +12 -5
  18. package/dist/index.js +828 -516
  19. package/dist/modals/CheckoutModal/InputAmount/InputAmount.d.ts +4 -0
  20. package/dist/modals/CheckoutModal/InputAmount/aaveClient.d.ts +20 -0
  21. package/dist/modals/CheckoutModal/InputAmount/useAaveNativeSupply.d.ts +44 -0
  22. package/dist/modals/WithdrawalModal/WithdrawalSuccess.d.ts +0 -1
  23. package/dist/modals/WithdrawalModal/useWithdrawal.d.ts +1 -2
  24. package/dist/providers/FunkitCheckoutContext/index.d.ts +8 -0
  25. package/dist/providers/FunkitCheckoutContext/types.d.ts +6 -0
  26. package/dist/wagmi/actions.d.ts +1 -1
  27. package/dist/wallets/walletConnectors/bifrostWallet/bifrostWallet.js +2 -2
  28. package/dist/wallets/walletConnectors/bitgetWallet/bitgetWallet.js +2 -2
  29. package/dist/wallets/walletConnectors/bybitWallet/bybitWallet.js +2 -2
  30. package/dist/wallets/walletConnectors/clvWallet/clvWallet.js +2 -2
  31. package/dist/wallets/walletConnectors/coin98Wallet/coin98Wallet.js +2 -2
  32. package/dist/wallets/walletConnectors/coreWallet/coreWallet.js +2 -2
  33. package/dist/wallets/walletConnectors/foxWallet/foxWallet.js +2 -2
  34. package/dist/wallets/walletConnectors/frontierWallet/frontierWallet.js +2 -2
  35. package/dist/wallets/walletConnectors/gateWallet/gateWallet.js +2 -2
  36. package/dist/wallets/walletConnectors/index.js +51 -51
  37. package/dist/wallets/walletConnectors/metaMaskWallet/metaMaskWallet.js +2 -2
  38. package/dist/wallets/walletConnectors/okxWallet/okxWallet.js +2 -2
  39. package/dist/wallets/walletConnectors/rainbowWallet/rainbowWallet.js +2 -2
  40. package/dist/wallets/walletConnectors/roninWallet/roninWallet.js +2 -2
  41. package/dist/wallets/walletConnectors/safepalWallet/safepalWallet.js +2 -2
  42. package/dist/wallets/walletConnectors/subWallet/subWallet.js +2 -2
  43. package/dist/wallets/walletConnectors/tokenPocketWallet/tokenPocketWallet.js +2 -2
  44. package/dist/wallets/walletConnectors/trustWallet/trustWallet.js +2 -2
  45. package/dist/wallets/walletConnectors/zerionWallet/zerionWallet.js +2 -2
  46. package/package.json +10 -5
  47. package/dist/wallets/walletConnectors/{chunk-VMMROPXK.js → chunk-34HACM5U.js} +3 -3
  48. package/dist/wallets/walletConnectors/{chunk-3ZJN3PXP.js → chunk-5TN5Z2WY.js} +3 -3
  49. package/dist/wallets/walletConnectors/{chunk-OD6B2ISG.js → chunk-6DRCY52E.js} +3 -3
  50. package/dist/wallets/walletConnectors/{chunk-IRHK6SOW.js → chunk-7V33VJAL.js} +3 -3
  51. package/dist/wallets/walletConnectors/{chunk-ZJJWGKB6.js → chunk-APHCF4DT.js} +3 -3
  52. package/dist/wallets/walletConnectors/{chunk-7IEUTLHY.js → chunk-DEFRRPXB.js} +3 -3
  53. package/dist/wallets/walletConnectors/{chunk-OSOB6QYX.js → chunk-FG2LDVXL.js} +3 -3
  54. package/dist/wallets/walletConnectors/{chunk-ZL6XCMV5.js → chunk-HRDPUW3V.js} +3 -3
  55. package/dist/wallets/walletConnectors/{chunk-UYW6MV74.js → chunk-HXWUH73P.js} +3 -3
  56. package/dist/wallets/walletConnectors/{chunk-UFYNHHDU.js → chunk-KWX2SYU2.js} +3 -3
  57. package/dist/wallets/walletConnectors/{chunk-AZYMJ4C6.js → chunk-LCIPVVH5.js} +3 -3
  58. package/dist/wallets/walletConnectors/{chunk-FWM4KTOV.js → chunk-T4ROGPMF.js} +3 -3
  59. package/dist/wallets/walletConnectors/{chunk-J3PJOMO7.js → chunk-UDTBQV4Q.js} +3 -3
  60. package/dist/wallets/walletConnectors/{chunk-55VS2NKG.js → chunk-V6UOWTEZ.js} +3 -3
  61. package/dist/wallets/walletConnectors/{chunk-LEAZMT5Y.js → chunk-VJZWNQOF.js} +3 -3
  62. package/dist/wallets/walletConnectors/{chunk-RZQ4B4Z7.js → chunk-XVBSJCW5.js} +3 -3
  63. package/dist/wallets/walletConnectors/{chunk-IMNI4AGV.js → chunk-YIEASHLS.js} +3 -3
  64. package/dist/wallets/walletConnectors/{chunk-YGMU5VWD.js → chunk-ZPSPK6LH.js} +3 -3
package/CHANGELOG.md CHANGED
@@ -1,5 +1,39 @@
1
1
  # @funkit/connect
2
2
 
3
+ ## 9.15.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 8d525fb: Add Aave deposit fast-path: same-token deposits to supported Aave reserves go directly to the protocol, skipping the quote flow.
8
+ - cc655ee: feat(connect): add Aave V3 supply actions factory + checkout config builder via VaultDepositor
9
+ - e9883ef: Add `display.collateralizationEnabled` to `createAaveSupplyCheckoutConfig`, driving the deposit modal's collateralization subtitle.
10
+ - 11a585d: Register enable-free-usdc-banner feature gate and wire stub component in WithdrawalModal and SourceChange
11
+ - 783d034: feat(api-base, connect): track Lighter Secure withdrawals as `direct_execution` rows.
12
+
13
+ - `@funkit/api-base`: add `DirectExecutionType.EXTERNALLY_FULFILLED` for flows fulfilled outside Fun — backend persists the row but never polls for status.
14
+ - `@funkit/connect`: Lighter Secure withdrawals now post a tracking-only DE row keyed off the L2 tx hash. Fire-and-forget — failures log at warn and never block the UI.
15
+
16
+ - ab5ab81: feat(connect): add createPerpsGenerateActionParams factory for Polymarket Perps deposits
17
+ - 49b653f: Route Polymarket Perps deposits to pUSD: QR/UDA transfers for the `POLYMARKET_PERPS_DEPOSIT` action now target pUSD instead of the configured target asset.
18
+
19
+ ### Patch Changes
20
+
21
+ - 650d56e: Skip the redundant approve(0) reset for Aave supply assets outside `TOKENS_REQUIRING_APPROVAL_RESET`.
22
+ - d9e78ce: test(connect): add direct execution history coverage
23
+ - 3d19a04: test(connect): add direct execution polling coverage
24
+ - 2846b98: Add unit tests for evaluateFeeBreakdown covering wallet, brokerage, card, and unsupported payment methods
25
+ - a0353b7: Show user-entered token amount (not USD) on Lighter Secure withdrawal success screen
26
+ - 86300af: test(connect): test useAmountInput
27
+ - b38e78b: test(connect): add domains/quote tests
28
+ - 8207111: test(connect): test useQuoteRefresh
29
+ - 3fd1475: Add exhaustive unit tests for the quoteMode domain builders
30
+ - 9a2c30a: Extract `SAFE_URL_PROTOCOLS` set in `sanitizeUrl`. Internal refactor, no behavior change.
31
+ - 298eec7: feat: add invoice label support on copyinput component
32
+ - 984ce0c: chore(connect): expand bundled statsig fallbacks
33
+ - Updated dependencies [8d525fb]
34
+ - Updated dependencies [783d034]
35
+ - @funkit/api-base@4.3.0
36
+
3
37
  ## 9.14.0
4
38
 
5
39
  ### Minor Changes
@@ -22,6 +22,8 @@ declare const _default: {
22
22
  readonly '0x881D40237659C251811CEC9c364ef91dC08D300C': "Metamask Swap Router";
23
23
  readonly '0x07d82CD44cd598ACf355Af8c8089b30b2a13B088': "Polymarket Withdrawal Block";
24
24
  readonly '2ygdTkdUtN9PhoMko12bQi6PimJrqxcKmCvQGkCG6SN7': "Polymarket Withdrawal Block";
25
+ readonly '0xd40cBF452e8D6c9dF3e8bbE24eA8b65f859Ae34b': "Polymarket Withdrawal Block";
26
+ readonly GZxiVHg1JM6gCWRG7FwhaD6gPYpcLhiJ21s4ga7Ynfus: "Polymarket Withdrawal Block";
25
27
  };
26
28
  };
27
29
  readonly blockedcountries: {
@@ -298,6 +300,9 @@ declare const _default: {
298
300
  readonly enablesourcegrouplabels: {
299
301
  readonly value: true;
300
302
  };
303
+ readonly enableswapped: {
304
+ readonly value: false;
305
+ };
301
306
  readonly enableswappeddeposit: {
302
307
  readonly value: false;
303
308
  };
@@ -661,17 +666,6 @@ declare const _default: {
661
666
  }, {
662
667
  readonly address: "0x5d3a1Ff2b6BAb83b63cd9AD0787074081a52ef34";
663
668
  }];
664
- }, {
665
- readonly chainId: 2741;
666
- readonly assets: readonly [{
667
- readonly address: "0x84A71ccD554Cc1b02749b35d22F684CC8ec987e1";
668
- }, {
669
- readonly address: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";
670
- }, {
671
- readonly address: "0x3439153EB7AF838Ad19d56E1571FBD09333C2809";
672
- }, {
673
- readonly address: "0x0709F39376dEEe2A2dfC94A58EdEb2Eb9DF012bD";
674
- }];
675
669
  }, {
676
670
  readonly chainId: 5064014;
677
671
  readonly assets: readonly [{
@@ -1,7 +1,9 @@
1
1
  declare const _default: {
2
2
  readonly 'compliance-review-blocker': false;
3
3
  readonly 'enable-across-wallet-flow': false;
4
+ readonly 'enable-add-token-to-wallet': false;
4
5
  readonly 'enable-empty-withdrawal-selection': false;
6
+ readonly 'enable-free-usdc-banner': false;
5
7
  readonly 'enable-permit-toggle': false;
6
8
  readonly 'enable-polymarket-wallet-withdrawal': false;
7
9
  readonly 'enable-swapped-exchanges': false;
@@ -9,9 +11,8 @@ declare const _default: {
9
11
  readonly 'faster-notifications': false;
10
12
  readonly 'new-token-transfer-config': false;
11
13
  readonly 'new-withdrawal-config': false;
12
- readonly 'polymarket-pusd-migration': false;
13
14
  readonly 'saved-card-defaults-to-fiat-tab': false;
14
- readonly 'test-testing-gate': false;
15
+ readonly 'test-feature-gate': false;
15
16
  readonly 'wallet-flow-enable-exact-input-with-actions': false;
16
17
  readonly 'you-receive-remove-swap-impact': false;
17
18
  };
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Aave V3 supply routed through Fun's VaultDepositor proxy.
3
+ *
4
+ * Two entry points:
5
+ * - `createAaveSupplyCheckoutConfig` — high-level; returns a full
6
+ * `FunkitCheckoutConfig` or `undefined` if the chain isn't Fun-supported.
7
+ * The `undefined` return is the canonical "is this Fun-routed?" signal.
8
+ * - `createAaveSupplyActions` — low-level; returns just the actions
9
+ * closure. Use when you need non-default modal copy.
10
+ *
11
+ * Adding a new Aave entrypoint here (e.g. `supplyWithPermit`) requires
12
+ * coordinating with backend: VaultDepositor selector-whitelists each
13
+ * forwarded call. Pool addresses, in contrast, are owned by Aave's
14
+ * registry — callers pass `poolAddress` directly.
15
+ */
16
+ import { type Address } from 'viem';
17
+ import type { FunkitCheckoutActionParams, FunkitCheckoutConfig } from '../providers/FunkitCheckoutContext/types';
18
+ /** Returns true if Fun has a VaultDepositor deployment on `chainId` ready to route Aave supplies. */
19
+ export declare function isAaveSupplySupported(chainId: number): boolean;
20
+ export interface AaveSupplyActionsConfig {
21
+ /** Address that receives the aToken receipt. Typically the connected wallet. */
22
+ onBehalfOf: Address | undefined;
23
+ /** Underlying asset to be supplied. Matches Aave's `DashboardReserve.underlyingAsset`. */
24
+ underlyingAsset: Address;
25
+ /** Aave V3 Pool contract on `chainId`. Aave maintains the registry — pass the value from `@aave-dao/aave-address-book` or your own `marketsData`. */
26
+ poolAddress: Address;
27
+ /** Chain ID — selects the Fun VaultDepositor deployment. */
28
+ chainId: number;
29
+ /** Aave referral code. Defaults to 0; partners with a registered code pass theirs. */
30
+ referralCode?: number;
31
+ }
32
+ /**
33
+ * Builds the `generateActionsParams` callback for an Aave V3 supply routed
34
+ * through VaultDepositor.
35
+ *
36
+ * Usage:
37
+ * ```ts
38
+ * const checkoutConfig: FunkitCheckoutConfig = {
39
+ * // ...
40
+ * generateActionsParams: createAaveSupplyActions({
41
+ * onBehalfOf: walletAddress,
42
+ * underlyingAsset: usdtAddress,
43
+ * poolAddress: AaveV3Ethereum.POOL,
44
+ * chainId: mainnet.id,
45
+ * }),
46
+ * }
47
+ * ```
48
+ */
49
+ export declare function createAaveSupplyActions(config: AaveSupplyActionsConfig): () => Promise<FunkitCheckoutActionParams[]>;
50
+ export interface AaveSupplyCheckoutInput {
51
+ /** Underlying asset (Aave's `DashboardReserve.underlyingAsset`). */
52
+ underlyingAsset: Address;
53
+ /** Aave V3 Pool contract on `chainId`. From Aave's own registry (`marketsData[market].addresses.LENDING_POOL` or `@aave-dao/aave-address-book`). */
54
+ poolAddress: Address;
55
+ /** Chain ID — typically resolved from Aave's `currentMarket` via `marketsData[market].chainId`. */
56
+ chainId: number;
57
+ /** Connected wallet — becomes `onBehalfOf` for the aToken receipt. Pass `undefined` if the wallet isn't connected yet; actions throw at exec time. */
58
+ walletAddress: Address | undefined;
59
+ /** Reserve metadata used for modal display. Optional, but recommended. */
60
+ display?: {
61
+ /** Token symbol (e.g. "USDT") — drives modal title "Supply USDT" and receipt ticker "aUSDT". */
62
+ symbol: string;
63
+ /** Supply APY as a display string (e.g. "2.79"). When provided, the modal subtitle includes "{apy}% APY". */
64
+ supplyAPY?: string;
65
+ /**
66
+ * Whether this supply is/will be enabled as collateral for the user —
67
+ * Aave's "usage as collateral" toggle (the `isCollateral` enablement
68
+ * concept), NOT the reserve-level "can be collateral" eligibility. When
69
+ * provided, the modal subtitle includes "Collateralization enabled" /
70
+ * "disabled".
71
+ */
72
+ collateralizationEnabled?: boolean;
73
+ /** Override modal icon. If omitted, the modal falls back to its own asset-icon resolver. */
74
+ iconSrc?: string;
75
+ };
76
+ /** Aave referral code; defaults to 0. */
77
+ referralCode?: number;
78
+ }
79
+ /**
80
+ * High-level builder for an Aave V3 supply checkout. Returns a
81
+ * `FunkitCheckoutConfig` ready to launch via Fun's checkout, or `undefined`
82
+ * if `chainId` isn't a Fun-supported chain.
83
+ *
84
+ * The `undefined` return is the canonical "is this path Fun-routed?" signal —
85
+ * callers should fall back to Aave's native supply flow when it's returned.
86
+ *
87
+ * Modal copy ("Supply {symbol}", the "{apy}% APY · Collateralization
88
+ * enabled/disabled" subtitle, "a{symbol}" receipt ticker) is owned here so it
89
+ * stays consistent across SDK consumers. Subtitle segments only appear when
90
+ * the corresponding `display` signal is provided.
91
+ */
92
+ export declare function createAaveSupplyCheckoutConfig(input: AaveSupplyCheckoutInput): FunkitCheckoutConfig | undefined;
@@ -0,0 +1,156 @@
1
+ "use client";
2
+
3
+ // src/clients/aave.tsx
4
+ import {
5
+ encodeFunctionData,
6
+ erc20Abi,
7
+ getAddress,
8
+ maxUint256
9
+ } from "viem";
10
+ import { mainnet as mainnet2 } from "viem/chains";
11
+
12
+ // src/utils/isMainnetUsdt.ts
13
+ import { isTokenEquivalent } from "@funkit/utils";
14
+ import { mainnet } from "viem/chains";
15
+ var USDT_MAINNET_ADDRESS = "0xdAC17F958D2ee523a2206206994597C13D831ec7";
16
+ function isMainnetUsdt(chainId, address) {
17
+ return isTokenEquivalent({
18
+ firstTokenAddress: address,
19
+ firstTokenChainId: chainId.toString(),
20
+ secondTokenAddress: USDT_MAINNET_ADDRESS,
21
+ secondTokenChainId: mainnet.id.toString()
22
+ });
23
+ }
24
+
25
+ // src/clients/aave.tsx
26
+ var VAULT_DEPOSITOR_BY_CHAIN_ID = {
27
+ [mainnet2.id]: getAddress("0x40b72bB73B1E9380629B205e7880Fa409ae7fcc9")
28
+ };
29
+ function isAaveSupplySupported(chainId) {
30
+ return chainId in VAULT_DEPOSITOR_BY_CHAIN_ID;
31
+ }
32
+ var AMOUNT_PLACEHOLDER = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffdeadbeefn;
33
+ var AAVE_POOL_ABI = [
34
+ {
35
+ name: "supply",
36
+ type: "function",
37
+ stateMutability: "nonpayable",
38
+ inputs: [
39
+ { name: "asset", type: "address" },
40
+ { name: "amount", type: "uint256" },
41
+ { name: "onBehalfOf", type: "address" },
42
+ { name: "referralCode", type: "uint16" }
43
+ ],
44
+ outputs: []
45
+ }
46
+ ];
47
+ var VAULT_DEPOSITOR_ABI = [
48
+ {
49
+ name: "deposit",
50
+ type: "function",
51
+ stateMutability: "nonpayable",
52
+ inputs: [
53
+ { name: "token", type: "address" },
54
+ { name: "vault", type: "address" },
55
+ { name: "callData", type: "bytes" },
56
+ { name: "minAmountOut", type: "uint256" }
57
+ ],
58
+ outputs: [{ name: "returnData", type: "bytes" }]
59
+ }
60
+ ];
61
+ function createAaveSupplyActions(config) {
62
+ const {
63
+ onBehalfOf,
64
+ underlyingAsset,
65
+ poolAddress,
66
+ chainId,
67
+ referralCode = 0
68
+ } = config;
69
+ const vaultDepositor = VAULT_DEPOSITOR_BY_CHAIN_ID[chainId];
70
+ return async () => {
71
+ if (!vaultDepositor) {
72
+ throw new Error(
73
+ `Aave supply is not yet supported on chain ${chainId}. Supported chain IDs: ${Object.keys(VAULT_DEPOSITOR_BY_CHAIN_ID).join(", ")}`
74
+ );
75
+ }
76
+ if (!onBehalfOf) {
77
+ throw new Error(
78
+ "Please connect your wallet before starting an Aave supply"
79
+ );
80
+ }
81
+ const asset = getAddress(underlyingAsset);
82
+ const supplyCalldata = encodeFunctionData({
83
+ abi: AAVE_POOL_ABI,
84
+ functionName: "supply",
85
+ args: [asset, AMOUNT_PLACEHOLDER, onBehalfOf, referralCode]
86
+ });
87
+ const needsApprovalReset = isMainnetUsdt(chainId, asset);
88
+ const resetApproval = {
89
+ contractAbi: erc20Abi,
90
+ contractAddress: asset,
91
+ functionName: "approve",
92
+ functionArgs: [vaultDepositor, 0n]
93
+ };
94
+ const maxApproval = {
95
+ contractAbi: erc20Abi,
96
+ contractAddress: asset,
97
+ functionName: "approve",
98
+ functionArgs: [vaultDepositor, maxUint256]
99
+ };
100
+ const vaultDeposit = {
101
+ contractAbi: VAULT_DEPOSITOR_ABI,
102
+ contractAddress: vaultDepositor,
103
+ functionName: "deposit",
104
+ functionArgs: [asset, poolAddress, supplyCalldata, 0n]
105
+ };
106
+ return needsApprovalReset ? [resetApproval, maxApproval, vaultDeposit] : [maxApproval, vaultDeposit];
107
+ };
108
+ }
109
+ function buildSupplyModalTitleMeta(display) {
110
+ const parts = [];
111
+ if (display?.supplyAPY !== void 0) {
112
+ parts.push(`${display.supplyAPY}% APY`);
113
+ }
114
+ if (display?.collateralizationEnabled !== void 0) {
115
+ parts.push(
116
+ `Collateralization ${display.collateralizationEnabled ? "enabled" : "disabled"}`
117
+ );
118
+ }
119
+ return parts.length > 0 ? parts.join(" \xB7 ") : void 0;
120
+ }
121
+ function createAaveSupplyCheckoutConfig(input) {
122
+ const {
123
+ underlyingAsset,
124
+ poolAddress,
125
+ chainId,
126
+ walletAddress,
127
+ display,
128
+ referralCode
129
+ } = input;
130
+ if (!isAaveSupplySupported(chainId)) {
131
+ return void 0;
132
+ }
133
+ const symbol = display?.symbol ?? "asset";
134
+ const receiptTicker = `a${symbol}`;
135
+ return {
136
+ modalTitle: `Supply ${symbol}`,
137
+ modalTitleMeta: buildSupplyModalTitleMeta(display),
138
+ targetChain: chainId.toString(),
139
+ targetAsset: underlyingAsset,
140
+ targetAssetTicker: receiptTicker,
141
+ checkoutItemTitle: receiptTicker,
142
+ iconSrc: display?.iconSrc,
143
+ generateActionsParams: createAaveSupplyActions({
144
+ onBehalfOf: walletAddress,
145
+ underlyingAsset,
146
+ poolAddress,
147
+ chainId,
148
+ referralCode
149
+ })
150
+ };
151
+ }
152
+ export {
153
+ createAaveSupplyActions,
154
+ createAaveSupplyCheckoutConfig,
155
+ isAaveSupplySupported
156
+ };
@@ -125,13 +125,14 @@ function preloadRemoteImages(...imageUrls) {
125
125
  import React2, { useMemo, useReducer as useReducer2, useState } from "react";
126
126
 
127
127
  // src/utils/sanitizeUrl.ts
128
+ var SAFE_URL_PROTOCOLS = /* @__PURE__ */ new Set(["https:", "http:"]);
128
129
  function sanitizeUrl(url) {
129
130
  if (!url) {
130
131
  return void 0;
131
132
  }
132
133
  try {
133
134
  const parsed = new URL(url);
134
- if (parsed.protocol === "https:" || parsed.protocol === "http:") {
135
+ if (SAFE_URL_PROTOCOLS.has(parsed.protocol)) {
135
136
  return parsed.href;
136
137
  }
137
138
  return void 0;
@@ -4,7 +4,7 @@ import {
4
4
  Box,
5
5
  preloadRemoteImages,
6
6
  useFunkitTranslation
7
- } from "./chunk-LMEQD56M.js";
7
+ } from "./chunk-PLDXBAAH.js";
8
8
  import "./chunk-H6F75ULR.js";
9
9
 
10
10
  // src/clients/fanatics.tsx
@@ -13,7 +13,7 @@
13
13
  * Both callbacks conform to CustomWithdrawalConfig.withdrawCallback; the
14
14
  * caller provides the actual on-chain implementation.
15
15
  */
16
- import type { Address } from 'viem';
16
+ import { type Address } from 'viem';
17
17
  import type { CustomWithdrawalConfig, MultiMethodWithdrawalConfig } from '../providers/FunkitCheckoutContext/types';
18
18
  export type LighterTransferParams = {
19
19
  toAccountIndex: number;
@@ -93,6 +93,37 @@ export interface LighterSecureWithdrawalConfig {
93
93
  */
94
94
  getMinWithdrawalAmount?: (symbol: string) => number;
95
95
  }
96
+ /**
97
+ * Records a Lighter Secure withdrawal in Fun's direct-execution table as
98
+ * `EXTERNALLY_FULFILLED` — tracking-only, since Fun is not in the execution
99
+ * path. The row is keyed off the L2 tx hash and exists purely for attribution
100
+ * and support tooling; the backend writes a one-time terminal `listenerInfo`
101
+ * and never polls for L1 settlement (see EXTERNALLY_FULFILLED design doc).
102
+ *
103
+ * Fire-and-forget: callers should not await this, and any failure here must
104
+ * not block the withdrawal success UI. Failures log at warn/error and return.
105
+ */
106
+ export declare function trackLighterSecureWithdrawal({ apiKey, userId, txHash, recipientAddr, assetIndex, mainnetTokenAddress, amountTokenUnits, withdrawalUSD, }: {
107
+ apiKey: string;
108
+ userId: string;
109
+ txHash: string;
110
+ recipientAddr: Address;
111
+ /**
112
+ * Lighter L2 asset index. Used as `fromTokenAddress`
113
+ * (`pad(toHex(assetIndex))`) and to resolve symbol + mainnet decimals from
114
+ * {@link LIGHTER_SECURE_ASSETS_BY_INDEX}.
115
+ */
116
+ assetIndex: number;
117
+ /** Mainnet ERC-20 address the L2 asset bridges to (resolved by the modal). */
118
+ mainnetTokenAddress: Address;
119
+ /** User-input amount in token units (e.g. "1.5" for 1.5 ETH). */
120
+ amountTokenUnits: string;
121
+ /**
122
+ * USD value of the withdrawal as computed by the modal (token amount × live
123
+ * spot price). Avoids a separate spot-price round-trip from this helper.
124
+ */
125
+ withdrawalUSD: string;
126
+ }): Promise<void>;
96
127
  /** Single-method config for Lighter's Secure withdrawal (bridge to Ethereum). */
97
128
  export declare function createLighterSecureWithdrawalConfig(config: LighterSecureWithdrawalConfig): CustomWithdrawalConfig;
98
129
  /**
@@ -112,7 +143,7 @@ export declare function createLighterSecureWithdrawalConfig(config: LighterSecur
112
143
  * ```tsx
113
144
  * const { address: l1Address } = useFunkitUserInfo()
114
145
  * const lighter = useLighterWithdrawalConfig(
115
- * userId && walletClient
146
+ * l1Address && walletClient
116
147
  * ? { l1Address, signerClient, sendLighterSecureWithdrawal, ... }
117
148
  * : null,
118
149
  * )
@@ -3,18 +3,25 @@ import {
3
3
  AsyncImage,
4
4
  Box,
5
5
  useFunkitTranslation
6
- } from "./chunk-LMEQD56M.js";
6
+ } from "./chunk-PLDXBAAH.js";
7
7
  import {
8
8
  logger
9
9
  } from "./chunk-H6F75ULR.js";
10
10
 
11
11
  // src/clients/lighter.tsx
12
- import { SOLANA_MAINNET_CHAIN_ID } from "@funkit/chains";
12
+ import {
13
+ DirectExecutionType,
14
+ LIGHTERXYZ_API_KEY as LIGHTERXYZ_API_KEY2,
15
+ createDirectExecution
16
+ } from "@funkit/api-base";
17
+ import { LIGHTER_CHAIN_ID, SOLANA_MAINNET_CHAIN_ID } from "@funkit/chains";
13
18
  import { RELAY_LIGHTER_CHAIN_ID } from "@funkit/fun-relay";
14
19
  import { retry } from "@lifeomic/attempt";
15
20
  import { useQuery as useQuery2 } from "@tanstack/react-query";
16
21
  import i18next from "i18next";
17
22
  import React2, { useMemo as useMemo2 } from "react";
23
+ import { v4 as uuid } from "uuid";
24
+ import { pad, parseUnits, toHex } from "viem";
18
25
  import { arbitrum, base, bsc, mainnet as mainnet2, optimism } from "viem/chains";
19
26
 
20
27
  // src/components/Icons/EvmWallet.tsx
@@ -291,6 +298,17 @@ function formatSecondsTranslated(seconds, t, specifyUnderMinute = false, omitSec
291
298
  // src/clients/lighter.tsx
292
299
  var LIGHTER_USDC_PERPS_ADDRESS = "0x0000000000000000000000000000000000000000";
293
300
  var MAINNET_USDC = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48";
301
+ var LIGHTER_SECURE_ASSETS_BY_INDEX = {
302
+ 1: { symbol: "ETH", decimals: 18 },
303
+ 2: { symbol: "LIT", decimals: 18 },
304
+ 3: { symbol: "USDC", decimals: 6 },
305
+ 5: { symbol: "LINK", decimals: 18 },
306
+ 6: { symbol: "UNI", decimals: 18 },
307
+ 7: { symbol: "AAVE", decimals: 18 },
308
+ 8: { symbol: "SKY", decimals: 18 },
309
+ 9: { symbol: "LDO", decimals: 18 },
310
+ 10: { symbol: "AZTEC", decimals: 18 }
311
+ };
294
312
  var LIGHTER_API_BASE = "https://mainnet.zklighter.elliot.ai";
295
313
  async function getLighterWithdrawalDelay() {
296
314
  const response = await fetch(`${LIGHTER_API_BASE}/api/v1/withdrawalDelay`);
@@ -456,6 +474,86 @@ var LIGHTER_DEFAULT_SECURE_MIN_WITHDRAWAL_AMOUNTS = {
456
474
  LDO: 2,
457
475
  AZTEC: 100
458
476
  };
477
+ function truncateAmountToDecimals(amount, decimals) {
478
+ const [whole = "0", frac = ""] = amount.split(".");
479
+ if (frac.length <= decimals) {
480
+ return amount;
481
+ }
482
+ const truncated = frac.slice(0, decimals);
483
+ return truncated ? `${whole}.${truncated}` : whole;
484
+ }
485
+ async function trackLighterSecureWithdrawal({
486
+ apiKey,
487
+ userId,
488
+ txHash,
489
+ recipientAddr,
490
+ assetIndex,
491
+ mainnetTokenAddress,
492
+ amountTokenUnits,
493
+ withdrawalUSD
494
+ }) {
495
+ const assetMeta = LIGHTER_SECURE_ASSETS_BY_INDEX[assetIndex];
496
+ if (!assetMeta) {
497
+ logger.error(
498
+ "lighter:withdrawal:secure:tracking:unknownAssetIndex",
499
+ new Error(`Unknown Lighter Secure asset index: ${assetIndex}`),
500
+ { assetIndex, txHash }
501
+ );
502
+ return;
503
+ }
504
+ const { symbol, decimals } = assetMeta;
505
+ const estTotalUsd = Number(withdrawalUSD);
506
+ const safeAmount = truncateAmountToDecimals(amountTokenUnits, decimals);
507
+ const baseUnitAmount = parseUnits(safeAmount, decimals).toString();
508
+ const fromTokenAddress = pad(toHex(assetIndex), { size: 20 });
509
+ await createDirectExecution({
510
+ apiKey,
511
+ logger,
512
+ // Lighter L2 tx hashes are not 0x-prefixed EVM hashes — they're the L2's
513
+ // own format. We cast here for convenience to satisfy the DE row type;
514
+ // the backend stores the literal string and we never use it as an EVM hash.
515
+ txHash,
516
+ type: DirectExecutionType.EXTERNALLY_FULFILLED,
517
+ userId,
518
+ recipientAddr,
519
+ fromChainId: LIGHTER_CHAIN_ID.toString(),
520
+ fromTokenAddress,
521
+ toChainId: mainnet2.id.toString(),
522
+ toTokenAddress: mainnetTokenAddress,
523
+ fromAmountBaseUnit: baseUnitAmount,
524
+ toAmountBaseUnit: baseUnitAmount,
525
+ estTotalUsd,
526
+ // Secure withdrawals come out of the user's Lighter account balance; the
527
+ // L1 owner of that account is the recipient (Secure locks to connected wallet).
528
+ sourceOfFund: `balance|lighter-secure|${recipientAddr}`,
529
+ clientMetadata: {
530
+ id: uuid(),
531
+ startTimestampMs: Date.now(),
532
+ finalDollarValue: estTotalUsd,
533
+ latestQuote: null,
534
+ depositAddress: null,
535
+ initSettings: {
536
+ config: {
537
+ targetAsset: mainnetTokenAddress,
538
+ targetChain: mainnet2.id.toString(),
539
+ targetAssetTicker: symbol
540
+ }
541
+ },
542
+ selectedSourceAssetInfo: {
543
+ address: fromTokenAddress,
544
+ symbol,
545
+ chainId: LIGHTER_CHAIN_ID.toString(),
546
+ iconSrc: null
547
+ },
548
+ selectedPaymentMethodInfo: {
549
+ paymentMethod: "LIGHTER_SECURE_WITHDRAWAL",
550
+ title: "",
551
+ description: ""
552
+ },
553
+ isWithdrawal: true
554
+ }
555
+ });
556
+ }
459
557
  function buildSecureWithdrawalCallback({
460
558
  exec
461
559
  }) {
@@ -479,6 +577,7 @@ function buildSecureWithdrawalCallback({
479
577
  );
480
578
  return;
481
579
  }
580
+ const withdrawalUSD = param.withdrawalUSD ?? "0";
482
581
  logger.info("lighter:withdrawal:secure:start", {
483
582
  assetIndex,
484
583
  amountTokenUnits,
@@ -494,6 +593,25 @@ function buildSecureWithdrawalCallback({
494
593
  assetIndex,
495
594
  txHash
496
595
  });
596
+ void trackLighterSecureWithdrawal({
597
+ apiKey: LIGHTERXYZ_API_KEY2,
598
+ // Secure locks the destination to the connected wallet, so the L1
599
+ // recipient address doubles as the userId for tracking purposes.
600
+ userId: destinationAddress,
601
+ txHash,
602
+ recipientAddr: destinationAddress,
603
+ assetIndex,
604
+ mainnetTokenAddress: targetAssetAddress,
605
+ amountTokenUnits,
606
+ withdrawalUSD
607
+ }).catch((err) => {
608
+ logger.warn("lighter:withdrawal:secure:trackingFailed", {
609
+ error: err instanceof Error ? err.message : String(err),
610
+ txHash,
611
+ assetIndex,
612
+ amountTokenUnits
613
+ });
614
+ });
497
615
  return txHash;
498
616
  };
499
617
  }
@@ -658,5 +776,6 @@ function useLighterWithdrawalConfig(config) {
658
776
  export {
659
777
  LIGHTER_DEFAULT_SECURE_MIN_WITHDRAWAL_AMOUNTS,
660
778
  createLighterSecureWithdrawalConfig,
779
+ trackLighterSecureWithdrawal,
661
780
  useLighterWithdrawalConfig
662
781
  };
@@ -16,7 +16,7 @@
16
16
  * {@link WalletWithdrawalConfig}.
17
17
  */
18
18
  import { type Address, type PublicClient, type TransactionReceipt } from 'viem';
19
- import type { CustomWithdrawalConfig, FunkitWithdrawalConfig, WalletWithdrawalConfig } from '../providers/FunkitCheckoutContext/types';
19
+ import type { CustomWithdrawalConfig, FunkitCheckoutActionParams, FunkitWithdrawalConfig, WalletWithdrawalConfig } from '../providers/FunkitCheckoutContext/types';
20
20
  import type { WithdrawalTransaction } from '../wallets/Wallet';
21
21
  export interface PolymarketWithdrawalCallbackConfig {
22
22
  userId: string;
@@ -130,3 +130,32 @@ export declare function createPolymarketWithdrawalConfig(config: PolymarketWithd
130
130
  * ```
131
131
  */
132
132
  export declare function createPolymarketWithdrawalConfig(config: PolymarketWalletUnwrapWithdrawalConfig): WalletWithdrawalConfig;
133
+ export interface PolymarketPerpsDepositConfig {
134
+ /**
135
+ * Polymarket Perps account credited with the deposit
136
+ */
137
+ recipientAddress: Address;
138
+ }
139
+ /**
140
+ * Builds the `generateActionsParams` callback for a Polymarket Perps deposit.
141
+ *
142
+ * Both legs run inside a single Relay Router V3 `cleanupErc20sViaCall` sweep,
143
+ * each mediated by the VaultDepositor proxy so the flow composes with
144
+ * EXACT_INPUT quoting — the VaultDepositor pulls msg.sender's full balance and
145
+ * substitutes AMOUNT_PLACEHOLDER at exec time, so arrival amounts don't need to
146
+ * be known at quote time:
147
+ * 1. USDC.e → pUSD via `CollateralOnramp.wrap`, attributing pUSD to Relay
148
+ * Router V3.
149
+ * 2. pUSD → `POLYMARKET_PERPS_ADDRESS.deposit`, crediting `recipientAddress`.
150
+ *
151
+ * Usage:
152
+ * ```ts
153
+ * const checkoutConfig: FunkitCheckoutConfig = {
154
+ * // ...
155
+ * generateActionsParams: createPerpsGenerateActionParams({
156
+ * recipientAddress: proxyAddress,
157
+ * }),
158
+ * }
159
+ * ```
160
+ */
161
+ export declare function createPerpsGenerateActionParams(config: PolymarketPerpsDepositConfig): () => Promise<FunkitCheckoutActionParams[]>;