@coinlist-co/react 0.6.0 → 0.9.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.
- package/dist/{chunk-5E3P7AMH.js → chunk-AAER5LOL.js} +3 -1
- package/dist/chunk-AAER5LOL.js.map +1 -0
- package/dist/chunk-I5YTJ5SL.js +644 -0
- package/dist/chunk-I5YTJ5SL.js.map +1 -0
- package/dist/{chunk-5C4TEVM7.js → chunk-MKCOK3DF.js} +68 -57
- package/dist/chunk-MKCOK3DF.js.map +1 -0
- package/dist/chunk-Z2HAA2TI.js +768 -0
- package/dist/chunk-Z2HAA2TI.js.map +1 -0
- package/dist/client/index.cjs +2895 -230
- package/dist/client/index.cjs.map +1 -1
- package/dist/client/index.d.cts +902 -29
- package/dist/client/index.d.ts +902 -29
- package/dist/client/index.js +1980 -211
- package/dist/client/index.js.map +1 -1
- package/dist/collections-B84Vw55t.d.cts +28 -0
- package/dist/collections-BQbFJS3g.d.ts +28 -0
- package/dist/requirement-C2w45Q11.d.cts +969 -0
- package/dist/requirement-C2w45Q11.d.ts +969 -0
- package/dist/server/index.cjs +521 -37
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.d.cts +116 -9
- package/dist/server/index.d.ts +116 -9
- package/dist/server/index.js +95 -28
- package/dist/server/index.js.map +1 -1
- package/dist/shared/index.cjs +1245 -72
- package/dist/shared/index.cjs.map +1 -1
- package/dist/shared/index.d.cts +624 -3
- package/dist/shared/index.d.ts +624 -3
- package/dist/shared/index.js +216 -5
- package/dist/shared/index.js.map +1 -1
- package/package.json +7 -3
- package/dist/chunk-5C4TEVM7.js.map +0 -1
- package/dist/chunk-5E3P7AMH.js.map +0 -1
- package/dist/chunk-7SB2GKEU.js +0 -311
- package/dist/chunk-7SB2GKEU.js.map +0 -1
- package/dist/chunk-UEJVCU2J.js +0 -43
- package/dist/chunk-UEJVCU2J.js.map +0 -1
- package/dist/requirement-Dk6nYN1c.d.cts +0 -389
- package/dist/requirement-Dk6nYN1c.d.ts +0 -389
package/dist/client/index.cjs
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __export = (target, all) => {
|
|
7
9
|
for (var name in all)
|
|
@@ -15,18 +17,31 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
17
|
}
|
|
16
18
|
return to;
|
|
17
19
|
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
18
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
29
|
|
|
20
30
|
// src/client/index.ts
|
|
21
31
|
var client_exports = {};
|
|
22
32
|
__export(client_exports, {
|
|
23
33
|
ChecklistStatus: () => ChecklistStatus,
|
|
34
|
+
ClientSwapNamespaceImpl: () => ClientSwapNamespaceImpl,
|
|
24
35
|
CoinListClientInitializationError: () => CoinListClientInitializationError,
|
|
25
36
|
CoinListContext: () => CoinListContext,
|
|
26
37
|
CoinListContextProvider: () => CoinListContextProvider,
|
|
27
38
|
CoinListProvider: () => CoinListProvider,
|
|
28
39
|
CoinListSignInCard: () => CoinListSignInCard,
|
|
29
40
|
CoinListStyleScope: () => CoinListStyleScope,
|
|
41
|
+
ConnectWalletModal: () => ConnectWalletModal,
|
|
42
|
+
ConnectedWalletList: () => ConnectedWalletList,
|
|
43
|
+
IdentityVerification: () => IdentityVerification,
|
|
44
|
+
KycToken: () => KycToken,
|
|
30
45
|
OAUTH_CODE_VERIFIER_KEY: () => OAUTH_CODE_VERIFIER_KEY,
|
|
31
46
|
OAUTH_STATE_KEY: () => OAUTH_STATE_KEY,
|
|
32
47
|
OfferCard: () => OfferCard,
|
|
@@ -37,49 +52,31 @@ __export(client_exports, {
|
|
|
37
52
|
RequirementStatus: () => RequirementStatus,
|
|
38
53
|
RequirementVariant: () => RequirementVariant,
|
|
39
54
|
RequirementsChecklist: () => RequirementsChecklist,
|
|
55
|
+
TaxDocumentModal: () => TaxDocumentModal,
|
|
56
|
+
authorizeWallet: () => authorizeWallet,
|
|
57
|
+
classifyWalletError: () => classifyWalletError,
|
|
58
|
+
connectExternalWalletFlow: () => connectExternalWalletFlow,
|
|
40
59
|
createCoinListClient: () => createCoinListClient,
|
|
60
|
+
executeSwap: () => executeSwap,
|
|
41
61
|
useCoinList: () => useCoinList,
|
|
42
62
|
useCompleteOAuth: () => useCompleteOAuth,
|
|
63
|
+
useConnectWallet: () => useConnectWallet,
|
|
64
|
+
useKycToken: () => useKycToken,
|
|
43
65
|
useOfferDetails: () => useOfferDetails,
|
|
44
66
|
useOffers: () => useOffers,
|
|
67
|
+
useOptionAddresses: () => useOptionAddresses,
|
|
45
68
|
useParticipations: () => useParticipations,
|
|
46
|
-
useRequirements: () => useRequirements
|
|
69
|
+
useRequirements: () => useRequirements,
|
|
70
|
+
useSwapOutputToken: () => useSwapOutputToken,
|
|
71
|
+
useSwapQuote: () => useSwapQuote,
|
|
72
|
+
useSwapTokenBalances: () => useSwapTokenBalances,
|
|
73
|
+
useTaxDocument: () => useTaxDocument
|
|
47
74
|
});
|
|
48
75
|
module.exports = __toCommonJS(client_exports);
|
|
49
76
|
|
|
50
77
|
// src/client/CoinListProvider.tsx
|
|
51
78
|
var import_react = require("react");
|
|
52
79
|
|
|
53
|
-
// src/client/generated/sdk-styles.gen.ts
|
|
54
|
-
var sdkStyles = '/*! tailwindcss v4.2.1 | MIT License | https://tailwindcss.com */\n@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-space-y-reverse:0;--tw-divide-y-reverse:0;--tw-border-style:solid;--tw-gradient-position:initial;--tw-gradient-from:#0000;--tw-gradient-via:#0000;--tw-gradient-to:#0000;--tw-gradient-stops:initial;--tw-gradient-via-stops:initial;--tw-gradient-from-position:0%;--tw-gradient-via-position:50%;--tw-gradient-to-position:100%;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-duration:initial;--tw-ease:initial;--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0}}}@layer theme{:root,:host{--clcosdk-color-red-400:oklch(70.4% .191 22.216);--clcosdk-color-red-500:oklch(63.7% .237 25.331);--clcosdk-color-amber-500:oklch(76.9% .188 70.08);--clcosdk-color-gray-400:oklch(70.7% .022 261.325);--clcosdk-color-gray-500:oklch(55.1% .027 264.364);--clcosdk-spacing:.25rem;--clcosdk-container-md:28rem;--clcosdk-text-xs:.75rem;--clcosdk-text-xs--line-height:calc(1 / .75);--clcosdk-text-sm:.875rem;--clcosdk-text-sm--line-height:calc(1.25 / .875);--clcosdk-text-base:1rem;--clcosdk-text-base--line-height:calc(1.5 / 1);--clcosdk-font-weight-normal:400;--clcosdk-font-weight-medium:500;--clcosdk-font-weight-semibold:600;--clcosdk-radius-md:.375rem;--clcosdk-radius-lg:.5rem;--clcosdk-radius-2xl:1rem;--clcosdk-ease-in-out:cubic-bezier(.4, 0, .2, 1);--clcosdk-animate-spin:spin 1s linear infinite;--clcosdk-color-brand-primary:var(--color-brand-primary)}}@layer base{.clco-sdk-root{--color-brand-primary:#171717;--color-brand-primary-hover:#000;--color-brand-primary-active:#262626;--color-accent:#2b3a67;--color-accent-hover:#243057;--color-accent-active:#1d2647;--color-accent-focus:#c7d2fe;--color-accent-subtle:#eef1f8;--color-text-primary:#171717;--color-text-secondary:#8c8c8c;--color-text-disabled:#d1d1d1;--color-text-inverse:#fff;--color-background:#fff;--color-surface:#fafafa;--color-section:#f3f3f3;--color-border:#e5e5e5;--color-divider:#ececec;--color-overlay:#00000080;--color-positive:#15803d;--color-positive-subtle:#dcfce7;--color-negative:#dc2626;--color-negative-subtle:#fee2e2;--color-success:#2c8c5e;--color-success-subtle:#e6f4ec;--color-success-border:#cfe9db;--color-warning:#e08a1a;--color-warning-subtle:#fff7ed;--color-warning-border:#fdead7;--color-error:#b42318;--color-error-subtle:#feeceb;--color-error-border:#fbd5d2}@media (prefers-color-scheme:dark){.clco-sdk-root:not(:where(.light,.light *)){--color-brand-primary:#f4f4f5;--color-brand-primary-hover:#fff;--color-brand-primary-active:#e4e4e7;--color-accent:#6f82c9;--color-accent-hover:#8799e4;--color-accent-active:#5b6fcf;--color-accent-focus:#6f82c959;--color-accent-subtle:#6f82c91f;--color-text-primary:#f4f4f5;--color-text-secondary:#a1a1aa;--color-text-disabled:#71717a;--color-text-inverse:#171717;--color-background:#0f1115;--color-surface:#161a20;--color-section:#20242c;--color-border:#2a2e35;--color-divider:#323741;--color-overlay:#000000b3;--color-positive:#22c55e;--color-positive-subtle:#22c55e1f;--color-negative:#ef4444;--color-negative-subtle:#ef44441f;--color-success:#34d399;--color-success-subtle:#34d3991f;--color-success-border:#34d39940;--color-warning:#f59e0b;--color-warning-subtle:#f59e0b1f;--color-warning-border:#f59e0b40;--color-error:#f87171;--color-error-subtle:#f871711f;--color-error-border:#f8717140}}:where(.dark,.dark *) .clco-sdk-root{--color-brand-primary:#f4f4f5;--color-brand-primary-hover:#fff;--color-brand-primary-active:#e4e4e7;--color-accent:#6f82c9;--color-accent-hover:#8799e4;--color-accent-active:#5b6fcf;--color-accent-focus:#6f82c959;--color-accent-subtle:#6f82c91f;--color-text-primary:#f4f4f5;--color-text-secondary:#a1a1aa;--color-text-disabled:#71717a;--color-text-inverse:#171717;--color-background:#0f1115;--color-surface:#161a20;--color-section:#20242c;--color-border:#2a2e35;--color-divider:#323741;--color-overlay:#000000b3;--color-positive:#22c55e;--color-positive-subtle:#22c55e1f;--color-negative:#ef4444;--color-negative-subtle:#ef44441f;--color-success:#34d399;--color-success-subtle:#34d3991f;--color-success-border:#34d39940;--color-warning:#f59e0b;--color-warning-subtle:#f59e0b1f;--color-warning-border:#f59e0b40;--color-error:#f87171;--color-error-subtle:#f871711f;--color-error-border:#f8717140}.clco-sdk-root{color:var(--color-text-primary);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-family:Inter,sans-serif}.clco-sdk-root *,.clco-sdk-root :before,.clco-sdk-root :after{box-sizing:border-box}.clco-sdk-root button{appearance:none;cursor:pointer;font:inherit;color:inherit;background:0 0;border:none;padding:0}.clco-sdk-root a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}.clco-sdk-root ul,.clco-sdk-root ol{margin:0;padding:0;list-style:none}.clco-sdk-root img,.clco-sdk-root svg{max-width:100%;display:block}}@layer components;@layer utilities{.clcosdk\\:absolute{position:absolute}.clcosdk\\:relative{position:relative}.clcosdk\\:inset-0{inset:calc(var(--clcosdk-spacing) * 0)}.clcosdk\\:top-4{top:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:right-4{right:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:mt-4{margin-top:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:mb-6{margin-bottom:calc(var(--clcosdk-spacing) * 6)}.clcosdk\\:flex{display:flex}.clcosdk\\:grid{display:grid}.clcosdk\\:inline-flex{display:inline-flex}.clcosdk\\:h-3{height:calc(var(--clcosdk-spacing) * 3)}.clcosdk\\:h-4{height:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:h-5{height:calc(var(--clcosdk-spacing) * 5)}.clcosdk\\:h-6{height:calc(var(--clcosdk-spacing) * 6)}.clcosdk\\:h-9{height:calc(var(--clcosdk-spacing) * 9)}.clcosdk\\:h-11{height:calc(var(--clcosdk-spacing) * 11)}.clcosdk\\:h-12{height:calc(var(--clcosdk-spacing) * 12)}.clcosdk\\:h-14{height:calc(var(--clcosdk-spacing) * 14)}.clcosdk\\:h-28{height:calc(var(--clcosdk-spacing) * 28)}.clcosdk\\:h-52{height:calc(var(--clcosdk-spacing) * 52)}.clcosdk\\:h-\\[18px\\]{height:18px}.clcosdk\\:h-auto{height:auto}.clcosdk\\:h-full{height:100%}.clcosdk\\:min-h-0{min-height:calc(var(--clcosdk-spacing) * 0)}.clcosdk\\:min-h-40{min-height:calc(var(--clcosdk-spacing) * 40)}.clcosdk\\:min-h-\\[2\\.4rem\\]{min-height:2.4rem}.clcosdk\\:w-4{width:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:w-5{width:calc(var(--clcosdk-spacing) * 5)}.clcosdk\\:w-6{width:calc(var(--clcosdk-spacing) * 6)}.clcosdk\\:w-12{width:calc(var(--clcosdk-spacing) * 12)}.clcosdk\\:w-16{width:calc(var(--clcosdk-spacing) * 16)}.clcosdk\\:w-28{width:calc(var(--clcosdk-spacing) * 28)}.clcosdk\\:w-80{width:calc(var(--clcosdk-spacing) * 80)}.clcosdk\\:w-96{width:calc(var(--clcosdk-spacing) * 96)}.clcosdk\\:w-\\[16px\\]{width:16px}.clcosdk\\:w-\\[448px\\]{width:448px}.clcosdk\\:w-auto{width:auto}.clcosdk\\:w-full{width:100%}.clcosdk\\:max-w-\\[22rem\\]{max-width:22rem}.clcosdk\\:max-w-\\[28rem\\]{max-width:28rem}.clcosdk\\:max-w-\\[30rem\\]{max-width:30rem}.clcosdk\\:max-w-\\[1200px\\]{max-width:1200px}.clcosdk\\:max-w-md{max-width:var(--clcosdk-container-md)}.clcosdk\\:shrink-0{flex-shrink:0}.clcosdk\\:rotate-90{rotate:90deg}.clcosdk\\:animate-spin{animation:var(--clcosdk-animate-spin)}.clcosdk\\:cursor-pointer{cursor:pointer}.clcosdk\\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.clcosdk\\:grid-rows-\\[0fr\\]{grid-template-rows:0fr}.clcosdk\\:grid-rows-\\[1fr\\]{grid-template-rows:1fr}.clcosdk\\:flex-col{flex-direction:column}.clcosdk\\:flex-wrap{flex-wrap:wrap}.clcosdk\\:items-center{align-items:center}.clcosdk\\:items-start{align-items:flex-start}.clcosdk\\:justify-between{justify-content:space-between}.clcosdk\\:justify-center{justify-content:center}.clcosdk\\:gap-1{gap:calc(var(--clcosdk-spacing) * 1)}.clcosdk\\:gap-2{gap:calc(var(--clcosdk-spacing) * 2)}.clcosdk\\:gap-3{gap:calc(var(--clcosdk-spacing) * 3)}.clcosdk\\:gap-4{gap:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:gap-5{gap:calc(var(--clcosdk-spacing) * 5)}.clcosdk\\:gap-6{gap:calc(var(--clcosdk-spacing) * 6)}.clcosdk\\:gap-8{gap:calc(var(--clcosdk-spacing) * 8)}.clcosdk\\:gap-\\[5px\\]{gap:5px}:where(.clcosdk\\:space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--clcosdk-spacing) * 3) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--clcosdk-spacing) * 3) * calc(1 - var(--tw-space-y-reverse)))}:where(.clcosdk\\:space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--clcosdk-spacing) * 4) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--clcosdk-spacing) * 4) * calc(1 - var(--tw-space-y-reverse)))}:where(.clcosdk\\:divide-y>:not(:last-child)){--tw-divide-y-reverse:0;border-bottom-style:var(--tw-border-style);border-top-style:var(--tw-border-style);border-top-width:calc(1px * var(--tw-divide-y-reverse));border-bottom-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)))}:where(.clcosdk\\:divide-border>:not(:last-child)){border-color:var(--color-border)}:where(.clcosdk\\:divide-divider>:not(:last-child)){border-color:var(--color-divider)}.clcosdk\\:overflow-hidden{overflow:hidden}.clcosdk\\:rounded-2xl{border-radius:var(--clcosdk-radius-2xl)}.clcosdk\\:rounded-btn{border-radius:12px}.clcosdk\\:rounded-card{border-radius:24px}.clcosdk\\:rounded-full{border-radius:3.40282e38px}.clcosdk\\:rounded-lg{border-radius:var(--clcosdk-radius-lg)}.clcosdk\\:rounded-md{border-radius:var(--clcosdk-radius-md)}.clcosdk\\:border{border-style:var(--tw-border-style);border-width:1px}.clcosdk\\:border-2{border-style:var(--tw-border-style);border-width:2px}.clcosdk\\:border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.clcosdk\\:border-dashed{--tw-border-style:dashed;border-style:dashed}.clcosdk\\:border-accent\\/50{border-color:var(--color-accent)}@supports (color:color-mix(in lab, red, red)){.clcosdk\\:border-accent\\/50{border-color:color-mix(in oklab, var(--color-accent) 50%, transparent)}}.clcosdk\\:border-accent\\/60{border-color:var(--color-accent)}@supports (color:color-mix(in lab, red, red)){.clcosdk\\:border-accent\\/60{border-color:color-mix(in oklab, var(--color-accent) 60%, transparent)}}.clcosdk\\:border-amber-500{border-color:var(--clcosdk-color-amber-500)}.clcosdk\\:border-border,.clcosdk\\:border-border\\/60{border-color:var(--color-border)}@supports (color:color-mix(in lab, red, red)){.clcosdk\\:border-border\\/60{border-color:color-mix(in oklab, var(--color-border) 60%, transparent)}}.clcosdk\\:border-current{border-color:currentColor}.clcosdk\\:border-divider{border-color:var(--color-divider)}.clcosdk\\:border-error-border{border-color:var(--color-error-border)}.clcosdk\\:border-success-border{border-color:var(--color-success-border)}.clcosdk\\:border-warning-border{border-color:var(--color-warning-border)}.clcosdk\\:border-t-transparent{border-top-color:#0000}.clcosdk\\:bg-accent\\/10{background-color:var(--color-accent)}@supports (color:color-mix(in lab, red, red)){.clcosdk\\:bg-accent\\/10{background-color:color-mix(in oklab, var(--color-accent) 10%, transparent)}}.clcosdk\\:bg-background{background-color:var(--color-background)}.clcosdk\\:bg-brand-primary{background-color:var(--color-brand-primary)}.clcosdk\\:bg-error-subtle{background-color:var(--color-error-subtle)}.clcosdk\\:bg-section{background-color:var(--color-section)}.clcosdk\\:bg-success-subtle{background-color:var(--color-success-subtle)}.clcosdk\\:bg-surface{background-color:var(--color-surface)}.clcosdk\\:bg-transparent{background-color:#0000}.clcosdk\\:bg-warning-subtle{background-color:var(--color-warning-subtle)}.clcosdk\\:bg-gradient-to-b{--tw-gradient-position:to bottom in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.clcosdk\\:bg-gradient-to-br{--tw-gradient-position:to bottom right in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.clcosdk\\:from-surface{--tw-gradient-from:var(--color-surface);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.clcosdk\\:from-transparent{--tw-gradient-from:transparent;--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.clcosdk\\:via-section{--tw-gradient-via:var(--color-section);--tw-gradient-via-stops:var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-via) var(--tw-gradient-via-position), var(--tw-gradient-to) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-via-stops)}.clcosdk\\:via-transparent{--tw-gradient-via:transparent;--tw-gradient-via-stops:var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-via) var(--tw-gradient-via-position), var(--tw-gradient-to) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-via-stops)}.clcosdk\\:to-background{--tw-gradient-to:var(--color-background);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.clcosdk\\:to-overlay\\/35{--tw-gradient-to:var(--color-overlay)}@supports (color:color-mix(in lab, red, red)){.clcosdk\\:to-overlay\\/35{--tw-gradient-to:color-mix(in oklab, var(--color-overlay) 35%, transparent)}}.clcosdk\\:to-overlay\\/35{--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.clcosdk\\:object-cover{object-fit:cover}.clcosdk\\:p-0{padding:calc(var(--clcosdk-spacing) * 0)}.clcosdk\\:p-1\\.5{padding:calc(var(--clcosdk-spacing) * 1.5)}.clcosdk\\:p-3{padding:calc(var(--clcosdk-spacing) * 3)}.clcosdk\\:p-6{padding:calc(var(--clcosdk-spacing) * 6)}.clcosdk\\:p-8{padding:calc(var(--clcosdk-spacing) * 8)}.clcosdk\\:px-2{padding-inline:calc(var(--clcosdk-spacing) * 2)}.clcosdk\\:px-4{padding-inline:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:px-5{padding-inline:calc(var(--clcosdk-spacing) * 5)}.clcosdk\\:px-6{padding-inline:calc(var(--clcosdk-spacing) * 6)}.clcosdk\\:pt-4{padding-top:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:pb-4{padding-bottom:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:text-center{text-align:center}.clcosdk\\:text-left{text-align:left}.clcosdk\\:text-base{font-size:var(--clcosdk-text-base);line-height:var(--tw-leading,var(--clcosdk-text-base--line-height))}.clcosdk\\:text-sm{font-size:var(--clcosdk-text-sm);line-height:var(--tw-leading,var(--clcosdk-text-sm--line-height))}.clcosdk\\:text-xs{font-size:var(--clcosdk-text-xs);line-height:var(--tw-leading,var(--clcosdk-text-xs--line-height))}.clcosdk\\:text-\\[11px\\]{font-size:11px}.clcosdk\\:text-\\[12px\\]{font-size:12px}.clcosdk\\:text-\\[14px\\]{font-size:14px}.clcosdk\\:text-\\[16px\\]{font-size:16px}.clcosdk\\:text-\\[18px\\]{font-size:18px}.clcosdk\\:text-\\[22px\\]{font-size:22px}.clcosdk\\:text-\\[28px\\]{font-size:28px}.clcosdk\\:text-\\[36px\\]{font-size:36px}.clcosdk\\:text-\\[48px\\]{font-size:48px}.clcosdk\\:text-\\[64px\\]{font-size:64px}.clcosdk\\:leading-\\[110\\%\\]{--tw-leading:110%;line-height:110%}.clcosdk\\:leading-\\[120\\%\\]{--tw-leading:120%;line-height:120%}.clcosdk\\:leading-\\[125\\%\\]{--tw-leading:125%;line-height:125%}.clcosdk\\:leading-\\[130\\%\\]{--tw-leading:130%;line-height:130%}.clcosdk\\:leading-\\[135\\%\\]{--tw-leading:135%;line-height:135%}.clcosdk\\:leading-\\[140\\%\\]{--tw-leading:140%;line-height:140%}.clcosdk\\:leading-\\[150\\%\\]{--tw-leading:150%;line-height:150%}.clcosdk\\:font-medium{--tw-font-weight:var(--clcosdk-font-weight-medium);font-weight:var(--clcosdk-font-weight-medium)}.clcosdk\\:font-normal{--tw-font-weight:var(--clcosdk-font-weight-normal);font-weight:var(--clcosdk-font-weight-normal)}.clcosdk\\:font-semibold{--tw-font-weight:var(--clcosdk-font-weight-semibold);font-weight:var(--clcosdk-font-weight-semibold)}.clcosdk\\:tracking-\\[0\\.12px\\]{--tw-tracking:.12px;letter-spacing:.12px}.clcosdk\\:tracking-\\[0\\.28px\\]{--tw-tracking:.28px;letter-spacing:.28px}.clcosdk\\:whitespace-nowrap{white-space:nowrap}.clcosdk\\:text-error{color:var(--color-error)}.clcosdk\\:text-success{color:var(--color-success)}.clcosdk\\:text-text-inverse{color:var(--color-text-inverse)}.clcosdk\\:text-text-primary{color:var(--color-text-primary)}.clcosdk\\:text-text-secondary{color:var(--color-text-secondary)}.clcosdk\\:text-warning{color:var(--color-warning)}.clcosdk\\:capitalize{text-transform:capitalize}.clcosdk\\:underline{text-decoration-line:underline}.clcosdk\\:underline-offset-2{text-underline-offset:2px}.clcosdk\\:underline-offset-4{text-underline-offset:4px}.clcosdk\\:opacity-60{opacity:.6}.clcosdk\\:shadow-\\[0_0_0_3px_rgba\\(59\\,130\\,246\\,0\\.2\\)\\]{--tw-shadow:0 0 0 3px var(--tw-shadow-color,#3b82f633);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.clcosdk\\:shadow-\\[0_0_0_3px_rgba\\(59\\,130\\,246\\,0\\.18\\)\\]{--tw-shadow:0 0 0 3px var(--tw-shadow-color,#3b82f62e);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.clcosdk\\:shadow-\\[0_0_0_3px_rgba\\(59\\,130\\,246\\,0\\.25\\)\\]{--tw-shadow:0 0 0 3px var(--tw-shadow-color,#3b82f640);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.clcosdk\\:shadow-\\[0_10px_24px_rgba\\(0\\,0\\,0\\,0\\.18\\)\\]{--tw-shadow:0 10px 24px var(--tw-shadow-color,#0000002e);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.clcosdk\\:shadow-\\[0_10px_24px_rgba\\(0\\,0\\,0\\,0\\.25\\)\\]{--tw-shadow:0 10px 24px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.clcosdk\\:shadow-card{--tw-shadow:0px 4px 6px -2px var(--tw-shadow-color,#0000000d), 0px 12px 24px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.clcosdk\\:transition-\\[grid-template-rows\\]{transition-property:grid-template-rows;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.clcosdk\\:transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.clcosdk\\:transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.clcosdk\\:transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.clcosdk\\:duration-200{--tw-duration:.2s;transition-duration:.2s}.clcosdk\\:duration-300{--tw-duration:.3s;transition-duration:.3s}.clcosdk\\:ease-in-out{--tw-ease:var(--clcosdk-ease-in-out);transition-timing-function:var(--clcosdk-ease-in-out)}@media (hover:hover){.clcosdk\\:hover\\:-translate-y-0\\.5:hover{--tw-translate-y:calc(var(--clcosdk-spacing) * -.5);translate:var(--tw-translate-x) var(--tw-translate-y)}.clcosdk\\:hover\\:border-divider:hover{border-color:var(--color-divider)}.clcosdk\\:hover\\:bg-\\[\\#fcdcd8\\]:hover{background-color:#fcdcd8}.clcosdk\\:hover\\:bg-border:hover{background-color:var(--color-border)}.clcosdk\\:hover\\:bg-brand-primary:hover{background-color:var(--color-brand-primary)}.clcosdk\\:hover\\:bg-brand-primary-hover:hover{background-color:var(--color-brand-primary-hover)}.clcosdk\\:hover\\:bg-section:hover{background-color:var(--color-section)}.clcosdk\\:hover\\:bg-surface:hover{background-color:var(--color-surface)}.clcosdk\\:hover\\:text-\\[\\#8b1a13\\]:hover{color:#8b1a13}.clcosdk\\:hover\\:text-text-primary:hover{color:var(--color-text-primary)}.clcosdk\\:hover\\:underline:hover{text-decoration-line:underline}.clcosdk\\:hover\\:shadow-\\[0px_14px_32px_-10px_rgba\\(0\\,0\\,0\\,0\\.35\\)\\]:hover{--tw-shadow:0px 14px 32px -10px var(--tw-shadow-color,#00000059);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}}.clcosdk\\:focus-visible\\:ring-2:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.clcosdk\\:focus-visible\\:ring-accent-focus:focus-visible{--tw-ring-color:var(--color-accent-focus)}.clcosdk\\:focus-visible\\:ring-gray-400:focus-visible{--tw-ring-color:var(--clcosdk-color-gray-400)}.clcosdk\\:focus-visible\\:ring-gray-500:focus-visible{--tw-ring-color:var(--clcosdk-color-gray-500)}.clcosdk\\:focus-visible\\:ring-red-400:focus-visible{--tw-ring-color:var(--clcosdk-color-red-400)}.clcosdk\\:focus-visible\\:ring-red-500:focus-visible{--tw-ring-color:var(--clcosdk-color-red-500)}.clcosdk\\:focus-visible\\:ring-offset-2:focus-visible{--tw-ring-offset-width:2px;--tw-ring-offset-shadow:var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)}.clcosdk\\:focus-visible\\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.clcosdk\\:active\\:bg-\\[\\#d9d9d9\\]:active{background-color:#d9d9d9}.clcosdk\\:active\\:bg-\\[\\#f9c9c4\\]:active{background-color:#f9c9c4}.clcosdk\\:active\\:bg-border:active{background-color:var(--color-border)}.clcosdk\\:active\\:bg-brand-primary-active:active{background-color:var(--color-brand-primary-active)}.clcosdk\\:active\\:text-\\[\\#6d1510\\]:active{color:#6d1510}.clcosdk\\:disabled\\:pointer-events-none:disabled{pointer-events:none}.clcosdk\\:disabled\\:opacity-40:disabled{opacity:.4}@media (prefers-color-scheme:dark){@media (hover:hover){.clcosdk\\:dark\\:hover\\:bg-\\[rgba\\(248\\,113\\,113\\,0\\.20\\)\\]:not(:where(.light,.light *)):hover{background-color:#f8717133}}}@media (hover:hover){.clcosdk\\:dark\\:hover\\:bg-\\[rgba\\(248\\,113\\,113\\,0\\.20\\)\\]:where(.dark,.dark *):hover{background-color:#f8717133}}@media (prefers-color-scheme:dark){@media (hover:hover){.clcosdk\\:dark\\:hover\\:text-\\[\\#fca5a5\\]:not(:where(.light,.light *)):hover{color:#fca5a5}}}@media (hover:hover){.clcosdk\\:dark\\:hover\\:text-\\[\\#fca5a5\\]:where(.dark,.dark *):hover{color:#fca5a5}}@media (prefers-color-scheme:dark){.clcosdk\\:dark\\:active\\:bg-\\[rgba\\(248\\,113\\,113\\,0\\.30\\)\\]:not(:where(.light,.light *)):active{background-color:#f871714d}}.clcosdk\\:dark\\:active\\:bg-\\[rgba\\(248\\,113\\,113\\,0\\.30\\)\\]:where(.dark,.dark *):active{background-color:#f871714d}@media (prefers-color-scheme:dark){.clcosdk\\:dark\\:active\\:bg-divider:not(:where(.light,.light *)):active{background-color:var(--color-divider)}}.clcosdk\\:dark\\:active\\:bg-divider:where(.dark,.dark *):active{background-color:var(--color-divider)}@media (prefers-color-scheme:dark){.clcosdk\\:dark\\:active\\:text-\\[\\#f87171\\]:not(:where(.light,.light *)):active{color:#f87171}}.clcosdk\\:dark\\:active\\:text-\\[\\#f87171\\]:where(.dark,.dark *):active{color:#f87171}.clcosdk\\:\\[\\&_circle\\]\\:fill-error-subtle circle{fill:var(--color-error-subtle)}.clcosdk\\:\\[\\&_circle\\]\\:fill-success-subtle circle{fill:var(--color-success-subtle)}.clcosdk\\:\\[\\&_circle\\]\\:fill-warning-subtle circle{fill:var(--color-warning-subtle)}}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-divide-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-gradient-position{syntax:"*";inherits:false}@property --tw-gradient-from{syntax:"<color>";inherits:false;initial-value:#0000}@property --tw-gradient-via{syntax:"<color>";inherits:false;initial-value:#0000}@property --tw-gradient-to{syntax:"<color>";inherits:false;initial-value:#0000}@property --tw-gradient-stops{syntax:"*";inherits:false}@property --tw-gradient-via-stops{syntax:"*";inherits:false}@property --tw-gradient-from-position{syntax:"<length-percentage>";inherits:false;initial-value:0%}@property --tw-gradient-via-position{syntax:"<length-percentage>";inherits:false;initial-value:50%}@property --tw-gradient-to-position{syntax:"<length-percentage>";inherits:false;initial-value:100%}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@keyframes spin{to{transform:rotate(360deg)}}';
|
|
55
|
-
|
|
56
|
-
// src/client/CoinListStyleScope.tsx
|
|
57
|
-
var import_jsx_runtime = require("react/jsx-runtime");
|
|
58
|
-
function CoinListStyleScope({ children }) {
|
|
59
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
60
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("link", { rel: "preconnect", href: "https://fonts.googleapis.com" }),
|
|
61
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
62
|
-
"link",
|
|
63
|
-
{
|
|
64
|
-
rel: "preconnect",
|
|
65
|
-
href: "https://fonts.gstatic.com",
|
|
66
|
-
crossOrigin: "anonymous"
|
|
67
|
-
}
|
|
68
|
-
),
|
|
69
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
70
|
-
"link",
|
|
71
|
-
{
|
|
72
|
-
rel: "stylesheet",
|
|
73
|
-
href: "https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap"
|
|
74
|
-
}
|
|
75
|
-
),
|
|
76
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "clco-sdk-root", children: [
|
|
77
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { dangerouslySetInnerHTML: { __html: sdkStyles } }),
|
|
78
|
-
children
|
|
79
|
-
] })
|
|
80
|
-
] });
|
|
81
|
-
}
|
|
82
|
-
|
|
83
80
|
// src/shared/utils.ts
|
|
84
81
|
async function sha256(data) {
|
|
85
82
|
const bytes = typeof data === "string" ? new TextEncoder().encode(data) : data;
|
|
@@ -175,6 +172,9 @@ var userAgent = () => ({ userAgent: true });
|
|
|
175
172
|
var idempotencyKey = () => ({
|
|
176
173
|
idempotencyKey: true
|
|
177
174
|
});
|
|
175
|
+
var clientCredentials = (credentials) => ({
|
|
176
|
+
clientCredentials: credentials
|
|
177
|
+
});
|
|
178
178
|
var retryAttempt = (attempt) => ({
|
|
179
179
|
retryAttempt: attempt
|
|
180
180
|
});
|
|
@@ -186,6 +186,7 @@ var needUserAgent = (attrs) => attrs?.userAgent === true;
|
|
|
186
186
|
var isIdempotent = (attrs) => attrs?.idempotencyKey === true;
|
|
187
187
|
var getRetryAttempt = (attrs) => attrs?.retryAttempt ?? 0;
|
|
188
188
|
var wasRenewAttempted = (attrs) => attrs?.renewAttempted === true;
|
|
189
|
+
var getClientCredentials = (attrs) => attrs?.clientCredentials;
|
|
189
190
|
var Attributes = {
|
|
190
191
|
empty,
|
|
191
192
|
concat,
|
|
@@ -199,7 +200,9 @@ var Attributes = {
|
|
|
199
200
|
retryAttempt,
|
|
200
201
|
getRetryAttempt,
|
|
201
202
|
renewAttempted,
|
|
202
|
-
wasRenewAttempted
|
|
203
|
+
wasRenewAttempted,
|
|
204
|
+
clientCredentials,
|
|
205
|
+
getClientCredentials
|
|
203
206
|
};
|
|
204
207
|
|
|
205
208
|
// src/client/core/api/middleware/user-agent.ts
|
|
@@ -399,7 +402,13 @@ function attachSessionMiddleware(fetchAccessToken) {
|
|
|
399
402
|
if (!Attributes.isProtected(request.attributes)) {
|
|
400
403
|
return request;
|
|
401
404
|
}
|
|
402
|
-
|
|
405
|
+
let accessToken = await fetchAccessToken(false);
|
|
406
|
+
if (!accessToken) {
|
|
407
|
+
const clientCreds = Attributes.getClientCredentials(request.attributes);
|
|
408
|
+
if (clientCreds) {
|
|
409
|
+
accessToken = clientCreds;
|
|
410
|
+
}
|
|
411
|
+
}
|
|
403
412
|
if (accessToken === null) {
|
|
404
413
|
return request;
|
|
405
414
|
}
|
|
@@ -528,76 +537,857 @@ var ApiClient = class {
|
|
|
528
537
|
}
|
|
529
538
|
};
|
|
530
539
|
|
|
531
|
-
// src/
|
|
532
|
-
var
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
540
|
+
// src/client/core/blockchain/wallet-error.ts
|
|
541
|
+
var import_viem = require("viem");
|
|
542
|
+
function classifyWalletError(error, ctx) {
|
|
543
|
+
if (error instanceof import_viem.UserRejectedRequestError) {
|
|
544
|
+
return { type: "user_rejected" };
|
|
545
|
+
}
|
|
546
|
+
if (error instanceof import_viem.InsufficientFundsError) {
|
|
547
|
+
return { type: "insufficient_funds" };
|
|
548
|
+
}
|
|
549
|
+
if (error instanceof import_viem.ContractFunctionRevertedError) {
|
|
550
|
+
return { type: "contract_reverted", reason: error.reason ?? error.message };
|
|
551
|
+
}
|
|
552
|
+
if (error instanceof import_viem.WaitForTransactionReceiptTimeoutError && ctx?.hash) {
|
|
553
|
+
return { type: "timeout", hash: ctx.hash };
|
|
554
|
+
}
|
|
555
|
+
return { type: "unknown", cause: error };
|
|
546
556
|
}
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
557
|
+
|
|
558
|
+
// src/shared/core/blockchain/abis/erc20.ts
|
|
559
|
+
var ERC20_ABI = [
|
|
560
|
+
{
|
|
561
|
+
type: "function",
|
|
562
|
+
name: "allowance",
|
|
563
|
+
inputs: [
|
|
564
|
+
{ name: "owner", type: "address" },
|
|
565
|
+
{ name: "spender", type: "address" }
|
|
566
|
+
],
|
|
567
|
+
outputs: [{ name: "", type: "uint256" }],
|
|
568
|
+
stateMutability: "view"
|
|
569
|
+
},
|
|
570
|
+
{
|
|
571
|
+
type: "function",
|
|
572
|
+
name: "approve",
|
|
573
|
+
inputs: [
|
|
574
|
+
{ name: "spender", type: "address" },
|
|
575
|
+
{ name: "amount", type: "uint256" }
|
|
576
|
+
],
|
|
577
|
+
outputs: [{ name: "", type: "bool" }],
|
|
578
|
+
stateMutability: "nonpayable"
|
|
579
|
+
},
|
|
580
|
+
{
|
|
581
|
+
type: "function",
|
|
582
|
+
name: "balanceOf",
|
|
583
|
+
inputs: [{ name: "account", type: "address" }],
|
|
584
|
+
outputs: [{ name: "", type: "uint256" }],
|
|
585
|
+
stateMutability: "view"
|
|
586
|
+
},
|
|
587
|
+
{
|
|
588
|
+
type: "function",
|
|
589
|
+
name: "decimals",
|
|
590
|
+
inputs: [],
|
|
591
|
+
outputs: [{ name: "", type: "uint8" }],
|
|
592
|
+
stateMutability: "view"
|
|
593
|
+
},
|
|
594
|
+
{
|
|
595
|
+
type: "function",
|
|
596
|
+
name: "name",
|
|
597
|
+
inputs: [],
|
|
598
|
+
outputs: [{ name: "", type: "string" }],
|
|
599
|
+
stateMutability: "view"
|
|
600
|
+
},
|
|
601
|
+
{
|
|
602
|
+
type: "function",
|
|
603
|
+
name: "symbol",
|
|
604
|
+
inputs: [],
|
|
605
|
+
outputs: [{ name: "", type: "string" }],
|
|
606
|
+
stateMutability: "view"
|
|
607
|
+
},
|
|
608
|
+
{
|
|
609
|
+
type: "function",
|
|
610
|
+
name: "totalSupply",
|
|
611
|
+
inputs: [],
|
|
612
|
+
outputs: [{ name: "", type: "uint256" }],
|
|
613
|
+
stateMutability: "view"
|
|
614
|
+
},
|
|
615
|
+
{
|
|
616
|
+
type: "function",
|
|
617
|
+
name: "transfer",
|
|
618
|
+
inputs: [
|
|
619
|
+
{ name: "recipient", type: "address" },
|
|
620
|
+
{ name: "amount", type: "uint256" }
|
|
621
|
+
],
|
|
622
|
+
outputs: [{ name: "", type: "bool" }],
|
|
623
|
+
stateMutability: "nonpayable"
|
|
624
|
+
},
|
|
625
|
+
{
|
|
626
|
+
type: "function",
|
|
627
|
+
name: "transferFrom",
|
|
628
|
+
inputs: [
|
|
629
|
+
{ name: "sender", type: "address" },
|
|
630
|
+
{ name: "recipient", type: "address" },
|
|
631
|
+
{ name: "amount", type: "uint256" }
|
|
632
|
+
],
|
|
633
|
+
outputs: [{ name: "", type: "bool" }],
|
|
634
|
+
stateMutability: "nonpayable"
|
|
635
|
+
},
|
|
636
|
+
{
|
|
637
|
+
type: "event",
|
|
638
|
+
name: "Approval",
|
|
639
|
+
inputs: [
|
|
640
|
+
{ name: "owner", type: "address", indexed: true },
|
|
641
|
+
{ name: "spender", type: "address", indexed: true },
|
|
642
|
+
{ name: "value", type: "uint256", indexed: false }
|
|
643
|
+
],
|
|
644
|
+
anonymous: false
|
|
645
|
+
},
|
|
646
|
+
{
|
|
647
|
+
type: "event",
|
|
648
|
+
name: "Transfer",
|
|
649
|
+
inputs: [
|
|
650
|
+
{ name: "from", type: "address", indexed: true },
|
|
651
|
+
{ name: "to", type: "address", indexed: true },
|
|
652
|
+
{ name: "value", type: "uint256", indexed: false }
|
|
653
|
+
],
|
|
654
|
+
anonymous: false
|
|
655
|
+
}
|
|
656
|
+
];
|
|
657
|
+
|
|
658
|
+
// src/shared/core/blockchain/abis/superstate-swap.ts
|
|
659
|
+
var SUPERSTATE_SWAP_ABI = [
|
|
660
|
+
{
|
|
661
|
+
type: "function",
|
|
662
|
+
name: "authorized",
|
|
663
|
+
inputs: [{ name: "user", type: "address", internalType: "address" }],
|
|
664
|
+
outputs: [{ name: "", type: "bool", internalType: "bool" }],
|
|
665
|
+
stateMutability: "view"
|
|
666
|
+
},
|
|
667
|
+
{
|
|
668
|
+
type: "function",
|
|
669
|
+
name: "stopped",
|
|
670
|
+
inputs: [],
|
|
671
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
672
|
+
stateMutability: "view"
|
|
673
|
+
},
|
|
674
|
+
{
|
|
675
|
+
type: "function",
|
|
676
|
+
name: "SWAP_LEVEL",
|
|
677
|
+
inputs: [],
|
|
678
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
679
|
+
stateMutability: "view"
|
|
680
|
+
},
|
|
681
|
+
{
|
|
682
|
+
type: "function",
|
|
683
|
+
name: "preview",
|
|
684
|
+
inputs: [
|
|
685
|
+
{ name: "token", type: "address", internalType: "address" },
|
|
686
|
+
{ name: "amount", type: "uint256", internalType: "uint256" }
|
|
687
|
+
],
|
|
688
|
+
outputs: [
|
|
689
|
+
{
|
|
690
|
+
name: "",
|
|
691
|
+
type: "tuple",
|
|
692
|
+
internalType: "struct Preview",
|
|
693
|
+
components: [
|
|
694
|
+
{ name: "input", type: "uint256", internalType: "uint256" },
|
|
695
|
+
{ name: "fee", type: "uint256", internalType: "uint256" },
|
|
696
|
+
{ name: "output", type: "uint256", internalType: "uint256" }
|
|
697
|
+
]
|
|
698
|
+
}
|
|
699
|
+
],
|
|
700
|
+
stateMutability: "view"
|
|
701
|
+
},
|
|
702
|
+
{
|
|
703
|
+
type: "function",
|
|
704
|
+
name: "swap",
|
|
705
|
+
inputs: [
|
|
706
|
+
{ name: "token", type: "address", internalType: "address" },
|
|
707
|
+
{ name: "amount", type: "uint256", internalType: "uint256" },
|
|
708
|
+
{ name: "slip", type: "uint256", internalType: "uint256" }
|
|
709
|
+
],
|
|
710
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
711
|
+
stateMutability: "nonpayable"
|
|
712
|
+
},
|
|
713
|
+
{
|
|
714
|
+
type: "function",
|
|
715
|
+
name: "tokenBalance",
|
|
716
|
+
inputs: [{ name: "token", type: "address", internalType: "address" }],
|
|
717
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
718
|
+
stateMutability: "view"
|
|
719
|
+
},
|
|
720
|
+
{
|
|
721
|
+
type: "function",
|
|
722
|
+
name: "outputToken",
|
|
723
|
+
inputs: [],
|
|
724
|
+
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
725
|
+
stateMutability: "view"
|
|
726
|
+
},
|
|
727
|
+
{
|
|
728
|
+
type: "function",
|
|
729
|
+
name: "outputTokenBalance",
|
|
730
|
+
inputs: [],
|
|
731
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
732
|
+
stateMutability: "view"
|
|
733
|
+
},
|
|
734
|
+
{
|
|
735
|
+
type: "function",
|
|
736
|
+
name: "totals",
|
|
737
|
+
inputs: [{ name: "token", type: "address", internalType: "address" }],
|
|
738
|
+
outputs: [
|
|
739
|
+
{
|
|
740
|
+
name: "",
|
|
741
|
+
type: "tuple",
|
|
742
|
+
internalType: "struct SwapTotal",
|
|
743
|
+
components: [
|
|
744
|
+
{ name: "inputSum", type: "uint256", internalType: "uint256" },
|
|
745
|
+
{ name: "feeSum", type: "uint256", internalType: "uint256" },
|
|
746
|
+
{ name: "outputSum", type: "uint256", internalType: "uint256" },
|
|
747
|
+
{ name: "count", type: "uint256", internalType: "uint256" }
|
|
748
|
+
]
|
|
749
|
+
}
|
|
750
|
+
],
|
|
751
|
+
stateMutability: "view"
|
|
752
|
+
},
|
|
753
|
+
{
|
|
754
|
+
type: "function",
|
|
755
|
+
name: "totals",
|
|
756
|
+
inputs: [
|
|
757
|
+
{ name: "user", type: "address", internalType: "address" },
|
|
758
|
+
{ name: "token", type: "address", internalType: "address" }
|
|
759
|
+
],
|
|
760
|
+
outputs: [
|
|
761
|
+
{
|
|
762
|
+
name: "",
|
|
763
|
+
type: "tuple",
|
|
764
|
+
internalType: "struct SwapTotal",
|
|
765
|
+
components: [
|
|
766
|
+
{ name: "inputSum", type: "uint256", internalType: "uint256" },
|
|
767
|
+
{ name: "feeSum", type: "uint256", internalType: "uint256" },
|
|
768
|
+
{ name: "outputSum", type: "uint256", internalType: "uint256" },
|
|
769
|
+
{ name: "count", type: "uint256", internalType: "uint256" }
|
|
770
|
+
]
|
|
771
|
+
}
|
|
772
|
+
],
|
|
773
|
+
stateMutability: "view"
|
|
774
|
+
},
|
|
775
|
+
{
|
|
776
|
+
type: "function",
|
|
777
|
+
name: "transfer",
|
|
778
|
+
inputs: [
|
|
779
|
+
{ name: "to", type: "address", internalType: "address" },
|
|
780
|
+
{ name: "amount", type: "uint256", internalType: "uint256" }
|
|
781
|
+
],
|
|
782
|
+
outputs: [{ name: "", type: "bool", internalType: "bool" }],
|
|
783
|
+
stateMutability: "nonpayable"
|
|
784
|
+
},
|
|
785
|
+
{
|
|
786
|
+
type: "function",
|
|
787
|
+
name: "transfer",
|
|
788
|
+
inputs: [
|
|
789
|
+
{ name: "to", type: "address", internalType: "address" },
|
|
790
|
+
{ name: "token", type: "address", internalType: "address" },
|
|
791
|
+
{ name: "amount", type: "uint256", internalType: "uint256" }
|
|
792
|
+
],
|
|
793
|
+
outputs: [{ name: "", type: "bool", internalType: "bool" }],
|
|
794
|
+
stateMutability: "nonpayable"
|
|
795
|
+
},
|
|
796
|
+
{
|
|
797
|
+
type: "function",
|
|
798
|
+
name: "setBps",
|
|
799
|
+
inputs: [{ name: "points", type: "uint256", internalType: "uint256" }],
|
|
800
|
+
outputs: [{ name: "", type: "bool", internalType: "bool" }],
|
|
801
|
+
stateMutability: "nonpayable"
|
|
802
|
+
},
|
|
803
|
+
{
|
|
804
|
+
type: "event",
|
|
805
|
+
name: "Swapped",
|
|
806
|
+
inputs: [
|
|
807
|
+
{ name: "user", type: "address", indexed: true, internalType: "address" },
|
|
808
|
+
{
|
|
809
|
+
name: "inputToken",
|
|
810
|
+
type: "address",
|
|
811
|
+
indexed: true,
|
|
812
|
+
internalType: "address"
|
|
813
|
+
},
|
|
814
|
+
{
|
|
815
|
+
name: "outputToken",
|
|
816
|
+
type: "address",
|
|
817
|
+
indexed: true,
|
|
818
|
+
internalType: "address"
|
|
819
|
+
},
|
|
820
|
+
{
|
|
821
|
+
name: "inputAmount",
|
|
822
|
+
type: "uint256",
|
|
823
|
+
indexed: false,
|
|
824
|
+
internalType: "uint256"
|
|
825
|
+
},
|
|
826
|
+
{
|
|
827
|
+
name: "outputAmount",
|
|
828
|
+
type: "uint256",
|
|
829
|
+
indexed: false,
|
|
830
|
+
internalType: "uint256"
|
|
831
|
+
}
|
|
832
|
+
],
|
|
833
|
+
anonymous: false
|
|
834
|
+
},
|
|
835
|
+
{
|
|
836
|
+
type: "event",
|
|
837
|
+
name: "Transferred",
|
|
838
|
+
inputs: [
|
|
839
|
+
{ name: "to", type: "address", indexed: true, internalType: "address" },
|
|
840
|
+
{
|
|
841
|
+
name: "token",
|
|
842
|
+
type: "address",
|
|
843
|
+
indexed: true,
|
|
844
|
+
internalType: "address"
|
|
845
|
+
},
|
|
846
|
+
{
|
|
847
|
+
name: "amount",
|
|
848
|
+
type: "uint256",
|
|
849
|
+
indexed: false,
|
|
850
|
+
internalType: "uint256"
|
|
851
|
+
}
|
|
852
|
+
],
|
|
853
|
+
anonymous: false
|
|
854
|
+
},
|
|
855
|
+
{
|
|
856
|
+
type: "error",
|
|
857
|
+
name: "InvalidAddress",
|
|
858
|
+
inputs: []
|
|
859
|
+
},
|
|
860
|
+
{
|
|
861
|
+
type: "error",
|
|
862
|
+
name: "InsufficientAmount",
|
|
863
|
+
inputs: []
|
|
864
|
+
},
|
|
865
|
+
{
|
|
866
|
+
type: "error",
|
|
867
|
+
name: "InvalidAmount",
|
|
868
|
+
inputs: []
|
|
869
|
+
},
|
|
870
|
+
{
|
|
871
|
+
type: "error",
|
|
872
|
+
name: "SwapFailed",
|
|
873
|
+
inputs: [
|
|
874
|
+
{ name: "user", type: "address", internalType: "address" },
|
|
875
|
+
{ name: "token", type: "address", internalType: "address" }
|
|
876
|
+
]
|
|
877
|
+
}
|
|
878
|
+
];
|
|
879
|
+
|
|
880
|
+
// src/shared/types/blockchain/core.ts
|
|
881
|
+
var EvmWalletAddress = (value) => value;
|
|
882
|
+
var EvmContractAddress = (value) => value;
|
|
883
|
+
var HexEncodedTransactionData = (value) => value;
|
|
884
|
+
var AssetDecimals = (value) => value;
|
|
885
|
+
var MAX_UINT_256 = 2n ** 256n - 1n;
|
|
886
|
+
var assertUint256 = (value) => {
|
|
887
|
+
if (value < 0n || value > MAX_UINT_256) {
|
|
888
|
+
throw new Error(`Value out of uint256 bounds: ${value}`);
|
|
889
|
+
}
|
|
890
|
+
return value;
|
|
553
891
|
};
|
|
554
|
-
var
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
892
|
+
var BlockchainAmount = Object.assign(
|
|
893
|
+
(value) => value,
|
|
894
|
+
{
|
|
895
|
+
add: (a, b) => combineAmounts(a, b, (x, y) => x + y),
|
|
896
|
+
sub: (a, b) => combineAmounts(a, b, (x, y) => x - y)
|
|
897
|
+
}
|
|
898
|
+
);
|
|
899
|
+
function combineAmounts(a, b, op) {
|
|
900
|
+
if (a.decimals !== b.decimals) {
|
|
901
|
+
throw new Error(
|
|
902
|
+
`Cannot combine BlockchainAmounts with different decimals: ${a.decimals} vs ${b.decimals}`
|
|
903
|
+
);
|
|
904
|
+
}
|
|
905
|
+
const raw = op(a.raw, b.raw);
|
|
906
|
+
if (raw < 0n || raw > MAX_UINT_256) {
|
|
907
|
+
throw new Error(`BlockchainAmount out of uint256 bounds: ${raw}`);
|
|
908
|
+
}
|
|
909
|
+
return BlockchainAmount({ raw, decimals: a.decimals });
|
|
910
|
+
}
|
|
911
|
+
var AssetSymbol = (value) => value;
|
|
912
|
+
var StablecoinSymbol = (value) => value;
|
|
913
|
+
var Bps = (value) => value;
|
|
914
|
+
|
|
915
|
+
// src/shared/core/blockchain/bps.ts
|
|
916
|
+
var BPS_DENOM = Bps(10000n);
|
|
917
|
+
function applyBps(amount, bps) {
|
|
918
|
+
return assertUint256(amount * bps / BPS_DENOM);
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
// src/shared/core/blockchain/swap/math.ts
|
|
922
|
+
function computePrice({
|
|
923
|
+
inputTokenAmount,
|
|
924
|
+
outputTokenAmount
|
|
925
|
+
}) {
|
|
926
|
+
if (outputTokenAmount.raw === 0n) return null;
|
|
927
|
+
const scale = 10n ** BigInt(outputTokenAmount.decimals);
|
|
928
|
+
const raw = assertUint256(
|
|
929
|
+
inputTokenAmount.raw * scale / outputTokenAmount.raw
|
|
930
|
+
);
|
|
931
|
+
return BlockchainAmount({ raw, decimals: inputTokenAmount.decimals });
|
|
932
|
+
}
|
|
933
|
+
function computeSlip(amount, slippage) {
|
|
934
|
+
const retained = Bps(assertUint256(BPS_DENOM - slippage));
|
|
935
|
+
const slipRaw = applyBps(amount.raw, retained);
|
|
936
|
+
return BlockchainAmount({ raw: slipRaw, decimals: amount.decimals });
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
// src/shared/core/blockchain/swap/status.ts
|
|
940
|
+
function isStopped(status) {
|
|
941
|
+
return (status.stopped & status.swapLevel) !== 0n;
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
// src/shared/core/blockchain/swap/swapped-event.ts
|
|
945
|
+
var import_viem2 = require("viem");
|
|
946
|
+
function decodeSwappedOutputAmount(receipt, outputDecimals) {
|
|
947
|
+
try {
|
|
948
|
+
const [swapped] = (0, import_viem2.parseEventLogs)({
|
|
949
|
+
abi: SUPERSTATE_SWAP_ABI,
|
|
950
|
+
eventName: "Swapped",
|
|
951
|
+
logs: receipt.logs
|
|
952
|
+
});
|
|
953
|
+
if (!swapped) return null;
|
|
954
|
+
const raw = swapped.args.outputAmount;
|
|
955
|
+
if (raw < 0n || raw > MAX_UINT_256) return null;
|
|
956
|
+
return BlockchainAmount({ raw, decimals: outputDecimals });
|
|
957
|
+
} catch {
|
|
958
|
+
return null;
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
// src/client/core/blockchain/swap-flows.ts
|
|
963
|
+
async function executeSwap(params) {
|
|
964
|
+
const {
|
|
965
|
+
swap,
|
|
966
|
+
wallet,
|
|
967
|
+
contractAddress,
|
|
968
|
+
chain,
|
|
969
|
+
inputTokenAddress,
|
|
970
|
+
quote,
|
|
971
|
+
slippageBps,
|
|
972
|
+
onProgress
|
|
973
|
+
} = params;
|
|
974
|
+
const emit = (phase) => onProgress?.(phase);
|
|
975
|
+
const inputAmount = BlockchainAmount.add(
|
|
976
|
+
quote.inputTokenAmount,
|
|
977
|
+
quote.fee
|
|
978
|
+
).raw;
|
|
979
|
+
const minOut = computeSlip(quote.outputTokenAmount, slippageBps).raw;
|
|
980
|
+
emit("checking-status");
|
|
981
|
+
let status;
|
|
982
|
+
try {
|
|
983
|
+
status = await swap.getStatus({ contractAddress, chain });
|
|
984
|
+
} catch {
|
|
985
|
+
return { type: "error", error: { step: "status-check" } };
|
|
986
|
+
}
|
|
987
|
+
if (isStopped(status)) {
|
|
988
|
+
return { type: "error", error: { step: "swap-stopped" } };
|
|
989
|
+
}
|
|
990
|
+
emit("checking-allowance");
|
|
991
|
+
let allowance;
|
|
992
|
+
try {
|
|
993
|
+
allowance = await swap.getTokenAllowance({
|
|
994
|
+
tokenAddress: inputTokenAddress,
|
|
995
|
+
owner: wallet.address,
|
|
996
|
+
spender: contractAddress,
|
|
997
|
+
chain
|
|
998
|
+
});
|
|
999
|
+
} catch {
|
|
1000
|
+
return { type: "error", error: { step: "allowance-check" } };
|
|
1001
|
+
}
|
|
1002
|
+
if (allowance.allowance < inputAmount) {
|
|
1003
|
+
if (allowance.allowance > 0n) {
|
|
1004
|
+
const reset = await submitApproval({
|
|
1005
|
+
wallet,
|
|
1006
|
+
tokenAddress: inputTokenAddress,
|
|
1007
|
+
spender: contractAddress,
|
|
1008
|
+
chain,
|
|
1009
|
+
value: 0n,
|
|
1010
|
+
pending: "resetting-allowance",
|
|
1011
|
+
confirming: "confirming-allowance-reset",
|
|
1012
|
+
emit
|
|
1013
|
+
});
|
|
1014
|
+
if (reset.type === "error") return { type: "error", error: reset.error };
|
|
559
1015
|
}
|
|
560
|
-
|
|
561
|
-
|
|
1016
|
+
const approve = await submitApproval({
|
|
1017
|
+
wallet,
|
|
1018
|
+
tokenAddress: inputTokenAddress,
|
|
1019
|
+
spender: contractAddress,
|
|
1020
|
+
chain,
|
|
1021
|
+
value: inputAmount,
|
|
1022
|
+
pending: "approving",
|
|
1023
|
+
confirming: "confirming-approval",
|
|
1024
|
+
emit
|
|
1025
|
+
});
|
|
1026
|
+
if (approve.type === "error")
|
|
1027
|
+
return { type: "error", error: approve.error };
|
|
1028
|
+
}
|
|
1029
|
+
emit("swapping");
|
|
1030
|
+
let swapTxHash;
|
|
1031
|
+
try {
|
|
1032
|
+
swapTxHash = await wallet.writeContract({
|
|
1033
|
+
abi: SUPERSTATE_SWAP_ABI,
|
|
1034
|
+
address: contractAddress,
|
|
1035
|
+
functionName: "swap",
|
|
1036
|
+
args: [inputTokenAddress, inputAmount, minOut],
|
|
1037
|
+
chain
|
|
1038
|
+
});
|
|
1039
|
+
} catch (error) {
|
|
1040
|
+
return {
|
|
1041
|
+
type: "error",
|
|
1042
|
+
error: { step: "swap", cause: classifyWalletError(error) }
|
|
1043
|
+
};
|
|
1044
|
+
}
|
|
1045
|
+
emit("confirming-swap");
|
|
1046
|
+
let receipt;
|
|
1047
|
+
try {
|
|
1048
|
+
receipt = await wallet.awaitTx(swapTxHash, chain);
|
|
1049
|
+
} catch (error) {
|
|
1050
|
+
return {
|
|
1051
|
+
type: "error",
|
|
1052
|
+
error: {
|
|
1053
|
+
step: "swap",
|
|
1054
|
+
cause: classifyWalletError(error, { hash: swapTxHash })
|
|
1055
|
+
}
|
|
1056
|
+
};
|
|
1057
|
+
}
|
|
1058
|
+
if (receipt.status !== "success") {
|
|
1059
|
+
return { type: "error", error: { step: "swap-reverted" } };
|
|
1060
|
+
}
|
|
1061
|
+
const outputAmount = decodeSwappedOutputAmount(receipt, quote.outputTokenAmount.decimals) ?? quote.outputTokenAmount;
|
|
1062
|
+
const finalQuote = { ...quote, outputTokenAmount: outputAmount };
|
|
1063
|
+
return {
|
|
1064
|
+
type: "success",
|
|
1065
|
+
swapTxHash,
|
|
1066
|
+
inputAmount: finalQuote.inputTokenAmount,
|
|
1067
|
+
fee: finalQuote.fee,
|
|
1068
|
+
outputAmount,
|
|
1069
|
+
pricePerShare: computePrice(finalQuote),
|
|
1070
|
+
recipientAddress: wallet.address
|
|
1071
|
+
};
|
|
1072
|
+
}
|
|
1073
|
+
async function submitApproval(args) {
|
|
1074
|
+
const {
|
|
1075
|
+
wallet,
|
|
1076
|
+
tokenAddress,
|
|
1077
|
+
spender,
|
|
1078
|
+
chain,
|
|
1079
|
+
value,
|
|
1080
|
+
pending,
|
|
1081
|
+
confirming,
|
|
1082
|
+
emit
|
|
1083
|
+
} = args;
|
|
1084
|
+
emit(pending);
|
|
1085
|
+
let hash;
|
|
1086
|
+
try {
|
|
1087
|
+
hash = await wallet.writeContract({
|
|
1088
|
+
abi: ERC20_ABI,
|
|
1089
|
+
address: tokenAddress,
|
|
1090
|
+
functionName: "approve",
|
|
1091
|
+
args: [spender, value],
|
|
1092
|
+
chain
|
|
1093
|
+
});
|
|
1094
|
+
} catch (error) {
|
|
1095
|
+
return {
|
|
1096
|
+
type: "error",
|
|
1097
|
+
error: { step: "approval", cause: classifyWalletError(error) }
|
|
1098
|
+
};
|
|
1099
|
+
}
|
|
1100
|
+
emit(confirming);
|
|
1101
|
+
let receipt;
|
|
1102
|
+
try {
|
|
1103
|
+
receipt = await wallet.awaitTx(hash, chain);
|
|
1104
|
+
} catch (error) {
|
|
1105
|
+
return {
|
|
1106
|
+
type: "error",
|
|
1107
|
+
error: { step: "approval", cause: classifyWalletError(error, { hash }) }
|
|
1108
|
+
};
|
|
1109
|
+
}
|
|
1110
|
+
if (receipt.status !== "success") {
|
|
1111
|
+
return { type: "error", error: { step: "approval-reverted" } };
|
|
1112
|
+
}
|
|
1113
|
+
return { type: "ok" };
|
|
1114
|
+
}
|
|
1115
|
+
async function authorizeWallet(params) {
|
|
1116
|
+
const { swap, wallet, offerId, contractAddress, chain, onProgress } = params;
|
|
1117
|
+
const emit = (phase) => onProgress?.(phase);
|
|
1118
|
+
const walletAddress = wallet.address;
|
|
1119
|
+
emit("checking-authorization");
|
|
1120
|
+
let auth;
|
|
1121
|
+
try {
|
|
1122
|
+
auth = await swap.getAuthorization({
|
|
1123
|
+
walletAddress,
|
|
1124
|
+
contractAddress,
|
|
1125
|
+
chain
|
|
1126
|
+
});
|
|
1127
|
+
} catch {
|
|
1128
|
+
return { type: "error", error: { step: "authorization-check" } };
|
|
1129
|
+
}
|
|
1130
|
+
if (auth.authorized) return { type: "success" };
|
|
1131
|
+
emit("requesting-challenge");
|
|
1132
|
+
let challenge;
|
|
1133
|
+
try {
|
|
1134
|
+
challenge = await swap.requestWalletOwnershipChallenge({
|
|
1135
|
+
walletAddress,
|
|
1136
|
+
chain,
|
|
1137
|
+
challengeType: "plain"
|
|
1138
|
+
});
|
|
1139
|
+
} catch {
|
|
1140
|
+
return { type: "error", error: { step: "challenge-request" } };
|
|
1141
|
+
}
|
|
1142
|
+
emit("signing-message");
|
|
1143
|
+
let signature;
|
|
1144
|
+
try {
|
|
1145
|
+
signature = await wallet.signMessage(challenge.message);
|
|
1146
|
+
} catch (error) {
|
|
1147
|
+
return {
|
|
1148
|
+
type: "error",
|
|
1149
|
+
error: { step: "signing", cause: classifyWalletError(error) }
|
|
1150
|
+
};
|
|
1151
|
+
}
|
|
1152
|
+
emit("submitting-signature");
|
|
1153
|
+
let allow;
|
|
1154
|
+
try {
|
|
1155
|
+
allow = await swap.allowWallet({
|
|
1156
|
+
offerId,
|
|
1157
|
+
walletAddress,
|
|
1158
|
+
chain,
|
|
1159
|
+
signature
|
|
1160
|
+
});
|
|
1161
|
+
} catch {
|
|
1162
|
+
return { type: "error", error: { step: "allow-wallet" } };
|
|
1163
|
+
}
|
|
1164
|
+
if (allow.action === "broadcast_transaction") {
|
|
1165
|
+
emit("broadcasting-transaction");
|
|
1166
|
+
let hash;
|
|
1167
|
+
try {
|
|
1168
|
+
hash = await wallet.broadcastRawTx({
|
|
1169
|
+
to: allow.to,
|
|
1170
|
+
data: allow.data,
|
|
1171
|
+
chain
|
|
1172
|
+
});
|
|
1173
|
+
} catch (error) {
|
|
1174
|
+
return {
|
|
1175
|
+
type: "error",
|
|
1176
|
+
error: { step: "broadcast", cause: classifyWalletError(error) }
|
|
1177
|
+
};
|
|
562
1178
|
}
|
|
563
|
-
|
|
564
|
-
|
|
1179
|
+
emit("awaiting-confirmation");
|
|
1180
|
+
try {
|
|
1181
|
+
await wallet.awaitTx(hash, chain);
|
|
1182
|
+
} catch (error) {
|
|
1183
|
+
return {
|
|
1184
|
+
type: "error",
|
|
1185
|
+
error: {
|
|
1186
|
+
step: "broadcast",
|
|
1187
|
+
cause: classifyWalletError(error, { hash })
|
|
1188
|
+
}
|
|
1189
|
+
};
|
|
565
1190
|
}
|
|
566
|
-
return queryParams;
|
|
567
1191
|
}
|
|
568
|
-
|
|
1192
|
+
emit("verifying-authorization");
|
|
1193
|
+
let reCheck;
|
|
1194
|
+
try {
|
|
1195
|
+
reCheck = await swap.getAuthorization({
|
|
1196
|
+
walletAddress,
|
|
1197
|
+
contractAddress,
|
|
1198
|
+
chain
|
|
1199
|
+
});
|
|
1200
|
+
} catch {
|
|
1201
|
+
return { type: "error", error: { step: "authorization-check" } };
|
|
1202
|
+
}
|
|
1203
|
+
if (!reCheck.authorized) {
|
|
1204
|
+
return { type: "error", error: { step: "not-authorized" } };
|
|
1205
|
+
}
|
|
1206
|
+
return { type: "success" };
|
|
1207
|
+
}
|
|
569
1208
|
|
|
570
|
-
// src/shared/types/
|
|
571
|
-
var
|
|
572
|
-
var OfferSlug = (value) => value;
|
|
573
|
-
var Offer = {
|
|
1209
|
+
// src/shared/types/swap.ts
|
|
1210
|
+
var SwapAuthorization = {
|
|
574
1211
|
fromDto: (dto) => ({
|
|
575
|
-
|
|
576
|
-
slug: OfferSlug(dto.slug),
|
|
577
|
-
tagline: notBlankStringOrNull(dto.tagline),
|
|
578
|
-
bannerUrl: notBlankStringOrNull(dto.banner_url),
|
|
579
|
-
logoUrl: notBlankStringOrNull(dto.logo_url),
|
|
580
|
-
startsAt: new Date(dto.starts_at),
|
|
581
|
-
endsAt: new Date(dto.ends_at)
|
|
1212
|
+
authorized: dto.authorized
|
|
582
1213
|
})
|
|
583
1214
|
};
|
|
584
|
-
|
|
585
|
-
// src/shared/types/asset.ts
|
|
586
|
-
var AssetId = (value) => value;
|
|
587
|
-
var AssetCode = (value) => value;
|
|
588
|
-
var Asset = {
|
|
1215
|
+
var SwapPreview = {
|
|
589
1216
|
fromDto: (dto) => ({
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
fractionalDigits: dto.fractional_digits
|
|
1217
|
+
inputAmount: assertUint256(BigInt(dto.pay_input_amount)),
|
|
1218
|
+
fee: assertUint256(BigInt(dto.fee)),
|
|
1219
|
+
outputAmount: assertUint256(BigInt(dto.receive_output_amount))
|
|
594
1220
|
})
|
|
595
1221
|
};
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
1222
|
+
var SwapStatus = {
|
|
1223
|
+
fromDto: (dto) => ({
|
|
1224
|
+
stopped: assertUint256(BigInt(dto.stopped)),
|
|
1225
|
+
swapLevel: assertUint256(BigInt(dto.swap_level))
|
|
1226
|
+
})
|
|
1227
|
+
};
|
|
1228
|
+
var TokenAllowance = {
|
|
1229
|
+
fromDto: (dto) => ({
|
|
1230
|
+
allowance: assertUint256(BigInt(dto.allowance))
|
|
1231
|
+
})
|
|
1232
|
+
};
|
|
1233
|
+
var TokenBalance = {
|
|
1234
|
+
fromDto: (dto) => ({
|
|
1235
|
+
balance: assertUint256(BigInt(dto.balance))
|
|
1236
|
+
})
|
|
1237
|
+
};
|
|
1238
|
+
var AllowWalletResponse = {
|
|
1239
|
+
fromDto: (dto) => {
|
|
1240
|
+
switch (dto.action) {
|
|
1241
|
+
case "broadcast_transaction":
|
|
1242
|
+
return {
|
|
1243
|
+
action: "broadcast_transaction",
|
|
1244
|
+
to: EvmContractAddress(dto.to),
|
|
1245
|
+
data: HexEncodedTransactionData(dto.data)
|
|
1246
|
+
};
|
|
1247
|
+
case "none":
|
|
1248
|
+
return {
|
|
1249
|
+
action: "none",
|
|
1250
|
+
alreadyAllowed: dto.already_allowed
|
|
1251
|
+
};
|
|
1252
|
+
default: {
|
|
1253
|
+
const _exhaustive = dto;
|
|
1254
|
+
return _exhaustive;
|
|
1255
|
+
}
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1258
|
+
};
|
|
1259
|
+
|
|
1260
|
+
// src/shared/api/frontline/swap.ts
|
|
1261
|
+
async function getSwapAuthorization(api, params) {
|
|
1262
|
+
const dto = await api.send({
|
|
1263
|
+
method: "GET",
|
|
1264
|
+
url: "/v1/wallet/authorized",
|
|
1265
|
+
queryParams: {
|
|
1266
|
+
chain: params.chain,
|
|
1267
|
+
contract_address: params.contractAddress,
|
|
1268
|
+
wallet_address: params.walletAddress
|
|
1269
|
+
},
|
|
1270
|
+
attributes: Attributes.protected()
|
|
1271
|
+
});
|
|
1272
|
+
return SwapAuthorization.fromDto(dto);
|
|
1273
|
+
}
|
|
1274
|
+
async function getSwapOutputToken(api, params) {
|
|
1275
|
+
const dto = await api.send({
|
|
1276
|
+
method: "GET",
|
|
1277
|
+
url: "/v1/swap/output-token",
|
|
1278
|
+
queryParams: {
|
|
1279
|
+
chain: params.chain,
|
|
1280
|
+
contract_address: params.contractAddress
|
|
1281
|
+
},
|
|
1282
|
+
attributes: Attributes.protected()
|
|
1283
|
+
});
|
|
1284
|
+
return toErc20Asset(dto);
|
|
1285
|
+
}
|
|
1286
|
+
async function getSwapPreview(api, params) {
|
|
1287
|
+
const dto = await api.send({
|
|
1288
|
+
method: "GET",
|
|
1289
|
+
url: "/v1/swap/preview",
|
|
1290
|
+
queryParams: {
|
|
1291
|
+
chain: params.chain,
|
|
1292
|
+
contract_address: params.contractAddress,
|
|
1293
|
+
input_token: params.inputToken,
|
|
1294
|
+
amount: params.amount.toString()
|
|
1295
|
+
},
|
|
1296
|
+
attributes: Attributes.protected()
|
|
1297
|
+
});
|
|
1298
|
+
return SwapPreview.fromDto(dto);
|
|
1299
|
+
}
|
|
1300
|
+
async function getSwapStatus(api, params) {
|
|
1301
|
+
const dto = await api.send({
|
|
1302
|
+
method: "GET",
|
|
1303
|
+
url: "/v1/swap/status",
|
|
1304
|
+
queryParams: {
|
|
1305
|
+
chain: params.chain,
|
|
1306
|
+
contract_address: params.contractAddress
|
|
1307
|
+
},
|
|
1308
|
+
attributes: Attributes.protected()
|
|
1309
|
+
});
|
|
1310
|
+
return SwapStatus.fromDto(dto);
|
|
1311
|
+
}
|
|
1312
|
+
async function getTokenAllowance(api, params) {
|
|
1313
|
+
const dto = await api.send({
|
|
1314
|
+
method: "GET",
|
|
1315
|
+
url: "/v1/token/allowance",
|
|
1316
|
+
queryParams: {
|
|
1317
|
+
chain: params.chain,
|
|
1318
|
+
token_address: params.tokenAddress,
|
|
1319
|
+
owner: params.owner,
|
|
1320
|
+
spender: params.spender
|
|
1321
|
+
},
|
|
1322
|
+
attributes: Attributes.protected()
|
|
1323
|
+
});
|
|
1324
|
+
return TokenAllowance.fromDto(dto);
|
|
1325
|
+
}
|
|
1326
|
+
async function getTokenBalance(api, params) {
|
|
1327
|
+
const dto = await api.send({
|
|
1328
|
+
method: "GET",
|
|
1329
|
+
url: "/v1/token/balance",
|
|
1330
|
+
queryParams: {
|
|
1331
|
+
chain: params.chain,
|
|
1332
|
+
token_address: params.tokenAddress,
|
|
1333
|
+
owner: params.owner
|
|
1334
|
+
},
|
|
1335
|
+
attributes: Attributes.protected()
|
|
1336
|
+
});
|
|
1337
|
+
return TokenBalance.fromDto(dto);
|
|
1338
|
+
}
|
|
1339
|
+
async function allowWallet(api, params) {
|
|
1340
|
+
const dto = await api.send({
|
|
1341
|
+
method: "POST",
|
|
1342
|
+
url: `/v1/offers/${encodeURIComponent(params.offerId)}/allow-wallet`,
|
|
1343
|
+
body: {
|
|
1344
|
+
wallet_address: params.walletAddress,
|
|
1345
|
+
chain: params.chain,
|
|
1346
|
+
signature: params.signature
|
|
1347
|
+
},
|
|
1348
|
+
attributes: Attributes.protected()
|
|
1349
|
+
});
|
|
1350
|
+
return AllowWalletResponse.fromDto(dto);
|
|
1351
|
+
}
|
|
1352
|
+
function toErc20Asset(dto) {
|
|
1353
|
+
return {
|
|
1354
|
+
name: dto.name,
|
|
1355
|
+
symbol: AssetSymbol(dto.symbol),
|
|
1356
|
+
decimals: AssetDecimals(dto.decimals)
|
|
1357
|
+
};
|
|
1358
|
+
}
|
|
1359
|
+
|
|
1360
|
+
// src/shared/types/asset.ts
|
|
1361
|
+
var AssetId = (value) => value;
|
|
1362
|
+
var AssetCode = (value) => value;
|
|
1363
|
+
var Asset = {
|
|
1364
|
+
fromDto: (dto) => ({
|
|
1365
|
+
id: AssetId(dto.id),
|
|
1366
|
+
code: AssetCode(dto.code),
|
|
1367
|
+
name: dto.name,
|
|
1368
|
+
fractionalDigits: dto.fractional_digits
|
|
1369
|
+
})
|
|
1370
|
+
};
|
|
1371
|
+
|
|
1372
|
+
// src/shared/types/offer.ts
|
|
1373
|
+
var OfferId = (value) => value;
|
|
1374
|
+
var OfferSlug = (value) => value;
|
|
1375
|
+
var Offer = {
|
|
1376
|
+
fromDto: (dto) => ({
|
|
1377
|
+
id: OfferId(dto.id),
|
|
1378
|
+
slug: OfferSlug(dto.slug),
|
|
1379
|
+
tagline: notBlankStringOrNull(dto.tagline),
|
|
1380
|
+
bannerUrl: notBlankStringOrNull(dto.banner_url),
|
|
1381
|
+
logoUrl: notBlankStringOrNull(dto.logo_url),
|
|
1382
|
+
startsAt: new Date(dto.starts_at),
|
|
1383
|
+
endsAt: new Date(dto.ends_at)
|
|
1384
|
+
})
|
|
1385
|
+
};
|
|
1386
|
+
|
|
1387
|
+
// src/shared/types/offer-detail.ts
|
|
1388
|
+
var OfferOptionId = (value) => value;
|
|
1389
|
+
var OfferOptionSlug = (value) => value;
|
|
1390
|
+
var OfferDetail = {
|
|
601
1391
|
fromDto: (dto) => {
|
|
602
1392
|
if (!Array.isArray(dto.funding_assets)) {
|
|
603
1393
|
throw new Error(`funding_assets must be an array`);
|
|
@@ -676,25 +1466,257 @@ var Milestone = {
|
|
|
676
1466
|
})
|
|
677
1467
|
};
|
|
678
1468
|
|
|
1469
|
+
// src/shared/types/offer-option-address.ts
|
|
1470
|
+
var OfferOptionAddressId = (value) => value;
|
|
1471
|
+
var OfferOptionAddress = {
|
|
1472
|
+
/** Maps the API DTO into the SDK offer-option-address domain model. */
|
|
1473
|
+
fromDto: (dto) => ({
|
|
1474
|
+
id: OfferOptionAddressId(dto.id),
|
|
1475
|
+
offerOptionId: OfferOptionId(dto.offer_option_id),
|
|
1476
|
+
address: EvmWalletAddress(dto.address),
|
|
1477
|
+
protocol: dto.protocol,
|
|
1478
|
+
createdAt: new Date(dto.created_at)
|
|
1479
|
+
})
|
|
1480
|
+
};
|
|
1481
|
+
var ConnectExternalWalletParams = {
|
|
1482
|
+
/** Maps connect-wallet params into the API DTO payload. */
|
|
1483
|
+
toDto: (params) => ({
|
|
1484
|
+
offer_option_id: params.offerOptionId,
|
|
1485
|
+
wallet_address: params.walletAddress,
|
|
1486
|
+
chain: params.chain,
|
|
1487
|
+
signature: params.signature
|
|
1488
|
+
})
|
|
1489
|
+
};
|
|
1490
|
+
|
|
1491
|
+
// src/shared/types/wallet-ownership-challenge.ts
|
|
1492
|
+
var WalletOwnershipChallenge = {
|
|
1493
|
+
/** Maps the API DTO into the SDK wallet-ownership-challenge domain model. */
|
|
1494
|
+
fromDto: (dto) => ({
|
|
1495
|
+
message: dto.message,
|
|
1496
|
+
expiresAt: new Date(dto.expires_at)
|
|
1497
|
+
})
|
|
1498
|
+
};
|
|
1499
|
+
var CreateWalletOwnershipChallengeParams = {
|
|
1500
|
+
/**
|
|
1501
|
+
* Maps challenge-request params into the API DTO payload. The discriminated
|
|
1502
|
+
* union guarantees SIWE fields are present exactly when `challengeType` is
|
|
1503
|
+
* `siwe`, so the mapping narrows on the discriminant.
|
|
1504
|
+
*/
|
|
1505
|
+
toDto: (params) => {
|
|
1506
|
+
switch (params.challengeType) {
|
|
1507
|
+
case "plain":
|
|
1508
|
+
return {
|
|
1509
|
+
wallet_address: params.walletAddress,
|
|
1510
|
+
chain: params.chain,
|
|
1511
|
+
challenge_type: "plain"
|
|
1512
|
+
};
|
|
1513
|
+
case "siwe":
|
|
1514
|
+
return {
|
|
1515
|
+
wallet_address: params.walletAddress,
|
|
1516
|
+
chain: params.chain,
|
|
1517
|
+
challenge_type: "siwe",
|
|
1518
|
+
domain: params.domain,
|
|
1519
|
+
uri: params.uri,
|
|
1520
|
+
statement: params.statement
|
|
1521
|
+
};
|
|
1522
|
+
default: {
|
|
1523
|
+
const _exhaustive = params;
|
|
1524
|
+
return _exhaustive;
|
|
1525
|
+
}
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1528
|
+
};
|
|
1529
|
+
|
|
1530
|
+
// src/shared/api/frontline/wallet-connect.ts
|
|
1531
|
+
async function createWalletOwnershipChallenge(api, params) {
|
|
1532
|
+
const dto = await api.send({
|
|
1533
|
+
method: "POST",
|
|
1534
|
+
url: "/v1/wallet-ownership",
|
|
1535
|
+
body: CreateWalletOwnershipChallengeParams.toDto(params),
|
|
1536
|
+
attributes: Attributes.protected()
|
|
1537
|
+
});
|
|
1538
|
+
return WalletOwnershipChallenge.fromDto(dto);
|
|
1539
|
+
}
|
|
1540
|
+
async function connectExternalWallet(api, offerId, params) {
|
|
1541
|
+
const dto = await api.send({
|
|
1542
|
+
method: "POST",
|
|
1543
|
+
url: `/v1/offers/${offerId}/addresses`,
|
|
1544
|
+
body: ConnectExternalWalletParams.toDto(params),
|
|
1545
|
+
attributes: Attributes.protected()
|
|
1546
|
+
});
|
|
1547
|
+
return OfferOptionAddress.fromDto(dto);
|
|
1548
|
+
}
|
|
1549
|
+
async function listOptionAddresses(api, offerId, offerOptionId) {
|
|
1550
|
+
const { data } = await api.send({
|
|
1551
|
+
method: "GET",
|
|
1552
|
+
url: `/v1/offers/${offerId}/addresses`,
|
|
1553
|
+
queryParams: { offer_option_id: offerOptionId },
|
|
1554
|
+
attributes: Attributes.protected()
|
|
1555
|
+
});
|
|
1556
|
+
return data.map(OfferOptionAddress.fromDto);
|
|
1557
|
+
}
|
|
1558
|
+
async function removeOptionAddress(api, offerId, addressId) {
|
|
1559
|
+
const dto = await api.send({
|
|
1560
|
+
method: "DELETE",
|
|
1561
|
+
url: `/v1/offers/${offerId}/addresses/${addressId}`,
|
|
1562
|
+
attributes: Attributes.protected()
|
|
1563
|
+
});
|
|
1564
|
+
return OfferOptionAddress.fromDto(dto);
|
|
1565
|
+
}
|
|
1566
|
+
|
|
1567
|
+
// src/shared/core/swap-namespace.ts
|
|
1568
|
+
var SwapNamespaceImpl = class {
|
|
1569
|
+
constructor(ctx) {
|
|
1570
|
+
this.ctx = ctx;
|
|
1571
|
+
}
|
|
1572
|
+
async getAuthorization(params) {
|
|
1573
|
+
await this.ctx.ensureUserAuthenticated();
|
|
1574
|
+
return getSwapAuthorization(this.ctx.api, params);
|
|
1575
|
+
}
|
|
1576
|
+
async getPreview(params) {
|
|
1577
|
+
await this.ctx.ensureUserAuthenticated();
|
|
1578
|
+
return getSwapPreview(this.ctx.api, params);
|
|
1579
|
+
}
|
|
1580
|
+
async getStatus(params) {
|
|
1581
|
+
await this.ctx.ensureUserAuthenticated();
|
|
1582
|
+
return getSwapStatus(this.ctx.api, params);
|
|
1583
|
+
}
|
|
1584
|
+
async getTokenAllowance(params) {
|
|
1585
|
+
await this.ctx.ensureUserAuthenticated();
|
|
1586
|
+
return getTokenAllowance(this.ctx.api, params);
|
|
1587
|
+
}
|
|
1588
|
+
async getTokenBalance(params) {
|
|
1589
|
+
await this.ctx.ensureUserAuthenticated();
|
|
1590
|
+
return getTokenBalance(this.ctx.api, params);
|
|
1591
|
+
}
|
|
1592
|
+
async getOutputToken(params) {
|
|
1593
|
+
await this.ctx.ensureUserAuthenticated();
|
|
1594
|
+
return getSwapOutputToken(this.ctx.api, params);
|
|
1595
|
+
}
|
|
1596
|
+
async requestWalletOwnershipChallenge(params) {
|
|
1597
|
+
await this.ctx.ensureUserAuthenticated();
|
|
1598
|
+
return createWalletOwnershipChallenge(this.ctx.api, params);
|
|
1599
|
+
}
|
|
1600
|
+
async allowWallet(params) {
|
|
1601
|
+
await this.ctx.ensureUserAuthenticated();
|
|
1602
|
+
return allowWallet(this.ctx.api, params);
|
|
1603
|
+
}
|
|
1604
|
+
};
|
|
1605
|
+
|
|
1606
|
+
// src/client/core/client-swap-namespace.ts
|
|
1607
|
+
var ClientSwapNamespaceImpl = class extends SwapNamespaceImpl {
|
|
1608
|
+
executeSwap(params) {
|
|
1609
|
+
return executeSwap({ ...params, swap: this });
|
|
1610
|
+
}
|
|
1611
|
+
authorizeWallet(params) {
|
|
1612
|
+
return authorizeWallet({ ...params, swap: this });
|
|
1613
|
+
}
|
|
1614
|
+
};
|
|
1615
|
+
|
|
1616
|
+
// src/shared/types/document-submission.ts
|
|
1617
|
+
var DocumentSubmission = {
|
|
1618
|
+
fromDto: (dto) => ({
|
|
1619
|
+
status: dto.status,
|
|
1620
|
+
formType: dto.form_type
|
|
1621
|
+
})
|
|
1622
|
+
};
|
|
1623
|
+
|
|
1624
|
+
// src/shared/api/frontline/documents.ts
|
|
1625
|
+
async function submitDocument(api, documentType, fields) {
|
|
1626
|
+
const dto = await api.send({
|
|
1627
|
+
method: "POST",
|
|
1628
|
+
url: `/v1/documents/${documentType}/submission`,
|
|
1629
|
+
body: fields,
|
|
1630
|
+
attributes: Attributes.protected()
|
|
1631
|
+
});
|
|
1632
|
+
return DocumentSubmission.fromDto(dto);
|
|
1633
|
+
}
|
|
1634
|
+
|
|
1635
|
+
// src/shared/types/kyc.ts
|
|
1636
|
+
var KycToken = {
|
|
1637
|
+
fromDto: (dto) => ({
|
|
1638
|
+
token: dto.token
|
|
1639
|
+
})
|
|
1640
|
+
};
|
|
1641
|
+
|
|
1642
|
+
// src/shared/api/frontline/kyc.ts
|
|
1643
|
+
async function createKycToken(api, levelName, reset) {
|
|
1644
|
+
const dto = await api.send({
|
|
1645
|
+
method: "POST",
|
|
1646
|
+
url: "/v1/kyc-token",
|
|
1647
|
+
body: {
|
|
1648
|
+
...levelName === void 0 ? {} : { level_name: levelName },
|
|
1649
|
+
...reset === void 0 ? {} : { reset }
|
|
1650
|
+
},
|
|
1651
|
+
attributes: Attributes.protected()
|
|
1652
|
+
});
|
|
1653
|
+
return KycToken.fromDto(dto);
|
|
1654
|
+
}
|
|
1655
|
+
|
|
1656
|
+
// src/shared/api/pagination.ts
|
|
1657
|
+
var Cursor = (value) => value;
|
|
1658
|
+
async function fetchAllPages(fetchPage, baseParams) {
|
|
1659
|
+
const items = [];
|
|
1660
|
+
let cursor = null;
|
|
1661
|
+
do {
|
|
1662
|
+
const params = {
|
|
1663
|
+
...baseParams ?? {},
|
|
1664
|
+
after: cursor ?? void 0
|
|
1665
|
+
};
|
|
1666
|
+
const page = await fetchPage(params);
|
|
1667
|
+
items.push(...page.data);
|
|
1668
|
+
cursor = page.startingAfter;
|
|
1669
|
+
} while (cursor);
|
|
1670
|
+
return items;
|
|
1671
|
+
}
|
|
1672
|
+
var PaginatedResponse = {
|
|
1673
|
+
fromDto: (dto, itemMapper) => ({
|
|
1674
|
+
data: dto.data.map(itemMapper),
|
|
1675
|
+
startingAfter: dto.starting_after ? Cursor(dto.starting_after) : null,
|
|
1676
|
+
startingBefore: dto.starting_before ? Cursor(dto.starting_before) : null
|
|
1677
|
+
})
|
|
1678
|
+
};
|
|
1679
|
+
var PaginationParams = {
|
|
1680
|
+
toQueryParams: (params) => {
|
|
1681
|
+
const queryParams = {};
|
|
1682
|
+
if (params.after) {
|
|
1683
|
+
queryParams.starting_after = params.after;
|
|
1684
|
+
}
|
|
1685
|
+
if (params.before) {
|
|
1686
|
+
queryParams.starting_before = params.before;
|
|
1687
|
+
}
|
|
1688
|
+
if (params.limit) {
|
|
1689
|
+
queryParams.limit = params.limit;
|
|
1690
|
+
}
|
|
1691
|
+
return queryParams;
|
|
1692
|
+
}
|
|
1693
|
+
};
|
|
1694
|
+
|
|
679
1695
|
// src/shared/api/frontline/offers.ts
|
|
680
|
-
async function fetchOffers(api) {
|
|
681
|
-
return fetchAllPages((params) => fetchOffersPage(api, params));
|
|
1696
|
+
async function fetchOffers(api, clientCreds) {
|
|
1697
|
+
return fetchAllPages((params) => fetchOffersPage(api, params, clientCreds));
|
|
682
1698
|
}
|
|
683
|
-
async function fetchOffersPage(api, params) {
|
|
1699
|
+
async function fetchOffersPage(api, params, clientCreds) {
|
|
684
1700
|
const queryParams = PaginationParams.toQueryParams(params);
|
|
685
1701
|
const pageDto = await api.send({
|
|
686
1702
|
method: "GET",
|
|
687
1703
|
url: "/v1/offers",
|
|
688
1704
|
queryParams,
|
|
689
|
-
attributes: Attributes.
|
|
1705
|
+
attributes: Attributes.concat(
|
|
1706
|
+
Attributes.protected(),
|
|
1707
|
+
Attributes.clientCredentials(clientCreds)
|
|
1708
|
+
)
|
|
690
1709
|
});
|
|
691
1710
|
return PaginatedResponse.fromDto(pageDto, Offer.fromDto);
|
|
692
1711
|
}
|
|
693
|
-
async function fetchOfferDetails(api, id) {
|
|
1712
|
+
async function fetchOfferDetails(api, id, clientCreds) {
|
|
694
1713
|
const dto = await api.send({
|
|
695
1714
|
method: "GET",
|
|
696
1715
|
url: `/v1/offers/${id}`,
|
|
697
|
-
attributes: Attributes.
|
|
1716
|
+
attributes: Attributes.concat(
|
|
1717
|
+
Attributes.protected(),
|
|
1718
|
+
Attributes.clientCredentials(clientCreds)
|
|
1719
|
+
)
|
|
698
1720
|
});
|
|
699
1721
|
return OfferDetail.fromDto(dto);
|
|
700
1722
|
}
|
|
@@ -780,6 +1802,44 @@ async function createParticipation(api, params) {
|
|
|
780
1802
|
return Participation.fromDto(dto);
|
|
781
1803
|
}
|
|
782
1804
|
|
|
1805
|
+
// src/shared/types/pii.ts
|
|
1806
|
+
var Iso2CountryCode = (value) => value;
|
|
1807
|
+
var PiiJurisdiction = {
|
|
1808
|
+
fromDto: (dto) => ({
|
|
1809
|
+
iso2: Iso2CountryCode(dto.iso_2),
|
|
1810
|
+
name: dto.name
|
|
1811
|
+
})
|
|
1812
|
+
};
|
|
1813
|
+
var PiiAddress = {
|
|
1814
|
+
fromDto: (dto) => ({
|
|
1815
|
+
street: dto.street,
|
|
1816
|
+
city: dto.city,
|
|
1817
|
+
state: dto.state,
|
|
1818
|
+
postalCode: dto.postal_code,
|
|
1819
|
+
country: dto.country
|
|
1820
|
+
})
|
|
1821
|
+
};
|
|
1822
|
+
var Pii = {
|
|
1823
|
+
fromDto: (dto) => ({
|
|
1824
|
+
kind: dto.kind,
|
|
1825
|
+
fullLegalName: dto.full_legal_name,
|
|
1826
|
+
dateOfBirth: dto.date_of_birth,
|
|
1827
|
+
jurisdiction: dto.jurisdiction ? PiiJurisdiction.fromDto(dto.jurisdiction) : null,
|
|
1828
|
+
taxId: dto.tax_id,
|
|
1829
|
+
permanentAddress: PiiAddress.fromDto(dto.permanent_address)
|
|
1830
|
+
})
|
|
1831
|
+
};
|
|
1832
|
+
|
|
1833
|
+
// src/shared/api/frontline/pii.ts
|
|
1834
|
+
async function fetchPii(api) {
|
|
1835
|
+
const dto = await api.send({
|
|
1836
|
+
method: "GET",
|
|
1837
|
+
url: "/v1/pii",
|
|
1838
|
+
attributes: Attributes.protected()
|
|
1839
|
+
});
|
|
1840
|
+
return Pii.fromDto(dto);
|
|
1841
|
+
}
|
|
1842
|
+
|
|
783
1843
|
// src/shared/types/requirement.ts
|
|
784
1844
|
var RequirementId = (value) => value;
|
|
785
1845
|
var Requirement = {
|
|
@@ -790,18 +1850,26 @@ var Requirement = {
|
|
|
790
1850
|
})
|
|
791
1851
|
};
|
|
792
1852
|
var RequirementStatusInfo = {
|
|
793
|
-
fromStatusesDto: (dto) => Object.entries(dto.statuses).map(
|
|
794
|
-
id: RequirementId(id),
|
|
795
|
-
|
|
796
|
-
|
|
1853
|
+
fromStatusesDto: (dto) => Object.entries(dto.statuses).map(
|
|
1854
|
+
([id, value]) => typeof value === "string" ? { id: RequirementId(id), status: value, action: null } : {
|
|
1855
|
+
id: RequirementId(id),
|
|
1856
|
+
status: value.status,
|
|
1857
|
+
action: value.action ?? null,
|
|
1858
|
+
kycLevel: value.kyc_level,
|
|
1859
|
+
kycReset: value.kyc_reset
|
|
1860
|
+
}
|
|
1861
|
+
)
|
|
797
1862
|
};
|
|
798
1863
|
|
|
799
1864
|
// src/shared/api/frontline/requirements.ts
|
|
800
|
-
async function fetchOfferRequirements(api, offerId) {
|
|
1865
|
+
async function fetchOfferRequirements(api, offerId, clientCreds) {
|
|
801
1866
|
const response = await api.send({
|
|
802
1867
|
method: "GET",
|
|
803
1868
|
url: `/v1/offers/${offerId}/requirements`,
|
|
804
|
-
attributes: Attributes.
|
|
1869
|
+
attributes: Attributes.concat(
|
|
1870
|
+
Attributes.protected(),
|
|
1871
|
+
Attributes.clientCredentials(clientCreds)
|
|
1872
|
+
)
|
|
805
1873
|
});
|
|
806
1874
|
return Object.fromEntries(
|
|
807
1875
|
Object.entries(response.options).map(([optionId, list]) => [
|
|
@@ -865,6 +1933,10 @@ var CoinListClientImpl = class {
|
|
|
865
1933
|
},
|
|
866
1934
|
this.fetchAccessToken.bind(this)
|
|
867
1935
|
);
|
|
1936
|
+
this.swap = new ClientSwapNamespaceImpl({
|
|
1937
|
+
api: this.api,
|
|
1938
|
+
ensureUserAuthenticated: async () => this.ensureAuthenticated()
|
|
1939
|
+
});
|
|
868
1940
|
}
|
|
869
1941
|
async init() {
|
|
870
1942
|
await this.fetchAccessToken(true);
|
|
@@ -936,15 +2008,15 @@ var CoinListClientImpl = class {
|
|
|
936
2008
|
}
|
|
937
2009
|
async fetchOffers() {
|
|
938
2010
|
this.ensureAuthenticated();
|
|
939
|
-
return fetchOffers(this.api);
|
|
2011
|
+
return fetchOffers(this.api, void 0);
|
|
940
2012
|
}
|
|
941
2013
|
async fetchOffersPage(params) {
|
|
942
2014
|
this.ensureAuthenticated();
|
|
943
|
-
return fetchOffersPage(this.api, params);
|
|
2015
|
+
return fetchOffersPage(this.api, params, void 0);
|
|
944
2016
|
}
|
|
945
2017
|
async fetchOfferDetails(id) {
|
|
946
2018
|
this.ensureAuthenticated();
|
|
947
|
-
return fetchOfferDetails(this.api, id);
|
|
2019
|
+
return fetchOfferDetails(this.api, id, void 0);
|
|
948
2020
|
}
|
|
949
2021
|
async fetchParticipations(offerId) {
|
|
950
2022
|
this.ensureAuthenticated();
|
|
@@ -962,14 +2034,46 @@ var CoinListClientImpl = class {
|
|
|
962
2034
|
this.ensureAuthenticated();
|
|
963
2035
|
return createParticipation(this.api, params);
|
|
964
2036
|
}
|
|
2037
|
+
async createWalletOwnershipChallenge(params) {
|
|
2038
|
+
this.ensureAuthenticated();
|
|
2039
|
+
return createWalletOwnershipChallenge(this.api, params);
|
|
2040
|
+
}
|
|
2041
|
+
async connectExternalWallet(offerId, params) {
|
|
2042
|
+
this.ensureAuthenticated();
|
|
2043
|
+
return connectExternalWallet(this.api, offerId, params);
|
|
2044
|
+
}
|
|
2045
|
+
async listOptionAddresses(offerId, offerOptionId) {
|
|
2046
|
+
this.ensureAuthenticated();
|
|
2047
|
+
return listOptionAddresses(
|
|
2048
|
+
this.api,
|
|
2049
|
+
offerId,
|
|
2050
|
+
offerOptionId
|
|
2051
|
+
);
|
|
2052
|
+
}
|
|
2053
|
+
async removeOptionAddress(offerId, addressId) {
|
|
2054
|
+
this.ensureAuthenticated();
|
|
2055
|
+
return removeOptionAddress(this.api, offerId, addressId);
|
|
2056
|
+
}
|
|
965
2057
|
async fetchOfferRequirements(offerId) {
|
|
966
2058
|
this.ensureAuthenticated();
|
|
967
|
-
return fetchOfferRequirements(this.api, offerId);
|
|
2059
|
+
return fetchOfferRequirements(this.api, offerId, void 0);
|
|
968
2060
|
}
|
|
969
2061
|
async fetchRequirementStatuses(offerId) {
|
|
970
2062
|
this.ensureAuthenticated();
|
|
971
2063
|
return fetchRequirementStatuses(this.api, offerId);
|
|
972
2064
|
}
|
|
2065
|
+
async fetchPii() {
|
|
2066
|
+
this.ensureAuthenticated();
|
|
2067
|
+
return fetchPii(this.api);
|
|
2068
|
+
}
|
|
2069
|
+
async submitDocument(documentType, fields) {
|
|
2070
|
+
this.ensureAuthenticated();
|
|
2071
|
+
return submitDocument(this.api, documentType, fields);
|
|
2072
|
+
}
|
|
2073
|
+
async createKycToken(levelName, reset) {
|
|
2074
|
+
this.ensureAuthenticated();
|
|
2075
|
+
return createKycToken(this.api, levelName, reset);
|
|
2076
|
+
}
|
|
973
2077
|
handleRequirement(requirement) {
|
|
974
2078
|
const baseUrl = this._config.coinlistBaseUrl ?? COINLIST_BASE_URL;
|
|
975
2079
|
let path;
|
|
@@ -996,6 +2100,9 @@ var CoinListClientImpl = class {
|
|
|
996
2100
|
case "jurisdiction":
|
|
997
2101
|
path = null;
|
|
998
2102
|
break;
|
|
2103
|
+
case "document":
|
|
2104
|
+
path = null;
|
|
2105
|
+
break;
|
|
999
2106
|
default: {
|
|
1000
2107
|
const _exhaustive = requirement.type;
|
|
1001
2108
|
return;
|
|
@@ -1021,7 +2128,7 @@ function createCoinListClient(config) {
|
|
|
1021
2128
|
}
|
|
1022
2129
|
|
|
1023
2130
|
// src/client/CoinListProvider.tsx
|
|
1024
|
-
var
|
|
2131
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
1025
2132
|
var CoinListContext = (0, import_react.createContext)(null);
|
|
1026
2133
|
function CoinListContextProvider({
|
|
1027
2134
|
config,
|
|
@@ -1049,17 +2156,60 @@ function CoinListContextProvider({
|
|
|
1049
2156
|
};
|
|
1050
2157
|
}, [coinlist]);
|
|
1051
2158
|
const value = (0, import_react.useMemo)(() => ({ coinlist, isReady }), [coinlist, isReady]);
|
|
1052
|
-
return /* @__PURE__ */ (0,
|
|
1053
|
-
}
|
|
1054
|
-
function CoinListProvider({ config, children }) {
|
|
1055
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(CoinListContextProvider, { config, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(CoinListStyleScope, { children }) });
|
|
2159
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CoinListContext.Provider, { value, children });
|
|
1056
2160
|
}
|
|
2161
|
+
var CoinListProvider = CoinListContextProvider;
|
|
1057
2162
|
|
|
1058
|
-
// src/client/
|
|
1059
|
-
var
|
|
2163
|
+
// src/client/CoinListStyleScope.tsx
|
|
2164
|
+
var import_react2 = require("react");
|
|
1060
2165
|
|
|
1061
|
-
// src/client/
|
|
1062
|
-
var typeClasses = {
|
|
2166
|
+
// src/client/generated/sdk-styles.gen.ts
|
|
2167
|
+
var sdkStyles = '/*! tailwindcss v4.2.1 | MIT License | https://tailwindcss.com */\n@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-space-y-reverse:0;--tw-divide-y-reverse:0;--tw-border-style:solid;--tw-gradient-position:initial;--tw-gradient-from:#0000;--tw-gradient-via:#0000;--tw-gradient-to:#0000;--tw-gradient-stops:initial;--tw-gradient-via-stops:initial;--tw-gradient-from-position:0%;--tw-gradient-via-position:50%;--tw-gradient-to-position:100%;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-duration:initial;--tw-ease:initial;--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0}}}@layer theme{:root,:host{--clcosdk-font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--clcosdk-color-red-400:oklch(70.4% .191 22.216);--clcosdk-color-red-500:oklch(63.7% .237 25.331);--clcosdk-color-amber-500:oklch(76.9% .188 70.08);--clcosdk-color-gray-400:oklch(70.7% .022 261.325);--clcosdk-color-gray-500:oklch(55.1% .027 264.364);--clcosdk-color-black:#000;--clcosdk-spacing:.25rem;--clcosdk-container-md:28rem;--clcosdk-text-xs:.75rem;--clcosdk-text-xs--line-height:calc(1 / .75);--clcosdk-text-sm:.875rem;--clcosdk-text-sm--line-height:calc(1.25 / .875);--clcosdk-text-base:1rem;--clcosdk-text-base--line-height:calc(1.5 / 1);--clcosdk-font-weight-normal:400;--clcosdk-font-weight-medium:500;--clcosdk-font-weight-semibold:600;--clcosdk-radius-md:.375rem;--clcosdk-radius-lg:.5rem;--clcosdk-radius-2xl:1rem;--clcosdk-ease-in-out:cubic-bezier(.4, 0, .2, 1);--clcosdk-animate-spin:spin 1s linear infinite;--clcosdk-animate-pulse:pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;--clcosdk-color-brand-primary:var(--color-brand-primary)}}@layer base{.clco-sdk-root{--color-brand-primary:#171717;--color-brand-primary-hover:#000;--color-brand-primary-active:#262626;--color-accent:#2b3a67;--color-accent-hover:#243057;--color-accent-active:#1d2647;--color-accent-focus:#c7d2fe;--color-accent-subtle:#eef1f8;--color-text-primary:#171717;--color-text-secondary:#8c8c8c;--color-text-disabled:#d1d1d1;--color-text-inverse:#fff;--color-background:#fff;--color-surface:#fafafa;--color-section:#f3f3f3;--color-border:#e5e5e5;--color-divider:#ececec;--color-overlay:#00000080;--color-positive:#15803d;--color-positive-subtle:#dcfce7;--color-negative:#dc2626;--color-negative-subtle:#fee2e2;--color-success:#2c8c5e;--color-success-subtle:#e6f4ec;--color-success-border:#cfe9db;--color-warning:#e08a1a;--color-warning-subtle:#fff7ed;--color-warning-border:#fdead7;--color-error:#b42318;--color-error-subtle:#feeceb;--color-error-border:#fbd5d2}@media (prefers-color-scheme:dark){.clco-sdk-root:not(:where(.light,.light *)){--color-brand-primary:#f4f4f5;--color-brand-primary-hover:#fff;--color-brand-primary-active:#e4e4e7;--color-accent:#6f82c9;--color-accent-hover:#8799e4;--color-accent-active:#5b6fcf;--color-accent-focus:#6f82c959;--color-accent-subtle:#6f82c91f;--color-text-primary:#f4f4f5;--color-text-secondary:#a1a1aa;--color-text-disabled:#71717a;--color-text-inverse:#171717;--color-background:#0f1115;--color-surface:#161a20;--color-section:#20242c;--color-border:#2a2e35;--color-divider:#323741;--color-overlay:#000000b3;--color-positive:#22c55e;--color-positive-subtle:#22c55e1f;--color-negative:#ef4444;--color-negative-subtle:#ef44441f;--color-success:#34d399;--color-success-subtle:#34d3991f;--color-success-border:#34d39940;--color-warning:#f59e0b;--color-warning-subtle:#f59e0b1f;--color-warning-border:#f59e0b40;--color-error:#f87171;--color-error-subtle:#f871711f;--color-error-border:#f8717140}}:where(.dark,.dark *) .clco-sdk-root{--color-brand-primary:#f4f4f5;--color-brand-primary-hover:#fff;--color-brand-primary-active:#e4e4e7;--color-accent:#6f82c9;--color-accent-hover:#8799e4;--color-accent-active:#5b6fcf;--color-accent-focus:#6f82c959;--color-accent-subtle:#6f82c91f;--color-text-primary:#f4f4f5;--color-text-secondary:#a1a1aa;--color-text-disabled:#71717a;--color-text-inverse:#171717;--color-background:#0f1115;--color-surface:#161a20;--color-section:#20242c;--color-border:#2a2e35;--color-divider:#323741;--color-overlay:#000000b3;--color-positive:#22c55e;--color-positive-subtle:#22c55e1f;--color-negative:#ef4444;--color-negative-subtle:#ef44441f;--color-success:#34d399;--color-success-subtle:#34d3991f;--color-success-border:#34d39940;--color-warning:#f59e0b;--color-warning-subtle:#f59e0b1f;--color-warning-border:#f59e0b40;--color-error:#f87171;--color-error-subtle:#f871711f;--color-error-border:#f8717140}.clco-sdk-root{color:var(--color-text-primary);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-family:Inter,sans-serif}.clco-sdk-root *,.clco-sdk-root :before,.clco-sdk-root :after{box-sizing:border-box}.clco-sdk-root button{appearance:none;cursor:pointer;font:inherit;color:inherit;background:0 0;border:none;padding:0}.clco-sdk-root a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}.clco-sdk-root ul,.clco-sdk-root ol{margin:0;padding:0;list-style:none}.clco-sdk-root img,.clco-sdk-root svg{max-width:100%;display:block}}@layer components;@layer utilities{.clcosdk\\:absolute{position:absolute}.clcosdk\\:fixed{position:fixed}.clcosdk\\:relative{position:relative}.clcosdk\\:inset-0{inset:calc(var(--clcosdk-spacing) * 0)}.clcosdk\\:top-4{top:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:right-4{right:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:z-50{z-index:50}.clcosdk\\:mt-4{margin-top:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:mb-6{margin-bottom:calc(var(--clcosdk-spacing) * 6)}.clcosdk\\:flex{display:flex}.clcosdk\\:grid{display:grid}.clcosdk\\:inline-flex{display:inline-flex}.clcosdk\\:h-3{height:calc(var(--clcosdk-spacing) * 3)}.clcosdk\\:h-4{height:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:h-5{height:calc(var(--clcosdk-spacing) * 5)}.clcosdk\\:h-6{height:calc(var(--clcosdk-spacing) * 6)}.clcosdk\\:h-9{height:calc(var(--clcosdk-spacing) * 9)}.clcosdk\\:h-11{height:calc(var(--clcosdk-spacing) * 11)}.clcosdk\\:h-12{height:calc(var(--clcosdk-spacing) * 12)}.clcosdk\\:h-14{height:calc(var(--clcosdk-spacing) * 14)}.clcosdk\\:h-28{height:calc(var(--clcosdk-spacing) * 28)}.clcosdk\\:h-52{height:calc(var(--clcosdk-spacing) * 52)}.clcosdk\\:h-\\[18px\\]{height:18px}.clcosdk\\:h-auto{height:auto}.clcosdk\\:h-full{height:100%}.clcosdk\\:max-h-\\[92vh\\]{max-height:92vh}.clcosdk\\:min-h-0{min-height:calc(var(--clcosdk-spacing) * 0)}.clcosdk\\:min-h-9{min-height:calc(var(--clcosdk-spacing) * 9)}.clcosdk\\:min-h-40{min-height:calc(var(--clcosdk-spacing) * 40)}.clcosdk\\:min-h-\\[2\\.4rem\\]{min-height:2.4rem}.clcosdk\\:w-4{width:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:w-5{width:calc(var(--clcosdk-spacing) * 5)}.clcosdk\\:w-6{width:calc(var(--clcosdk-spacing) * 6)}.clcosdk\\:w-12{width:calc(var(--clcosdk-spacing) * 12)}.clcosdk\\:w-16{width:calc(var(--clcosdk-spacing) * 16)}.clcosdk\\:w-28{width:calc(var(--clcosdk-spacing) * 28)}.clcosdk\\:w-48{width:calc(var(--clcosdk-spacing) * 48)}.clcosdk\\:w-80{width:calc(var(--clcosdk-spacing) * 80)}.clcosdk\\:w-96{width:calc(var(--clcosdk-spacing) * 96)}.clcosdk\\:w-\\[16px\\]{width:16px}.clcosdk\\:w-\\[448px\\]{width:448px}.clcosdk\\:w-auto{width:auto}.clcosdk\\:w-full{width:100%}.clcosdk\\:max-w-\\[22rem\\]{max-width:22rem}.clcosdk\\:max-w-\\[28rem\\]{max-width:28rem}.clcosdk\\:max-w-\\[30rem\\]{max-width:30rem}.clcosdk\\:max-w-\\[760px\\]{max-width:760px}.clcosdk\\:max-w-\\[1200px\\]{max-width:1200px}.clcosdk\\:max-w-md{max-width:var(--clcosdk-container-md)}.clcosdk\\:shrink-0{flex-shrink:0}.clcosdk\\:rotate-90{rotate:90deg}.clcosdk\\:animate-pulse{animation:var(--clcosdk-animate-pulse)}.clcosdk\\:animate-spin{animation:var(--clcosdk-animate-spin)}.clcosdk\\:cursor-pointer{cursor:pointer}.clcosdk\\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.clcosdk\\:grid-rows-\\[0fr\\]{grid-template-rows:0fr}.clcosdk\\:grid-rows-\\[1fr\\]{grid-template-rows:1fr}.clcosdk\\:flex-col{flex-direction:column}.clcosdk\\:flex-wrap{flex-wrap:wrap}.clcosdk\\:items-center{align-items:center}.clcosdk\\:items-start{align-items:flex-start}.clcosdk\\:justify-between{justify-content:space-between}.clcosdk\\:justify-center{justify-content:center}.clcosdk\\:gap-1{gap:calc(var(--clcosdk-spacing) * 1)}.clcosdk\\:gap-2{gap:calc(var(--clcosdk-spacing) * 2)}.clcosdk\\:gap-3{gap:calc(var(--clcosdk-spacing) * 3)}.clcosdk\\:gap-4{gap:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:gap-5{gap:calc(var(--clcosdk-spacing) * 5)}.clcosdk\\:gap-6{gap:calc(var(--clcosdk-spacing) * 6)}.clcosdk\\:gap-8{gap:calc(var(--clcosdk-spacing) * 8)}.clcosdk\\:gap-\\[5px\\]{gap:5px}:where(.clcosdk\\:space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--clcosdk-spacing) * 3) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--clcosdk-spacing) * 3) * calc(1 - var(--tw-space-y-reverse)))}:where(.clcosdk\\:space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--clcosdk-spacing) * 4) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--clcosdk-spacing) * 4) * calc(1 - var(--tw-space-y-reverse)))}:where(.clcosdk\\:divide-y>:not(:last-child)){--tw-divide-y-reverse:0;border-bottom-style:var(--tw-border-style);border-top-style:var(--tw-border-style);border-top-width:calc(1px * var(--tw-divide-y-reverse));border-bottom-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)))}:where(.clcosdk\\:divide-border>:not(:last-child)){border-color:var(--color-border)}:where(.clcosdk\\:divide-divider>:not(:last-child)){border-color:var(--color-divider)}.clcosdk\\:self-start{align-self:flex-start}.clcosdk\\:overflow-hidden{overflow:hidden}.clcosdk\\:overflow-y-auto{overflow-y:auto}.clcosdk\\:rounded{border-radius:.25rem}.clcosdk\\:rounded-2xl{border-radius:var(--clcosdk-radius-2xl)}.clcosdk\\:rounded-btn{border-radius:12px}.clcosdk\\:rounded-card{border-radius:24px}.clcosdk\\:rounded-full{border-radius:3.40282e38px}.clcosdk\\:rounded-lg{border-radius:var(--clcosdk-radius-lg)}.clcosdk\\:rounded-md{border-radius:var(--clcosdk-radius-md)}.clcosdk\\:border{border-style:var(--tw-border-style);border-width:1px}.clcosdk\\:border-2{border-style:var(--tw-border-style);border-width:2px}.clcosdk\\:border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.clcosdk\\:border-dashed{--tw-border-style:dashed;border-style:dashed}.clcosdk\\:border-accent\\/50{border-color:var(--color-accent)}@supports (color:color-mix(in lab, red, red)){.clcosdk\\:border-accent\\/50{border-color:color-mix(in oklab, var(--color-accent) 50%, transparent)}}.clcosdk\\:border-accent\\/60{border-color:var(--color-accent)}@supports (color:color-mix(in lab, red, red)){.clcosdk\\:border-accent\\/60{border-color:color-mix(in oklab, var(--color-accent) 60%, transparent)}}.clcosdk\\:border-amber-500{border-color:var(--clcosdk-color-amber-500)}.clcosdk\\:border-border,.clcosdk\\:border-border\\/60{border-color:var(--color-border)}@supports (color:color-mix(in lab, red, red)){.clcosdk\\:border-border\\/60{border-color:color-mix(in oklab, var(--color-border) 60%, transparent)}}.clcosdk\\:border-current{border-color:currentColor}.clcosdk\\:border-divider{border-color:var(--color-divider)}.clcosdk\\:border-error-border{border-color:var(--color-error-border)}.clcosdk\\:border-success-border{border-color:var(--color-success-border)}.clcosdk\\:border-warning-border{border-color:var(--color-warning-border)}.clcosdk\\:border-t-transparent{border-top-color:#0000}.clcosdk\\:bg-accent\\/10{background-color:var(--color-accent)}@supports (color:color-mix(in lab, red, red)){.clcosdk\\:bg-accent\\/10{background-color:color-mix(in oklab, var(--color-accent) 10%, transparent)}}.clcosdk\\:bg-background{background-color:var(--color-background)}.clcosdk\\:bg-black\\/50{background-color:var(--clcosdk-color-black)}@supports (color:color-mix(in lab, red, red)){.clcosdk\\:bg-black\\/50{background-color:color-mix(in oklab, var(--clcosdk-color-black) 50%, transparent)}}.clcosdk\\:bg-brand-primary{background-color:var(--color-brand-primary)}.clcosdk\\:bg-error-subtle{background-color:var(--color-error-subtle)}.clcosdk\\:bg-overlay{background-color:var(--color-overlay)}.clcosdk\\:bg-section{background-color:var(--color-section)}.clcosdk\\:bg-success-subtle{background-color:var(--color-success-subtle)}.clcosdk\\:bg-surface{background-color:var(--color-surface)}.clcosdk\\:bg-transparent{background-color:#0000}.clcosdk\\:bg-warning-subtle{background-color:var(--color-warning-subtle)}.clcosdk\\:bg-gradient-to-b{--tw-gradient-position:to bottom in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.clcosdk\\:bg-gradient-to-br{--tw-gradient-position:to bottom right in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.clcosdk\\:from-surface{--tw-gradient-from:var(--color-surface);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.clcosdk\\:from-transparent{--tw-gradient-from:transparent;--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.clcosdk\\:via-section{--tw-gradient-via:var(--color-section);--tw-gradient-via-stops:var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-via) var(--tw-gradient-via-position), var(--tw-gradient-to) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-via-stops)}.clcosdk\\:via-transparent{--tw-gradient-via:transparent;--tw-gradient-via-stops:var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-via) var(--tw-gradient-via-position), var(--tw-gradient-to) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-via-stops)}.clcosdk\\:to-background{--tw-gradient-to:var(--color-background);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.clcosdk\\:to-overlay\\/35{--tw-gradient-to:var(--color-overlay)}@supports (color:color-mix(in lab, red, red)){.clcosdk\\:to-overlay\\/35{--tw-gradient-to:color-mix(in oklab, var(--color-overlay) 35%, transparent)}}.clcosdk\\:to-overlay\\/35{--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.clcosdk\\:object-cover{object-fit:cover}.clcosdk\\:p-0{padding:calc(var(--clcosdk-spacing) * 0)}.clcosdk\\:p-1\\.5{padding:calc(var(--clcosdk-spacing) * 1.5)}.clcosdk\\:p-3{padding:calc(var(--clcosdk-spacing) * 3)}.clcosdk\\:p-4{padding:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:p-6{padding:calc(var(--clcosdk-spacing) * 6)}.clcosdk\\:p-8{padding:calc(var(--clcosdk-spacing) * 8)}.clcosdk\\:px-2{padding-inline:calc(var(--clcosdk-spacing) * 2)}.clcosdk\\:px-3{padding-inline:calc(var(--clcosdk-spacing) * 3)}.clcosdk\\:px-4{padding-inline:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:px-5{padding-inline:calc(var(--clcosdk-spacing) * 5)}.clcosdk\\:px-6{padding-inline:calc(var(--clcosdk-spacing) * 6)}.clcosdk\\:py-2{padding-block:calc(var(--clcosdk-spacing) * 2)}.clcosdk\\:pt-4{padding-top:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:pt-14{padding-top:calc(var(--clcosdk-spacing) * 14)}.clcosdk\\:pb-4{padding-bottom:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:text-center{text-align:center}.clcosdk\\:text-left{text-align:left}.clcosdk\\:font-mono{font-family:var(--clcosdk-font-mono)}.clcosdk\\:text-base{font-size:var(--clcosdk-text-base);line-height:var(--tw-leading,var(--clcosdk-text-base--line-height))}.clcosdk\\:text-sm{font-size:var(--clcosdk-text-sm);line-height:var(--tw-leading,var(--clcosdk-text-sm--line-height))}.clcosdk\\:text-xs{font-size:var(--clcosdk-text-xs);line-height:var(--tw-leading,var(--clcosdk-text-xs--line-height))}.clcosdk\\:text-\\[11px\\]{font-size:11px}.clcosdk\\:text-\\[12px\\]{font-size:12px}.clcosdk\\:text-\\[14px\\]{font-size:14px}.clcosdk\\:text-\\[16px\\]{font-size:16px}.clcosdk\\:text-\\[18px\\]{font-size:18px}.clcosdk\\:text-\\[22px\\]{font-size:22px}.clcosdk\\:text-\\[28px\\]{font-size:28px}.clcosdk\\:text-\\[36px\\]{font-size:36px}.clcosdk\\:text-\\[48px\\]{font-size:48px}.clcosdk\\:text-\\[64px\\]{font-size:64px}.clcosdk\\:leading-\\[110\\%\\]{--tw-leading:110%;line-height:110%}.clcosdk\\:leading-\\[120\\%\\]{--tw-leading:120%;line-height:120%}.clcosdk\\:leading-\\[125\\%\\]{--tw-leading:125%;line-height:125%}.clcosdk\\:leading-\\[130\\%\\]{--tw-leading:130%;line-height:130%}.clcosdk\\:leading-\\[135\\%\\]{--tw-leading:135%;line-height:135%}.clcosdk\\:leading-\\[140\\%\\]{--tw-leading:140%;line-height:140%}.clcosdk\\:leading-\\[150\\%\\]{--tw-leading:150%;line-height:150%}.clcosdk\\:font-medium{--tw-font-weight:var(--clcosdk-font-weight-medium);font-weight:var(--clcosdk-font-weight-medium)}.clcosdk\\:font-normal{--tw-font-weight:var(--clcosdk-font-weight-normal);font-weight:var(--clcosdk-font-weight-normal)}.clcosdk\\:font-semibold{--tw-font-weight:var(--clcosdk-font-weight-semibold);font-weight:var(--clcosdk-font-weight-semibold)}.clcosdk\\:tracking-\\[0\\.12px\\]{--tw-tracking:.12px;letter-spacing:.12px}.clcosdk\\:tracking-\\[0\\.28px\\]{--tw-tracking:.28px;letter-spacing:.28px}.clcosdk\\:whitespace-nowrap{white-space:nowrap}.clcosdk\\:text-error{color:var(--color-error)}.clcosdk\\:text-success{color:var(--color-success)}.clcosdk\\:text-text-inverse{color:var(--color-text-inverse)}.clcosdk\\:text-text-primary{color:var(--color-text-primary)}.clcosdk\\:text-text-secondary{color:var(--color-text-secondary)}.clcosdk\\:text-warning{color:var(--color-warning)}.clcosdk\\:capitalize{text-transform:capitalize}.clcosdk\\:underline{text-decoration-line:underline}.clcosdk\\:underline-offset-2{text-underline-offset:2px}.clcosdk\\:underline-offset-4{text-underline-offset:4px}.clcosdk\\:opacity-60{opacity:.6}.clcosdk\\:shadow-\\[0_0_0_3px_rgba\\(59\\,130\\,246\\,0\\.2\\)\\]{--tw-shadow:0 0 0 3px var(--tw-shadow-color,#3b82f633);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.clcosdk\\:shadow-\\[0_0_0_3px_rgba\\(59\\,130\\,246\\,0\\.18\\)\\]{--tw-shadow:0 0 0 3px var(--tw-shadow-color,#3b82f62e);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.clcosdk\\:shadow-\\[0_0_0_3px_rgba\\(59\\,130\\,246\\,0\\.25\\)\\]{--tw-shadow:0 0 0 3px var(--tw-shadow-color,#3b82f640);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.clcosdk\\:shadow-\\[0_10px_24px_rgba\\(0\\,0\\,0\\,0\\.18\\)\\]{--tw-shadow:0 10px 24px var(--tw-shadow-color,#0000002e);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.clcosdk\\:shadow-\\[0_10px_24px_rgba\\(0\\,0\\,0\\,0\\.25\\)\\]{--tw-shadow:0 10px 24px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.clcosdk\\:shadow-card{--tw-shadow:0px 4px 6px -2px var(--tw-shadow-color,#0000000d), 0px 12px 24px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.clcosdk\\:transition-\\[grid-template-rows\\]{transition-property:grid-template-rows;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.clcosdk\\:transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.clcosdk\\:transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.clcosdk\\:transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.clcosdk\\:duration-200{--tw-duration:.2s;transition-duration:.2s}.clcosdk\\:duration-300{--tw-duration:.3s;transition-duration:.3s}.clcosdk\\:ease-in-out{--tw-ease:var(--clcosdk-ease-in-out);transition-timing-function:var(--clcosdk-ease-in-out)}@media (hover:hover){.clcosdk\\:hover\\:-translate-y-0\\.5:hover{--tw-translate-y:calc(var(--clcosdk-spacing) * -.5);translate:var(--tw-translate-x) var(--tw-translate-y)}.clcosdk\\:hover\\:border-divider:hover{border-color:var(--color-divider)}.clcosdk\\:hover\\:bg-\\[\\#fcdcd8\\]:hover{background-color:#fcdcd8}.clcosdk\\:hover\\:bg-border:hover{background-color:var(--color-border)}.clcosdk\\:hover\\:bg-brand-primary:hover{background-color:var(--color-brand-primary)}.clcosdk\\:hover\\:bg-brand-primary-hover:hover{background-color:var(--color-brand-primary-hover)}.clcosdk\\:hover\\:bg-section:hover{background-color:var(--color-section)}.clcosdk\\:hover\\:bg-surface:hover{background-color:var(--color-surface)}.clcosdk\\:hover\\:text-\\[\\#8b1a13\\]:hover{color:#8b1a13}.clcosdk\\:hover\\:text-text-primary:hover{color:var(--color-text-primary)}.clcosdk\\:hover\\:underline:hover{text-decoration-line:underline}.clcosdk\\:hover\\:shadow-\\[0px_14px_32px_-10px_rgba\\(0\\,0\\,0\\,0\\.35\\)\\]:hover{--tw-shadow:0px 14px 32px -10px var(--tw-shadow-color,#00000059);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}}.clcosdk\\:focus-visible\\:ring-2:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.clcosdk\\:focus-visible\\:ring-accent-focus:focus-visible{--tw-ring-color:var(--color-accent-focus)}.clcosdk\\:focus-visible\\:ring-gray-400:focus-visible{--tw-ring-color:var(--clcosdk-color-gray-400)}.clcosdk\\:focus-visible\\:ring-gray-500:focus-visible{--tw-ring-color:var(--clcosdk-color-gray-500)}.clcosdk\\:focus-visible\\:ring-red-400:focus-visible{--tw-ring-color:var(--clcosdk-color-red-400)}.clcosdk\\:focus-visible\\:ring-red-500:focus-visible{--tw-ring-color:var(--clcosdk-color-red-500)}.clcosdk\\:focus-visible\\:ring-offset-2:focus-visible{--tw-ring-offset-width:2px;--tw-ring-offset-shadow:var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)}.clcosdk\\:focus-visible\\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.clcosdk\\:active\\:bg-\\[\\#d9d9d9\\]:active{background-color:#d9d9d9}.clcosdk\\:active\\:bg-\\[\\#f9c9c4\\]:active{background-color:#f9c9c4}.clcosdk\\:active\\:bg-border:active{background-color:var(--color-border)}.clcosdk\\:active\\:bg-brand-primary-active:active{background-color:var(--color-brand-primary-active)}.clcosdk\\:active\\:text-\\[\\#6d1510\\]:active{color:#6d1510}.clcosdk\\:disabled\\:pointer-events-none:disabled{pointer-events:none}.clcosdk\\:disabled\\:opacity-40:disabled{opacity:.4}@media (prefers-color-scheme:dark){@media (hover:hover){.clcosdk\\:dark\\:hover\\:bg-\\[rgba\\(248\\,113\\,113\\,0\\.20\\)\\]:not(:where(.light,.light *)):hover{background-color:#f8717133}}}@media (hover:hover){.clcosdk\\:dark\\:hover\\:bg-\\[rgba\\(248\\,113\\,113\\,0\\.20\\)\\]:where(.dark,.dark *):hover{background-color:#f8717133}}@media (prefers-color-scheme:dark){@media (hover:hover){.clcosdk\\:dark\\:hover\\:text-\\[\\#fca5a5\\]:not(:where(.light,.light *)):hover{color:#fca5a5}}}@media (hover:hover){.clcosdk\\:dark\\:hover\\:text-\\[\\#fca5a5\\]:where(.dark,.dark *):hover{color:#fca5a5}}@media (prefers-color-scheme:dark){.clcosdk\\:dark\\:active\\:bg-\\[rgba\\(248\\,113\\,113\\,0\\.30\\)\\]:not(:where(.light,.light *)):active{background-color:#f871714d}}.clcosdk\\:dark\\:active\\:bg-\\[rgba\\(248\\,113\\,113\\,0\\.30\\)\\]:where(.dark,.dark *):active{background-color:#f871714d}@media (prefers-color-scheme:dark){.clcosdk\\:dark\\:active\\:bg-divider:not(:where(.light,.light *)):active{background-color:var(--color-divider)}}.clcosdk\\:dark\\:active\\:bg-divider:where(.dark,.dark *):active{background-color:var(--color-divider)}@media (prefers-color-scheme:dark){.clcosdk\\:dark\\:active\\:text-\\[\\#f87171\\]:not(:where(.light,.light *)):active{color:#f87171}}.clcosdk\\:dark\\:active\\:text-\\[\\#f87171\\]:where(.dark,.dark *):active{color:#f87171}.clcosdk\\:\\[\\&_circle\\]\\:fill-error-subtle circle{fill:var(--color-error-subtle)}.clcosdk\\:\\[\\&_circle\\]\\:fill-success-subtle circle{fill:var(--color-success-subtle)}.clcosdk\\:\\[\\&_circle\\]\\:fill-warning-subtle circle{fill:var(--color-warning-subtle)}}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-divide-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-gradient-position{syntax:"*";inherits:false}@property --tw-gradient-from{syntax:"<color>";inherits:false;initial-value:#0000}@property --tw-gradient-via{syntax:"<color>";inherits:false;initial-value:#0000}@property --tw-gradient-to{syntax:"<color>";inherits:false;initial-value:#0000}@property --tw-gradient-stops{syntax:"*";inherits:false}@property --tw-gradient-via-stops{syntax:"*";inherits:false}@property --tw-gradient-from-position{syntax:"<length-percentage>";inherits:false;initial-value:0%}@property --tw-gradient-via-position{syntax:"<length-percentage>";inherits:false;initial-value:50%}@property --tw-gradient-to-position{syntax:"<length-percentage>";inherits:false;initial-value:100%}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@keyframes spin{to{transform:rotate(360deg)}}@keyframes pulse{50%{opacity:.5}}';
|
|
2168
|
+
|
|
2169
|
+
// src/client/CoinListStyleScope.tsx
|
|
2170
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
2171
|
+
var ScopeContext = (0, import_react2.createContext)(false);
|
|
2172
|
+
function CoinListStyleScope({ children }) {
|
|
2173
|
+
const alreadyScoped = (0, import_react2.useContext)(ScopeContext);
|
|
2174
|
+
if (alreadyScoped) {
|
|
2175
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children });
|
|
2176
|
+
}
|
|
2177
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
2178
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("link", { rel: "preconnect", href: "https://fonts.googleapis.com" }),
|
|
2179
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
2180
|
+
"link",
|
|
2181
|
+
{
|
|
2182
|
+
rel: "preconnect",
|
|
2183
|
+
href: "https://fonts.gstatic.com",
|
|
2184
|
+
crossOrigin: "anonymous"
|
|
2185
|
+
}
|
|
2186
|
+
),
|
|
2187
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
2188
|
+
"link",
|
|
2189
|
+
{
|
|
2190
|
+
rel: "stylesheet",
|
|
2191
|
+
href: "https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap"
|
|
2192
|
+
}
|
|
2193
|
+
),
|
|
2194
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "clco-sdk-root", style: { display: "contents" }, children: [
|
|
2195
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
2196
|
+
"style",
|
|
2197
|
+
{
|
|
2198
|
+
href: "clco-sdk-styles",
|
|
2199
|
+
precedence: "default",
|
|
2200
|
+
dangerouslySetInnerHTML: { __html: sdkStyles }
|
|
2201
|
+
}
|
|
2202
|
+
),
|
|
2203
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ScopeContext.Provider, { value: true, children })
|
|
2204
|
+
] })
|
|
2205
|
+
] });
|
|
2206
|
+
}
|
|
2207
|
+
|
|
2208
|
+
// src/client/components/design-system/AlertBanner.tsx
|
|
2209
|
+
var import_lucide_react = require("lucide-react");
|
|
2210
|
+
|
|
2211
|
+
// src/client/components/design-system/tokens/typography.ts
|
|
2212
|
+
var typeClasses = {
|
|
1063
2213
|
hero: "clcosdk:text-[64px] clcosdk:leading-[110%] clcosdk:font-semibold",
|
|
1064
2214
|
display: "clcosdk:text-[48px] clcosdk:leading-[110%] clcosdk:font-semibold",
|
|
1065
2215
|
h1: "clcosdk:text-[36px] clcosdk:leading-[120%] clcosdk:font-semibold",
|
|
@@ -1232,7 +2382,7 @@ function PoweredByCoinList({ className }) {
|
|
|
1232
2382
|
|
|
1233
2383
|
// src/client/components/design-system/ClButton.tsx
|
|
1234
2384
|
var import_class_variance_authority = require("class-variance-authority");
|
|
1235
|
-
var
|
|
2385
|
+
var import_react3 = require("react");
|
|
1236
2386
|
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
1237
2387
|
var buttonVariants = (0, import_class_variance_authority.cva)(
|
|
1238
2388
|
"clcosdk:inline-flex clcosdk:items-center clcosdk:justify-center clcosdk:gap-3 clcosdk:whitespace-nowrap clcosdk:transition-colors clcosdk:focus-visible:outline-none clcosdk:focus-visible:ring-2 clcosdk:focus-visible:ring-offset-2 clcosdk:disabled:pointer-events-none clcosdk:disabled:opacity-40 clcosdk:cursor-pointer",
|
|
@@ -1284,7 +2434,7 @@ var buttonVariants = (0, import_class_variance_authority.cva)(
|
|
|
1284
2434
|
}
|
|
1285
2435
|
}
|
|
1286
2436
|
);
|
|
1287
|
-
var ClButton = (0,
|
|
2437
|
+
var ClButton = (0, import_react3.forwardRef)(
|
|
1288
2438
|
({
|
|
1289
2439
|
className,
|
|
1290
2440
|
variant,
|
|
@@ -1402,9 +2552,9 @@ function CoinListSignInButton({
|
|
|
1402
2552
|
}
|
|
1403
2553
|
|
|
1404
2554
|
// src/client/hooks/useCoinList.ts
|
|
1405
|
-
var
|
|
2555
|
+
var import_react4 = require("react");
|
|
1406
2556
|
function useCoinList() {
|
|
1407
|
-
const context = (0,
|
|
2557
|
+
const context = (0, import_react4.useContext)(CoinListContext);
|
|
1408
2558
|
if (context === null) {
|
|
1409
2559
|
throw new CoinListClientInitializationError();
|
|
1410
2560
|
}
|
|
@@ -1432,7 +2582,7 @@ function CoinListSignInCard({
|
|
|
1432
2582
|
const handleSignIn = onSignIn ?? (() => {
|
|
1433
2583
|
void coinlist.startOAuth();
|
|
1434
2584
|
});
|
|
1435
|
-
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
2585
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(CoinListStyleScope, { children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
1436
2586
|
"div",
|
|
1437
2587
|
{
|
|
1438
2588
|
className: cn(
|
|
@@ -1471,7 +2621,7 @@ function CoinListSignInCard({
|
|
|
1471
2621
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(PoweredByCoinList, { className: "clcosdk:mt-4" })
|
|
1472
2622
|
]
|
|
1473
2623
|
}
|
|
1474
|
-
);
|
|
2624
|
+
) });
|
|
1475
2625
|
}
|
|
1476
2626
|
|
|
1477
2627
|
// src/client/components/offers/OfferCard.tsx
|
|
@@ -1569,22 +2719,20 @@ function OfferCard({
|
|
|
1569
2719
|
} else {
|
|
1570
2720
|
cardNode = /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: baseClasses, children: cardContent });
|
|
1571
2721
|
}
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
}
|
|
1575
|
-
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: containerClassName, children: cardNode });
|
|
2722
|
+
const card = containerClassName ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: containerClassName, children: cardNode }) : cardNode;
|
|
2723
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(CoinListStyleScope, { children: card });
|
|
1576
2724
|
}
|
|
1577
2725
|
|
|
1578
2726
|
// src/client/hooks/useOffers.ts
|
|
1579
|
-
var
|
|
2727
|
+
var import_react5 = require("react");
|
|
1580
2728
|
var LOADING_STATE = { type: "LOADING" };
|
|
1581
2729
|
function useOffers(options = {}) {
|
|
1582
2730
|
const { coinlist, isReady } = useCoinList();
|
|
1583
2731
|
const { data: serverOffers } = options;
|
|
1584
|
-
const [offersState, setOffersState] = (0,
|
|
2732
|
+
const [offersState, setOffersState] = (0, import_react5.useState)(
|
|
1585
2733
|
serverOffers !== void 0 ? { type: "CONTENT", offers: serverOffers } : LOADING_STATE
|
|
1586
2734
|
);
|
|
1587
|
-
(0,
|
|
2735
|
+
(0, import_react5.useEffect)(() => {
|
|
1588
2736
|
let isCancelled = false;
|
|
1589
2737
|
if (!isReady) {
|
|
1590
2738
|
if (serverOffers === void 0) {
|
|
@@ -1620,7 +2768,7 @@ function useOffers(options = {}) {
|
|
|
1620
2768
|
// src/client/components/offers/OffersGrid.tsx
|
|
1621
2769
|
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
1622
2770
|
var DEFAULT_MAX_COLUMNS = 3;
|
|
1623
|
-
function
|
|
2771
|
+
function OffersGridBody({
|
|
1624
2772
|
data,
|
|
1625
2773
|
maxColumns,
|
|
1626
2774
|
className,
|
|
@@ -1714,13 +2862,573 @@ function OffersGrid({
|
|
|
1714
2862
|
}
|
|
1715
2863
|
);
|
|
1716
2864
|
}
|
|
2865
|
+
function OffersGrid(props = {}) {
|
|
2866
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(CoinListStyleScope, { children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(OffersGridBody, { ...props }) });
|
|
2867
|
+
}
|
|
2868
|
+
|
|
2869
|
+
// src/client/components/requirements/ConnectedWalletList.tsx
|
|
2870
|
+
var import_react6 = require("react");
|
|
2871
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
2872
|
+
function ConnectedWalletRow({
|
|
2873
|
+
wallet,
|
|
2874
|
+
onRemove
|
|
2875
|
+
}) {
|
|
2876
|
+
const [state, setState] = (0, import_react6.useState)("idle");
|
|
2877
|
+
const remove = async () => {
|
|
2878
|
+
if (!onRemove) return;
|
|
2879
|
+
setState("removing");
|
|
2880
|
+
try {
|
|
2881
|
+
await onRemove(wallet.id);
|
|
2882
|
+
setState("idle");
|
|
2883
|
+
} catch {
|
|
2884
|
+
setState("error");
|
|
2885
|
+
}
|
|
2886
|
+
};
|
|
2887
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "clcosdk:flex clcosdk:min-h-9 clcosdk:flex-wrap clcosdk:items-center clcosdk:justify-between clcosdk:gap-2", children: [
|
|
2888
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2889
|
+
"span",
|
|
2890
|
+
{
|
|
2891
|
+
title: wallet.address,
|
|
2892
|
+
className: cn(
|
|
2893
|
+
typeClasses.body,
|
|
2894
|
+
"clcosdk:font-mono clcosdk:text-text-primary"
|
|
2895
|
+
),
|
|
2896
|
+
children: wallet.shortAddress
|
|
2897
|
+
}
|
|
2898
|
+
),
|
|
2899
|
+
onRemove != null && (state === "confirming" ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "clcosdk:flex clcosdk:items-center clcosdk:gap-2", children: [
|
|
2900
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2901
|
+
"span",
|
|
2902
|
+
{
|
|
2903
|
+
className: cn(typeClasses.subhead, "clcosdk:text-text-secondary"),
|
|
2904
|
+
children: "Remove?"
|
|
2905
|
+
}
|
|
2906
|
+
),
|
|
2907
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ClButton, { size: "sm", variant: "destructive", onClick: remove, children: "Remove" }),
|
|
2908
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2909
|
+
ClButton,
|
|
2910
|
+
{
|
|
2911
|
+
size: "sm",
|
|
2912
|
+
variant: "ghost",
|
|
2913
|
+
onClick: () => setState("idle"),
|
|
2914
|
+
children: "Cancel"
|
|
2915
|
+
}
|
|
2916
|
+
)
|
|
2917
|
+
] }) : state === "error" ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "clcosdk:flex clcosdk:items-center clcosdk:gap-2", children: [
|
|
2918
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: cn(typeClasses.subhead, "clcosdk:text-error"), children: "Couldn't remove." }),
|
|
2919
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2920
|
+
ClButton,
|
|
2921
|
+
{
|
|
2922
|
+
size: "sm",
|
|
2923
|
+
variant: "destructiveLink",
|
|
2924
|
+
onClick: () => setState("confirming"),
|
|
2925
|
+
children: "Try again"
|
|
2926
|
+
}
|
|
2927
|
+
)
|
|
2928
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2929
|
+
ClButton,
|
|
2930
|
+
{
|
|
2931
|
+
size: "sm",
|
|
2932
|
+
variant: "destructiveLink",
|
|
2933
|
+
disabled: state === "removing",
|
|
2934
|
+
onClick: () => setState("confirming"),
|
|
2935
|
+
children: state === "removing" ? "Removing\u2026" : "Remove"
|
|
2936
|
+
}
|
|
2937
|
+
))
|
|
2938
|
+
] });
|
|
2939
|
+
}
|
|
2940
|
+
function ConnectedWalletList({
|
|
2941
|
+
wallets,
|
|
2942
|
+
onRemove,
|
|
2943
|
+
onAdd,
|
|
2944
|
+
addLabel = "Add wallet",
|
|
2945
|
+
status = "ready",
|
|
2946
|
+
className
|
|
2947
|
+
}) {
|
|
2948
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
2949
|
+
"div",
|
|
2950
|
+
{
|
|
2951
|
+
className: cn("clcosdk:flex clcosdk:flex-col clcosdk:gap-2", className),
|
|
2952
|
+
children: [
|
|
2953
|
+
status === "loading" ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(AlertBanner, { variant: "info", content: "Loading your connected wallets\u2026" }) : status === "error" ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2954
|
+
AlertBanner,
|
|
2955
|
+
{
|
|
2956
|
+
variant: "error",
|
|
2957
|
+
content: "Couldn't load your connected wallets."
|
|
2958
|
+
}
|
|
2959
|
+
) : wallets.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(AlertBanner, { variant: "info", content: "No wallets connected yet." }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:divide-y clcosdk:divide-divider", children: wallets.map((wallet) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2960
|
+
ConnectedWalletRow,
|
|
2961
|
+
{
|
|
2962
|
+
wallet,
|
|
2963
|
+
onRemove
|
|
2964
|
+
},
|
|
2965
|
+
wallet.id
|
|
2966
|
+
)) }),
|
|
2967
|
+
onAdd != null && status !== "loading" && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2968
|
+
ClButton,
|
|
2969
|
+
{
|
|
2970
|
+
size: "sm",
|
|
2971
|
+
variant: "secondary",
|
|
2972
|
+
onClick: onAdd,
|
|
2973
|
+
className: "clcosdk:self-start",
|
|
2974
|
+
children: addLabel
|
|
2975
|
+
}
|
|
2976
|
+
)
|
|
2977
|
+
]
|
|
2978
|
+
}
|
|
2979
|
+
);
|
|
2980
|
+
}
|
|
2981
|
+
|
|
2982
|
+
// src/client/components/requirements/ConnectWalletModal.tsx
|
|
2983
|
+
var import_react8 = require("react");
|
|
2984
|
+
|
|
2985
|
+
// src/client/hooks/useConnectWallet.ts
|
|
2986
|
+
var import_react7 = require("react");
|
|
2987
|
+
|
|
2988
|
+
// src/client/core/connect-external-wallet.ts
|
|
2989
|
+
var DEFAULT_STATEMENT = "Sign this message to prove you own this wallet. This does not cost gas or move funds.";
|
|
2990
|
+
var TERMINAL_CODES = /* @__PURE__ */ new Set([
|
|
2991
|
+
"not_authenticated",
|
|
2992
|
+
"wallet_not_whitelisted",
|
|
2993
|
+
"max_wallets_reached"
|
|
2994
|
+
]);
|
|
2995
|
+
var API_ERROR_CODES = /* @__PURE__ */ new Set([
|
|
2996
|
+
"wallet_not_whitelisted",
|
|
2997
|
+
"max_wallets_reached"
|
|
2998
|
+
]);
|
|
2999
|
+
function flowError(code) {
|
|
3000
|
+
return { code, retryable: !TERMINAL_CODES.has(code) };
|
|
3001
|
+
}
|
|
3002
|
+
function siweContext() {
|
|
3003
|
+
if (typeof window === "undefined") return { domain: "", uri: "" };
|
|
3004
|
+
return { domain: window.location.host, uri: window.location.origin };
|
|
3005
|
+
}
|
|
3006
|
+
function apiErrorCode(error) {
|
|
3007
|
+
if (typeof error !== "object" || error === null) return void 0;
|
|
3008
|
+
const body = error.response?.body;
|
|
3009
|
+
return typeof body?.code === "string" ? body.code : void 0;
|
|
3010
|
+
}
|
|
3011
|
+
function classifyApiError(error) {
|
|
3012
|
+
if (error instanceof NotAuthenticatedError) {
|
|
3013
|
+
return flowError("not_authenticated");
|
|
3014
|
+
}
|
|
3015
|
+
const code = apiErrorCode(error);
|
|
3016
|
+
if (code !== void 0 && API_ERROR_CODES.has(code)) {
|
|
3017
|
+
return flowError(code);
|
|
3018
|
+
}
|
|
3019
|
+
return flowError("unknown");
|
|
3020
|
+
}
|
|
3021
|
+
function challengeParams(wallet, challengeType, statement) {
|
|
3022
|
+
switch (challengeType) {
|
|
3023
|
+
case "siwe":
|
|
3024
|
+
return {
|
|
3025
|
+
walletAddress: wallet.address,
|
|
3026
|
+
chain: wallet.chain,
|
|
3027
|
+
challengeType: "siwe",
|
|
3028
|
+
...siweContext(),
|
|
3029
|
+
statement: statement ?? DEFAULT_STATEMENT
|
|
3030
|
+
};
|
|
3031
|
+
case "plain":
|
|
3032
|
+
return {
|
|
3033
|
+
walletAddress: wallet.address,
|
|
3034
|
+
chain: wallet.chain,
|
|
3035
|
+
challengeType: "plain"
|
|
3036
|
+
};
|
|
3037
|
+
default: {
|
|
3038
|
+
const _exhaustive = challengeType;
|
|
3039
|
+
return _exhaustive;
|
|
3040
|
+
}
|
|
3041
|
+
}
|
|
3042
|
+
}
|
|
3043
|
+
async function connectExternalWalletFlow(params) {
|
|
3044
|
+
const {
|
|
3045
|
+
coinlist,
|
|
3046
|
+
wallet,
|
|
3047
|
+
offerId,
|
|
3048
|
+
offerOptionId,
|
|
3049
|
+
challengeType,
|
|
3050
|
+
statement,
|
|
3051
|
+
isCancelled,
|
|
3052
|
+
onProgress
|
|
3053
|
+
} = params;
|
|
3054
|
+
const emit = (phase) => onProgress?.(phase);
|
|
3055
|
+
const cancelled = () => isCancelled?.() ?? false;
|
|
3056
|
+
emit("requesting-challenge");
|
|
3057
|
+
let challenge;
|
|
3058
|
+
try {
|
|
3059
|
+
challenge = await coinlist.createWalletOwnershipChallenge(
|
|
3060
|
+
challengeParams(wallet, challengeType ?? "siwe", statement)
|
|
3061
|
+
);
|
|
3062
|
+
} catch (error) {
|
|
3063
|
+
return { type: "error", error: classifyApiError(error) };
|
|
3064
|
+
}
|
|
3065
|
+
if (cancelled()) return { type: "cancelled" };
|
|
3066
|
+
emit("signing-message");
|
|
3067
|
+
let signature;
|
|
3068
|
+
try {
|
|
3069
|
+
signature = await wallet.signMessage(challenge.message);
|
|
3070
|
+
} catch (error) {
|
|
3071
|
+
if (classifyWalletError(error).type === "user_rejected") {
|
|
3072
|
+
return { type: "error", error: flowError("user_rejected") };
|
|
3073
|
+
}
|
|
3074
|
+
return { type: "error", error: flowError("unknown") };
|
|
3075
|
+
}
|
|
3076
|
+
if (cancelled()) return { type: "cancelled" };
|
|
3077
|
+
emit("submitting-signature");
|
|
3078
|
+
try {
|
|
3079
|
+
const binding = await coinlist.connectExternalWallet(offerId, {
|
|
3080
|
+
offerOptionId,
|
|
3081
|
+
walletAddress: wallet.address,
|
|
3082
|
+
chain: wallet.chain,
|
|
3083
|
+
signature
|
|
3084
|
+
});
|
|
3085
|
+
return { type: "success", binding };
|
|
3086
|
+
} catch (error) {
|
|
3087
|
+
return { type: "error", error: classifyApiError(error) };
|
|
3088
|
+
}
|
|
3089
|
+
}
|
|
3090
|
+
|
|
3091
|
+
// src/client/hooks/useConnectWallet.ts
|
|
3092
|
+
var IDLE_SIGN = { type: "idle", error: null };
|
|
3093
|
+
var ERROR_COPY = {
|
|
3094
|
+
not_authenticated: "Sign in to connect your wallet.",
|
|
3095
|
+
user_rejected: "Signature request declined. Approve it in your wallet to continue.",
|
|
3096
|
+
wallet_not_whitelisted: "This wallet is not approved for this offer.",
|
|
3097
|
+
max_wallets_reached: "You've reached the maximum number of wallets for this option.",
|
|
3098
|
+
unknown: "Unable to connect your wallet. Please try again."
|
|
3099
|
+
};
|
|
3100
|
+
function displayError(error) {
|
|
3101
|
+
return {
|
|
3102
|
+
code: error.code,
|
|
3103
|
+
message: ERROR_COPY[error.code],
|
|
3104
|
+
retryable: error.retryable
|
|
3105
|
+
};
|
|
3106
|
+
}
|
|
3107
|
+
function useConnectWallet({
|
|
3108
|
+
isOpen,
|
|
3109
|
+
offerId,
|
|
3110
|
+
offerOptionId,
|
|
3111
|
+
wallet,
|
|
3112
|
+
challengeType,
|
|
3113
|
+
statement
|
|
3114
|
+
}) {
|
|
3115
|
+
const { coinlist } = useCoinList();
|
|
3116
|
+
const [state, setState] = (0, import_react7.useState)(
|
|
3117
|
+
() => wallet ? { type: "READY", address: wallet.address, sign: IDLE_SIGN } : { type: "NEEDS_WALLET" }
|
|
3118
|
+
);
|
|
3119
|
+
const attempt = (0, import_react7.useRef)(0);
|
|
3120
|
+
(0, import_react7.useEffect)(() => {
|
|
3121
|
+
attempt.current += 1;
|
|
3122
|
+
if (!isOpen) return;
|
|
3123
|
+
setState(
|
|
3124
|
+
wallet ? { type: "READY", address: wallet.address, sign: IDLE_SIGN } : { type: "NEEDS_WALLET" }
|
|
3125
|
+
);
|
|
3126
|
+
}, [isOpen, wallet?.address]);
|
|
3127
|
+
(0, import_react7.useEffect)(
|
|
3128
|
+
() => () => {
|
|
3129
|
+
attempt.current += 1;
|
|
3130
|
+
},
|
|
3131
|
+
[]
|
|
3132
|
+
);
|
|
3133
|
+
const onSign = (0, import_react7.useCallback)(() => {
|
|
3134
|
+
if (!wallet || state.type !== "READY") return;
|
|
3135
|
+
attempt.current += 1;
|
|
3136
|
+
const gen = attempt.current;
|
|
3137
|
+
setState({
|
|
3138
|
+
type: "READY",
|
|
3139
|
+
address: wallet.address,
|
|
3140
|
+
sign: { type: "signing" }
|
|
3141
|
+
});
|
|
3142
|
+
connectExternalWalletFlow({
|
|
3143
|
+
coinlist,
|
|
3144
|
+
wallet,
|
|
3145
|
+
offerId,
|
|
3146
|
+
offerOptionId,
|
|
3147
|
+
challengeType,
|
|
3148
|
+
statement,
|
|
3149
|
+
// Cancels the flow before signing / binding if this attempt is superseded.
|
|
3150
|
+
isCancelled: () => attempt.current !== gen
|
|
3151
|
+
}).then((result) => {
|
|
3152
|
+
if (attempt.current !== gen) return;
|
|
3153
|
+
if (result.type === "success") {
|
|
3154
|
+
setState({ type: "CONNECTED", binding: result.binding });
|
|
3155
|
+
} else if (result.type === "error") {
|
|
3156
|
+
setState({
|
|
3157
|
+
type: "READY",
|
|
3158
|
+
address: wallet.address,
|
|
3159
|
+
sign: { type: "idle", error: displayError(result.error) }
|
|
3160
|
+
});
|
|
3161
|
+
}
|
|
3162
|
+
});
|
|
3163
|
+
}, [
|
|
3164
|
+
wallet,
|
|
3165
|
+
state,
|
|
3166
|
+
coinlist,
|
|
3167
|
+
offerId,
|
|
3168
|
+
offerOptionId,
|
|
3169
|
+
challengeType,
|
|
3170
|
+
statement
|
|
3171
|
+
]);
|
|
3172
|
+
return { state, onSign };
|
|
3173
|
+
}
|
|
3174
|
+
|
|
3175
|
+
// src/shared/core/blockchain/formatters.ts
|
|
3176
|
+
var import_viem3 = require("viem");
|
|
3177
|
+
|
|
3178
|
+
// src/shared/types/blockchain/ui.ts
|
|
3179
|
+
var ShortenedWalletAddress = (value) => value;
|
|
3180
|
+
var FormattedAmountAssetUi = (value) => value;
|
|
3181
|
+
|
|
3182
|
+
// src/shared/core/blockchain/formatters.ts
|
|
3183
|
+
function shortenAddress(address) {
|
|
3184
|
+
const short = address.length > 10 ? `${address.slice(0, 6)}\u2026${address.slice(-4)}` : address;
|
|
3185
|
+
return ShortenedWalletAddress(short);
|
|
3186
|
+
}
|
|
3187
|
+
var NA_AMOUNT_ASSET_UI = FormattedAmountAssetUi("-");
|
|
3188
|
+
var USD_FRACTION_DIGITS = AssetDecimals(2);
|
|
3189
|
+
|
|
3190
|
+
// src/client/components/requirements/ConnectWalletModal.tsx
|
|
3191
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
3192
|
+
function ConnectWalletModal({
|
|
3193
|
+
isOpen,
|
|
3194
|
+
onClose,
|
|
3195
|
+
offerId,
|
|
3196
|
+
optionId,
|
|
3197
|
+
wallet,
|
|
3198
|
+
onConnected,
|
|
3199
|
+
onRequestConnect,
|
|
3200
|
+
challengeType,
|
|
3201
|
+
statement,
|
|
3202
|
+
className
|
|
3203
|
+
}) {
|
|
3204
|
+
const { state, onSign } = useConnectWallet({
|
|
3205
|
+
isOpen,
|
|
3206
|
+
offerId,
|
|
3207
|
+
offerOptionId: optionId,
|
|
3208
|
+
wallet,
|
|
3209
|
+
challengeType,
|
|
3210
|
+
statement
|
|
3211
|
+
});
|
|
3212
|
+
const titleId = (0, import_react8.useId)();
|
|
3213
|
+
(0, import_react8.useEffect)(() => {
|
|
3214
|
+
if (state.type === "CONNECTED") {
|
|
3215
|
+
onConnected?.(state.binding);
|
|
3216
|
+
onClose();
|
|
3217
|
+
}
|
|
3218
|
+
}, [state]);
|
|
3219
|
+
if (!isOpen || state.type === "CONNECTED") return null;
|
|
3220
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "clcosdk:fixed clcosdk:inset-0 clcosdk:z-50 clcosdk:flex clcosdk:items-center clcosdk:justify-center clcosdk:bg-black/50 clcosdk:p-4", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
3221
|
+
"div",
|
|
3222
|
+
{
|
|
3223
|
+
role: "dialog",
|
|
3224
|
+
"aria-modal": "true",
|
|
3225
|
+
"aria-labelledby": titleId,
|
|
3226
|
+
className: cn(
|
|
3227
|
+
"clcosdk:flex clcosdk:w-full clcosdk:max-w-md clcosdk:flex-col clcosdk:gap-6 clcosdk:rounded-2xl clcosdk:bg-background clcosdk:p-6",
|
|
3228
|
+
className
|
|
3229
|
+
),
|
|
3230
|
+
children: [
|
|
3231
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "clcosdk:flex clcosdk:items-start clcosdk:justify-between clcosdk:gap-4", children: [
|
|
3232
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
3233
|
+
"h3",
|
|
3234
|
+
{
|
|
3235
|
+
id: titleId,
|
|
3236
|
+
className: cn(typeClasses.h3, "clcosdk:text-text-primary"),
|
|
3237
|
+
children: "Connect your wallet"
|
|
3238
|
+
}
|
|
3239
|
+
),
|
|
3240
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(CloseButton, { onClick: onClose })
|
|
3241
|
+
] }),
|
|
3242
|
+
state.type === "NEEDS_WALLET" && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(NeedsWalletScreen, { onRequestConnect }),
|
|
3243
|
+
state.type === "READY" && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
3244
|
+
ReadyScreen,
|
|
3245
|
+
{
|
|
3246
|
+
address: state.address,
|
|
3247
|
+
sign: state.sign,
|
|
3248
|
+
onSign,
|
|
3249
|
+
onRequestConnect
|
|
3250
|
+
}
|
|
3251
|
+
)
|
|
3252
|
+
]
|
|
3253
|
+
}
|
|
3254
|
+
) });
|
|
3255
|
+
}
|
|
3256
|
+
function NeedsWalletScreen({
|
|
3257
|
+
onRequestConnect
|
|
3258
|
+
}) {
|
|
3259
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-6", children: [
|
|
3260
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: cn(typeClasses.body, "clcosdk:text-text-secondary"), children: "Connect an external wallet to prove ownership and bind it to this offer." }),
|
|
3261
|
+
onRequestConnect && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ClButton, { fullWidth: true, onClick: onRequestConnect, children: "Connect wallet" })
|
|
3262
|
+
] });
|
|
3263
|
+
}
|
|
3264
|
+
function ReadyScreen({
|
|
3265
|
+
address,
|
|
3266
|
+
sign,
|
|
3267
|
+
onSign,
|
|
3268
|
+
onRequestConnect
|
|
3269
|
+
}) {
|
|
3270
|
+
const hasTerminalError = sign.type === "idle" && sign.error !== null && !sign.error.retryable;
|
|
3271
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-6", children: [
|
|
3272
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: cn(typeClasses.body, "clcosdk:text-text-secondary"), children: "Sign a message with your connected wallet to prove you own it. This does not cost gas or move any funds." }),
|
|
3273
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-1 clcosdk:border-t clcosdk:border-divider clcosdk:pt-4", children: [
|
|
3274
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: cn(typeClasses.label, "clcosdk:text-text-secondary"), children: "Wallet address" }),
|
|
3275
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: cn(typeClasses.body, "clcosdk:text-text-primary"), children: shortenAddress(address) })
|
|
3276
|
+
] }),
|
|
3277
|
+
sign.type === "idle" && sign.error && // Live region: the error is inserted async after a failed attempt, so
|
|
3278
|
+
// screen readers need it announced rather than silently rendered.
|
|
3279
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { role: "alert", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(AlertBanner, { variant: "error", icon: true, content: sign.error.message }) }),
|
|
3280
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
3281
|
+
ClButton,
|
|
3282
|
+
{
|
|
3283
|
+
fullWidth: true,
|
|
3284
|
+
onClick: onSign,
|
|
3285
|
+
isLoading: sign.type === "signing",
|
|
3286
|
+
loadingText: "Waiting for signature...",
|
|
3287
|
+
disabled: hasTerminalError,
|
|
3288
|
+
children: "Sign & connect"
|
|
3289
|
+
}
|
|
3290
|
+
),
|
|
3291
|
+
onRequestConnect && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
3292
|
+
ClButton,
|
|
3293
|
+
{
|
|
3294
|
+
fullWidth: true,
|
|
3295
|
+
variant: "secondary",
|
|
3296
|
+
onClick: onRequestConnect,
|
|
3297
|
+
disabled: sign.type === "signing",
|
|
3298
|
+
children: "Use a different wallet"
|
|
3299
|
+
}
|
|
3300
|
+
)
|
|
3301
|
+
] });
|
|
3302
|
+
}
|
|
3303
|
+
|
|
3304
|
+
// src/client/components/requirements/IdentityVerification.tsx
|
|
3305
|
+
var import_websdk_react = __toESM(require("@sumsub/websdk-react"), 1);
|
|
3306
|
+
var import_react10 = require("react");
|
|
3307
|
+
|
|
3308
|
+
// src/client/hooks/useKycToken.ts
|
|
3309
|
+
var import_react9 = require("react");
|
|
3310
|
+
var IDLE_STATE = { type: "IDLE" };
|
|
3311
|
+
var LOADING_STATE2 = { type: "LOADING" };
|
|
3312
|
+
function useKycToken(levelName, reset) {
|
|
3313
|
+
const { coinlist } = useCoinList();
|
|
3314
|
+
const [kycTokenState, setKycTokenState] = (0, import_react9.useState)(IDLE_STATE);
|
|
3315
|
+
const resetPendingRef = (0, import_react9.useRef)(reset === true);
|
|
3316
|
+
const tokenIssuedRef = (0, import_react9.useRef)(false);
|
|
3317
|
+
(0, import_react9.useEffect)(() => {
|
|
3318
|
+
if (!tokenIssuedRef.current) {
|
|
3319
|
+
resetPendingRef.current = reset === true;
|
|
3320
|
+
}
|
|
3321
|
+
}, [reset]);
|
|
3322
|
+
const fetchToken = (0, import_react9.useCallback)(async () => {
|
|
3323
|
+
setKycTokenState(LOADING_STATE2);
|
|
3324
|
+
try {
|
|
3325
|
+
const kycToken = await coinlist.createKycToken(
|
|
3326
|
+
levelName,
|
|
3327
|
+
resetPendingRef.current
|
|
3328
|
+
);
|
|
3329
|
+
resetPendingRef.current = false;
|
|
3330
|
+
tokenIssuedRef.current = true;
|
|
3331
|
+
setKycTokenState({ type: "CONTENT", token: kycToken.token });
|
|
3332
|
+
return kycToken.token;
|
|
3333
|
+
} catch (error) {
|
|
3334
|
+
const reason = error instanceof NotAuthenticatedError ? "not-authenticated" : "generic-error";
|
|
3335
|
+
setKycTokenState({ type: "ERROR", reason });
|
|
3336
|
+
throw error;
|
|
3337
|
+
}
|
|
3338
|
+
}, [coinlist, levelName]);
|
|
3339
|
+
return { kycTokenState, fetchToken };
|
|
3340
|
+
}
|
|
3341
|
+
|
|
3342
|
+
// src/client/components/requirements/IdentityVerification.tsx
|
|
3343
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
3344
|
+
function IdentityVerification({
|
|
3345
|
+
levelName,
|
|
3346
|
+
reset,
|
|
3347
|
+
locale,
|
|
3348
|
+
onSubmitted,
|
|
3349
|
+
onError,
|
|
3350
|
+
className
|
|
3351
|
+
}) {
|
|
3352
|
+
const { kycTokenState, fetchToken } = useKycToken(levelName, reset);
|
|
3353
|
+
const fetchedRef = (0, import_react10.useRef)(false);
|
|
3354
|
+
(0, import_react10.useEffect)(() => {
|
|
3355
|
+
if (fetchedRef.current) return;
|
|
3356
|
+
fetchedRef.current = true;
|
|
3357
|
+
fetchToken().catch(() => {
|
|
3358
|
+
});
|
|
3359
|
+
}, [fetchToken]);
|
|
3360
|
+
const handleMessage = (type, payload) => {
|
|
3361
|
+
switch (type) {
|
|
3362
|
+
case "idCheck.onApplicantSubmitted":
|
|
3363
|
+
onSubmitted?.();
|
|
3364
|
+
break;
|
|
3365
|
+
case "idCheck.onError": {
|
|
3366
|
+
const message = payload?.message ?? "Verification error";
|
|
3367
|
+
onError?.(new Error(message));
|
|
3368
|
+
break;
|
|
3369
|
+
}
|
|
3370
|
+
default:
|
|
3371
|
+
break;
|
|
3372
|
+
}
|
|
3373
|
+
};
|
|
3374
|
+
const handleError = (error) => {
|
|
3375
|
+
onError?.(error instanceof Error ? error : new Error("Verification error"));
|
|
3376
|
+
};
|
|
3377
|
+
if (kycTokenState.type === "IDLE" || kycTokenState.type === "LOADING") {
|
|
3378
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
3379
|
+
"output",
|
|
3380
|
+
{
|
|
3381
|
+
"aria-live": "polite",
|
|
3382
|
+
className: cn(
|
|
3383
|
+
"clcosdk:flex clcosdk:min-h-40 clcosdk:items-center clcosdk:justify-center",
|
|
3384
|
+
className
|
|
3385
|
+
),
|
|
3386
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: cn(typeClasses.body, "clcosdk:text-text-secondary"), children: "Loading identity verification..." })
|
|
3387
|
+
}
|
|
3388
|
+
);
|
|
3389
|
+
}
|
|
3390
|
+
if (kycTokenState.type === "ERROR") {
|
|
3391
|
+
const errorMessage = kycTokenState.reason === "not-authenticated" ? "Sign in to verify your identity." : "Unable to start identity verification right now. Please try again.";
|
|
3392
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
3393
|
+
"div",
|
|
3394
|
+
{
|
|
3395
|
+
className: cn("clcosdk:flex clcosdk:flex-col clcosdk:gap-4", className),
|
|
3396
|
+
children: [
|
|
3397
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(AlertBanner, { variant: "error", icon: true, content: errorMessage }),
|
|
3398
|
+
kycTokenState.reason !== "not-authenticated" && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
3399
|
+
ClButton,
|
|
3400
|
+
{
|
|
3401
|
+
size: "sm",
|
|
3402
|
+
onClick: () => {
|
|
3403
|
+
fetchToken().catch(() => {
|
|
3404
|
+
});
|
|
3405
|
+
},
|
|
3406
|
+
children: "Try again"
|
|
3407
|
+
}
|
|
3408
|
+
)
|
|
3409
|
+
]
|
|
3410
|
+
}
|
|
3411
|
+
);
|
|
3412
|
+
}
|
|
3413
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: cn("clcosdk:w-full", className), children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
3414
|
+
import_websdk_react.default,
|
|
3415
|
+
{
|
|
3416
|
+
accessToken: kycTokenState.token,
|
|
3417
|
+
expirationHandler: fetchToken,
|
|
3418
|
+
config: locale === void 0 ? {} : { lang: locale },
|
|
3419
|
+
options: { addViewportTag: false, adaptIframeHeight: true },
|
|
3420
|
+
onMessage: handleMessage,
|
|
3421
|
+
onError: handleError
|
|
3422
|
+
}
|
|
3423
|
+
) });
|
|
3424
|
+
}
|
|
1717
3425
|
|
|
1718
3426
|
// src/client/components/requirements/RequirementItem.tsx
|
|
1719
3427
|
var import_lucide_react4 = require("lucide-react");
|
|
1720
3428
|
|
|
1721
3429
|
// src/client/components/design-system/StepStatusIcon.tsx
|
|
1722
3430
|
var import_lucide_react3 = require("lucide-react");
|
|
1723
|
-
var
|
|
3431
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
1724
3432
|
var statusConfig = {
|
|
1725
3433
|
required: {
|
|
1726
3434
|
Icon: import_lucide_react3.Info,
|
|
@@ -1745,7 +3453,7 @@ var statusConfig = {
|
|
|
1745
3453
|
};
|
|
1746
3454
|
function StepStatusIcon({ status, className }) {
|
|
1747
3455
|
const { Icon, colorClass, fillClass } = statusConfig[status];
|
|
1748
|
-
return /* @__PURE__ */ (0,
|
|
3456
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
1749
3457
|
Icon,
|
|
1750
3458
|
{
|
|
1751
3459
|
className: cn(
|
|
@@ -1760,7 +3468,7 @@ function StepStatusIcon({ status, className }) {
|
|
|
1760
3468
|
}
|
|
1761
3469
|
|
|
1762
3470
|
// src/client/components/requirements/RequirementItem.tsx
|
|
1763
|
-
var
|
|
3471
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
1764
3472
|
var RequirementVariant = {
|
|
1765
3473
|
fromType(type) {
|
|
1766
3474
|
switch (type) {
|
|
@@ -1795,13 +3503,18 @@ var ChecklistStatus = {
|
|
|
1795
3503
|
}
|
|
1796
3504
|
};
|
|
1797
3505
|
var RequirementItemUi = {
|
|
1798
|
-
fromDomain(req, statusInfo, label, description,
|
|
3506
|
+
fromDomain(req, statusInfo, label, description, addresses = []) {
|
|
1799
3507
|
return {
|
|
1800
3508
|
variant: RequirementVariant.fromType(req.type),
|
|
1801
3509
|
status: statusInfo ? RequirementStatus.fromStatusValue(statusInfo.status) : "required",
|
|
1802
3510
|
label,
|
|
1803
3511
|
description,
|
|
1804
|
-
|
|
3512
|
+
multiWallet: req.type === "whitelisted_wallet",
|
|
3513
|
+
connectedWallets: addresses.map((address) => ({
|
|
3514
|
+
id: address.id,
|
|
3515
|
+
address: address.address,
|
|
3516
|
+
shortAddress: shortenAddress(address.address)
|
|
3517
|
+
}))
|
|
1805
3518
|
};
|
|
1806
3519
|
}
|
|
1807
3520
|
};
|
|
@@ -1813,9 +3526,9 @@ function VerificationActionZone({
|
|
|
1813
3526
|
switch (status) {
|
|
1814
3527
|
case "required":
|
|
1815
3528
|
if (onAction === null) return null;
|
|
1816
|
-
return /* @__PURE__ */ (0,
|
|
3529
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(ClButton, { size: "sm", onClick: onAction, children: "Continue" });
|
|
1817
3530
|
case "pending":
|
|
1818
|
-
return /* @__PURE__ */ (0,
|
|
3531
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
1819
3532
|
AlertBanner,
|
|
1820
3533
|
{
|
|
1821
3534
|
variant: "warning",
|
|
@@ -1823,16 +3536,16 @@ function VerificationActionZone({
|
|
|
1823
3536
|
}
|
|
1824
3537
|
);
|
|
1825
3538
|
case "completed":
|
|
1826
|
-
return /* @__PURE__ */ (0,
|
|
3539
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(AlertBanner, { variant: "success", content: "Identity verified." });
|
|
1827
3540
|
case "rejected":
|
|
1828
|
-
return /* @__PURE__ */ (0,
|
|
3541
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
1829
3542
|
AlertBanner,
|
|
1830
3543
|
{
|
|
1831
3544
|
variant: "error",
|
|
1832
|
-
content: onContactSupport === null ? "Verification rejected." : /* @__PURE__ */ (0,
|
|
3545
|
+
content: onContactSupport === null ? "Verification rejected." : /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
|
|
1833
3546
|
"Verification rejected.",
|
|
1834
3547
|
" ",
|
|
1835
|
-
/* @__PURE__ */ (0,
|
|
3548
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
1836
3549
|
"button",
|
|
1837
3550
|
{
|
|
1838
3551
|
type: "button",
|
|
@@ -1849,25 +3562,61 @@ function VerificationActionZone({
|
|
|
1849
3562
|
}
|
|
1850
3563
|
function WalletActionZone({
|
|
1851
3564
|
status,
|
|
1852
|
-
|
|
1853
|
-
|
|
3565
|
+
multiWallet,
|
|
3566
|
+
connectedWallets,
|
|
3567
|
+
walletsStatus,
|
|
3568
|
+
onAction,
|
|
3569
|
+
onRemoveWallet
|
|
1854
3570
|
}) {
|
|
3571
|
+
if (multiWallet) {
|
|
3572
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
|
|
3573
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3574
|
+
ConnectedWalletList,
|
|
3575
|
+
{
|
|
3576
|
+
wallets: connectedWallets,
|
|
3577
|
+
onRemove: onRemoveWallet,
|
|
3578
|
+
onAdd: onAction ?? void 0,
|
|
3579
|
+
status: walletsStatus
|
|
3580
|
+
}
|
|
3581
|
+
),
|
|
3582
|
+
status === "rejected" && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3583
|
+
AlertBanner,
|
|
3584
|
+
{
|
|
3585
|
+
variant: "error",
|
|
3586
|
+
content: "One of these wallets is not eligible for this sale."
|
|
3587
|
+
}
|
|
3588
|
+
)
|
|
3589
|
+
] });
|
|
3590
|
+
}
|
|
1855
3591
|
if (status === "completed") {
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
/* @__PURE__ */ (0,
|
|
3592
|
+
const connected = connectedWallets[0];
|
|
3593
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
|
|
3594
|
+
onAction !== null && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(ClButton, { size: "sm", variant: "secondary", onClick: onAction, children: "Change wallet" }),
|
|
3595
|
+
walletsStatus === "loading" ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3596
|
+
AlertBanner,
|
|
3597
|
+
{
|
|
3598
|
+
variant: "info",
|
|
3599
|
+
content: "Loading your connected wallet\u2026"
|
|
3600
|
+
}
|
|
3601
|
+
) : walletsStatus === "error" ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3602
|
+
AlertBanner,
|
|
3603
|
+
{
|
|
3604
|
+
variant: "error",
|
|
3605
|
+
content: "Couldn't load your connected wallet."
|
|
3606
|
+
}
|
|
3607
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
1859
3608
|
AlertBanner,
|
|
1860
3609
|
{
|
|
1861
3610
|
variant: "success",
|
|
1862
|
-
content:
|
|
3611
|
+
content: connected ? connected.shortAddress : "Wallet connected."
|
|
1863
3612
|
}
|
|
1864
3613
|
)
|
|
1865
3614
|
] });
|
|
1866
3615
|
}
|
|
1867
3616
|
if (status === "rejected") {
|
|
1868
|
-
return /* @__PURE__ */ (0,
|
|
1869
|
-
onAction !== null && /* @__PURE__ */ (0,
|
|
1870
|
-
/* @__PURE__ */ (0,
|
|
3617
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
|
|
3618
|
+
onAction !== null && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(ClButton, { size: "sm", onClick: onAction, children: "Connect wallet" }),
|
|
3619
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
1871
3620
|
AlertBanner,
|
|
1872
3621
|
{
|
|
1873
3622
|
variant: "error",
|
|
@@ -1877,7 +3626,7 @@ function WalletActionZone({
|
|
|
1877
3626
|
] });
|
|
1878
3627
|
}
|
|
1879
3628
|
if (onAction === null) return null;
|
|
1880
|
-
return /* @__PURE__ */ (0,
|
|
3629
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(ClButton, { size: "sm", onClick: onAction, children: "Connect wallet" });
|
|
1881
3630
|
}
|
|
1882
3631
|
function RequirementItem({
|
|
1883
3632
|
ui,
|
|
@@ -1885,14 +3634,19 @@ function RequirementItem({
|
|
|
1885
3634
|
onToggle,
|
|
1886
3635
|
className,
|
|
1887
3636
|
onAction,
|
|
3637
|
+
onRemoveWallet,
|
|
3638
|
+
walletsStatus,
|
|
1888
3639
|
onContactSupport
|
|
1889
3640
|
}) {
|
|
1890
|
-
return /* @__PURE__ */ (0,
|
|
3641
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(CoinListStyleScope, { children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
1891
3642
|
"div",
|
|
1892
3643
|
{
|
|
1893
|
-
className: cn(
|
|
3644
|
+
className: cn(
|
|
3645
|
+
"clcosdk:flex clcosdk:w-full clcosdk:flex-col",
|
|
3646
|
+
className
|
|
3647
|
+
),
|
|
1894
3648
|
children: [
|
|
1895
|
-
/* @__PURE__ */ (0,
|
|
3649
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
1896
3650
|
"button",
|
|
1897
3651
|
{
|
|
1898
3652
|
type: "button",
|
|
@@ -1900,9 +3654,9 @@ function RequirementItem({
|
|
|
1900
3654
|
"aria-expanded": expanded,
|
|
1901
3655
|
className: "clcosdk:flex clcosdk:h-14 clcosdk:w-full clcosdk:cursor-pointer clcosdk:items-center clcosdk:justify-between clcosdk:rounded-2xl clcosdk:px-2 clcosdk:transition-colors clcosdk:hover:bg-surface",
|
|
1902
3656
|
children: [
|
|
1903
|
-
/* @__PURE__ */ (0,
|
|
1904
|
-
/* @__PURE__ */ (0,
|
|
1905
|
-
/* @__PURE__ */ (0,
|
|
3657
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "clcosdk:flex clcosdk:items-center clcosdk:gap-3", children: [
|
|
3658
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(StepStatusIcon, { status: ui.status }),
|
|
3659
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
1906
3660
|
"span",
|
|
1907
3661
|
{
|
|
1908
3662
|
className: cn(
|
|
@@ -1913,7 +3667,7 @@ function RequirementItem({
|
|
|
1913
3667
|
}
|
|
1914
3668
|
)
|
|
1915
3669
|
] }),
|
|
1916
|
-
/* @__PURE__ */ (0,
|
|
3670
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
1917
3671
|
import_lucide_react4.ChevronRight,
|
|
1918
3672
|
{
|
|
1919
3673
|
className: cn(
|
|
@@ -1926,34 +3680,40 @@ function RequirementItem({
|
|
|
1926
3680
|
]
|
|
1927
3681
|
}
|
|
1928
3682
|
),
|
|
1929
|
-
/* @__PURE__ */ (0,
|
|
3683
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
1930
3684
|
"div",
|
|
1931
3685
|
{
|
|
1932
3686
|
className: cn(
|
|
1933
3687
|
"clcosdk:grid clcosdk:transition-[grid-template-rows] clcosdk:duration-300 clcosdk:ease-in-out",
|
|
1934
3688
|
expanded ? "clcosdk:grid-rows-[1fr]" : "clcosdk:grid-rows-[0fr]"
|
|
1935
3689
|
),
|
|
1936
|
-
children: /* @__PURE__ */ (0,
|
|
1937
|
-
/* @__PURE__ */ (0,
|
|
3690
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "clcosdk:min-h-0 clcosdk:overflow-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-4 clcosdk:px-2 clcosdk:pb-4", children: [
|
|
3691
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
1938
3692
|
"p",
|
|
1939
3693
|
{
|
|
1940
|
-
className: cn(
|
|
3694
|
+
className: cn(
|
|
3695
|
+
typeClasses.subhead,
|
|
3696
|
+
"clcosdk:text-text-secondary"
|
|
3697
|
+
),
|
|
1941
3698
|
children: ui.description
|
|
1942
3699
|
}
|
|
1943
3700
|
),
|
|
1944
|
-
ui.variant === "verification" ? /* @__PURE__ */ (0,
|
|
3701
|
+
ui.variant === "verification" ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
1945
3702
|
VerificationActionZone,
|
|
1946
3703
|
{
|
|
1947
3704
|
status: ui.status,
|
|
1948
3705
|
onAction,
|
|
1949
3706
|
onContactSupport
|
|
1950
3707
|
}
|
|
1951
|
-
) : /* @__PURE__ */ (0,
|
|
3708
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
1952
3709
|
WalletActionZone,
|
|
1953
3710
|
{
|
|
1954
3711
|
status: ui.status,
|
|
1955
|
-
|
|
1956
|
-
|
|
3712
|
+
multiWallet: ui.multiWallet,
|
|
3713
|
+
connectedWallets: ui.connectedWallets,
|
|
3714
|
+
walletsStatus,
|
|
3715
|
+
onAction,
|
|
3716
|
+
onRemoveWallet
|
|
1957
3717
|
}
|
|
1958
3718
|
)
|
|
1959
3719
|
] }) })
|
|
@@ -1961,31 +3721,504 @@ function RequirementItem({
|
|
|
1961
3721
|
)
|
|
1962
3722
|
]
|
|
1963
3723
|
}
|
|
1964
|
-
);
|
|
3724
|
+
) });
|
|
1965
3725
|
}
|
|
1966
3726
|
|
|
1967
3727
|
// src/client/components/requirements/RequirementsChecklist.tsx
|
|
1968
|
-
var
|
|
3728
|
+
var import_react15 = require("react");
|
|
1969
3729
|
|
|
1970
|
-
// src/client/
|
|
1971
|
-
var
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
3730
|
+
// src/client/components/requirements/TaxDocumentModal.tsx
|
|
3731
|
+
var import_react12 = require("react");
|
|
3732
|
+
|
|
3733
|
+
// src/client/hooks/useTaxDocument.ts
|
|
3734
|
+
var import_react11 = require("react");
|
|
3735
|
+
var IDLE_SIGN2 = { type: "idle", error: null };
|
|
3736
|
+
var LOADING_STATE3 = { type: "LOADING" };
|
|
3737
|
+
var SIGN_FAILED_MESSAGE = "Unable to sign document. Please try again.";
|
|
3738
|
+
var DOB_INVALID_MESSAGE = "Enter your date of birth as MM/DD/YYYY.";
|
|
3739
|
+
var FIELD_KEYS = {
|
|
3740
|
+
fullLegalName: "Full Name",
|
|
3741
|
+
dob: "DOB",
|
|
3742
|
+
countryOfCitizenship: "Country Of Citizenship",
|
|
3743
|
+
taxId: "Foreign Tax Number",
|
|
3744
|
+
permanentAddress: "Permanent Address"
|
|
3745
|
+
};
|
|
3746
|
+
function formatUsDate(date) {
|
|
3747
|
+
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
3748
|
+
const day = String(date.getDate()).padStart(2, "0");
|
|
3749
|
+
const year = String(date.getFullYear()).padStart(4, "0");
|
|
3750
|
+
return `${month}/${day}/${year}`;
|
|
3751
|
+
}
|
|
3752
|
+
function formatIsoDateOnly(isoDate) {
|
|
3753
|
+
const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(isoDate);
|
|
3754
|
+
if (!match) return "";
|
|
3755
|
+
const [, year, month, day] = match;
|
|
3756
|
+
return `${month}/${day}/${year}`;
|
|
3757
|
+
}
|
|
3758
|
+
function isValidUsDate(value) {
|
|
3759
|
+
const match = /^(\d{2})\/(\d{2})\/(\d{4})$/.exec(value);
|
|
3760
|
+
if (!match) return false;
|
|
3761
|
+
const [, mm, dd, yyyy] = match;
|
|
3762
|
+
const month = Number(mm);
|
|
3763
|
+
const day = Number(dd);
|
|
3764
|
+
const year = Number(yyyy);
|
|
3765
|
+
const date = new Date(year, month - 1, day);
|
|
3766
|
+
return date.getFullYear() === year && date.getMonth() === month - 1 && date.getDate() === day;
|
|
3767
|
+
}
|
|
3768
|
+
function mapPiiToFields(pii) {
|
|
3769
|
+
const { street, city, state, postalCode } = pii.permanentAddress;
|
|
3770
|
+
const cityLine = [postalCode, city].filter(Boolean).join(" ");
|
|
3771
|
+
const permanentAddress = [street, cityLine, state].filter(Boolean).join(", ");
|
|
3772
|
+
return {
|
|
3773
|
+
fullLegalName: pii.fullLegalName ?? "",
|
|
3774
|
+
// Date-only ISO from the backend, shown as MM/DD/YYYY. Blank until the
|
|
3775
|
+
// backend has a date of birth (the field is editable in the meantime).
|
|
3776
|
+
dob: formatIsoDateOnly(pii.dateOfBirth ?? ""),
|
|
3777
|
+
countryOfCitizenship: pii.jurisdiction?.name ?? "",
|
|
3778
|
+
taxId: pii.taxId ?? "",
|
|
3779
|
+
permanentAddress
|
|
3780
|
+
};
|
|
3781
|
+
}
|
|
3782
|
+
function addressPartsFromPii(pii) {
|
|
3783
|
+
return {
|
|
3784
|
+
city: pii.permanentAddress.city ?? "",
|
|
3785
|
+
country: pii.permanentAddress.country ?? ""
|
|
3786
|
+
};
|
|
3787
|
+
}
|
|
3788
|
+
function hasAnyFieldValue(fields) {
|
|
3789
|
+
return Object.values(fields).some((value) => value.trim() !== "");
|
|
3790
|
+
}
|
|
3791
|
+
function toSubmissionFields(fields, addressParts) {
|
|
3792
|
+
return {
|
|
3793
|
+
[FIELD_KEYS.fullLegalName]: fields.fullLegalName,
|
|
3794
|
+
[FIELD_KEYS.dob]: fields.dob,
|
|
3795
|
+
[FIELD_KEYS.countryOfCitizenship]: fields.countryOfCitizenship,
|
|
3796
|
+
[FIELD_KEYS.taxId]: fields.taxId,
|
|
3797
|
+
[FIELD_KEYS.permanentAddress]: fields.permanentAddress,
|
|
3798
|
+
City: addressParts.city,
|
|
3799
|
+
Country: addressParts.country,
|
|
3800
|
+
Signature: fields.fullLegalName,
|
|
3801
|
+
Date: formatUsDate(/* @__PURE__ */ new Date())
|
|
3802
|
+
};
|
|
3803
|
+
}
|
|
3804
|
+
function useTaxDocument({
|
|
3805
|
+
isOpen
|
|
3806
|
+
}) {
|
|
3807
|
+
const { coinlist, isReady } = useCoinList();
|
|
3808
|
+
const [state, setState] = (0, import_react11.useState)(LOADING_STATE3);
|
|
3809
|
+
(0, import_react11.useEffect)(() => {
|
|
3810
|
+
let isCancelled = false;
|
|
3811
|
+
if (!isOpen) {
|
|
3812
|
+
return () => {
|
|
3813
|
+
isCancelled = true;
|
|
3814
|
+
};
|
|
3815
|
+
}
|
|
3816
|
+
if (!isReady) {
|
|
3817
|
+
setState(LOADING_STATE3);
|
|
3818
|
+
return () => {
|
|
3819
|
+
isCancelled = true;
|
|
3820
|
+
};
|
|
3821
|
+
}
|
|
3822
|
+
setState(LOADING_STATE3);
|
|
3823
|
+
coinlist.fetchPii().then((pii) => {
|
|
3824
|
+
if (isCancelled) return;
|
|
3825
|
+
if (pii.kind === "company") {
|
|
3826
|
+
setState({ type: "SIGN_ONLY", sign: IDLE_SIGN2 });
|
|
3827
|
+
return;
|
|
3828
|
+
}
|
|
3829
|
+
const fields = mapPiiToFields(pii);
|
|
3830
|
+
setState({
|
|
3831
|
+
type: "REVIEW",
|
|
3832
|
+
fields,
|
|
3833
|
+
addressParts: addressPartsFromPii(pii),
|
|
3834
|
+
piiUnavailable: !hasAnyFieldValue(fields),
|
|
3835
|
+
sign: IDLE_SIGN2
|
|
3836
|
+
});
|
|
3837
|
+
}).catch((error) => {
|
|
3838
|
+
if (isCancelled) return;
|
|
3839
|
+
setState({
|
|
3840
|
+
type: "ERROR",
|
|
3841
|
+
reason: error instanceof NotAuthenticatedError ? "not-authenticated" : "generic-error"
|
|
3842
|
+
});
|
|
3843
|
+
});
|
|
3844
|
+
return () => {
|
|
3845
|
+
isCancelled = true;
|
|
3846
|
+
};
|
|
3847
|
+
}, [coinlist, isReady, isOpen]);
|
|
3848
|
+
const onEditField = (0, import_react11.useCallback)(
|
|
3849
|
+
(field, value) => {
|
|
3850
|
+
setState(
|
|
3851
|
+
(prev) => prev.type === "EDITING" ? { ...prev, fields: { ...prev.fields, [field]: value } } : prev
|
|
3852
|
+
);
|
|
3853
|
+
},
|
|
3854
|
+
[]
|
|
3855
|
+
);
|
|
3856
|
+
const onStartEdit = (0, import_react11.useCallback)(() => {
|
|
3857
|
+
setState(
|
|
3858
|
+
(prev) => prev.type === "REVIEW" ? {
|
|
3859
|
+
type: "EDITING",
|
|
3860
|
+
fields: prev.fields,
|
|
3861
|
+
original: prev.fields,
|
|
3862
|
+
addressParts: prev.addressParts,
|
|
3863
|
+
piiUnavailable: prev.piiUnavailable
|
|
3864
|
+
} : prev
|
|
3865
|
+
);
|
|
3866
|
+
}, []);
|
|
3867
|
+
const onSaveEdit = (0, import_react11.useCallback)(() => {
|
|
3868
|
+
setState(
|
|
3869
|
+
(prev) => prev.type === "EDITING" ? {
|
|
3870
|
+
type: "REVIEW",
|
|
3871
|
+
fields: prev.fields,
|
|
3872
|
+
addressParts: prev.addressParts,
|
|
3873
|
+
piiUnavailable: prev.piiUnavailable,
|
|
3874
|
+
sign: IDLE_SIGN2
|
|
3875
|
+
} : prev
|
|
3876
|
+
);
|
|
3877
|
+
}, []);
|
|
3878
|
+
const onCancelEdit = (0, import_react11.useCallback)(() => {
|
|
3879
|
+
setState(
|
|
3880
|
+
(prev) => prev.type === "EDITING" ? {
|
|
3881
|
+
type: "REVIEW",
|
|
3882
|
+
fields: prev.original,
|
|
3883
|
+
addressParts: prev.addressParts,
|
|
3884
|
+
piiUnavailable: prev.piiUnavailable,
|
|
3885
|
+
sign: IDLE_SIGN2
|
|
3886
|
+
} : prev
|
|
3887
|
+
);
|
|
3888
|
+
}, []);
|
|
3889
|
+
const onSign = (0, import_react11.useCallback)(() => {
|
|
3890
|
+
if (state.type !== "REVIEW" && state.type !== "SIGN_ONLY") return;
|
|
3891
|
+
if (state.type === "REVIEW" && state.fields.dob.trim() !== "" && !isValidUsDate(state.fields.dob)) {
|
|
3892
|
+
setState({
|
|
3893
|
+
...state,
|
|
3894
|
+
sign: { type: "idle", error: DOB_INVALID_MESSAGE }
|
|
3895
|
+
});
|
|
3896
|
+
return;
|
|
3897
|
+
}
|
|
3898
|
+
setState({ ...state, sign: { type: "signing" } });
|
|
3899
|
+
coinlist.submitDocument(
|
|
3900
|
+
"tax_certification",
|
|
3901
|
+
state.type === "REVIEW" ? toSubmissionFields(state.fields, state.addressParts) : {}
|
|
3902
|
+
).then((submission) => {
|
|
3903
|
+
setState({ type: "SUBMITTED", submission });
|
|
3904
|
+
}).catch(() => {
|
|
3905
|
+
setState(
|
|
3906
|
+
(prev) => prev.type === "REVIEW" || prev.type === "SIGN_ONLY" ? { ...prev, sign: { type: "idle", error: SIGN_FAILED_MESSAGE } } : prev
|
|
3907
|
+
);
|
|
3908
|
+
});
|
|
3909
|
+
}, [state, coinlist]);
|
|
3910
|
+
return { state, onEditField, onStartEdit, onSaveEdit, onCancelEdit, onSign };
|
|
3911
|
+
}
|
|
3912
|
+
|
|
3913
|
+
// src/client/components/requirements/TaxDocumentModal.tsx
|
|
3914
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
3915
|
+
var FIELD_ROWS = [
|
|
3916
|
+
{ field: "fullLegalName", label: "Full legal name" },
|
|
3917
|
+
{ field: "dob", label: "Date of birth", placeholder: "MM/DD/YYYY" },
|
|
3918
|
+
{ field: "countryOfCitizenship", label: "Country of citizenship" },
|
|
3919
|
+
{ field: "taxId", label: "Tax ID" },
|
|
3920
|
+
{ field: "permanentAddress", label: "Permanent address" }
|
|
3921
|
+
];
|
|
3922
|
+
function TaxDocumentModal({
|
|
3923
|
+
isOpen,
|
|
3924
|
+
onClose,
|
|
3925
|
+
onSubmitted,
|
|
3926
|
+
className
|
|
3927
|
+
}) {
|
|
3928
|
+
const { state, onEditField, onStartEdit, onSaveEdit, onCancelEdit, onSign } = useTaxDocument({ isOpen });
|
|
3929
|
+
(0, import_react12.useEffect)(() => {
|
|
3930
|
+
if (state.type === "SUBMITTED") {
|
|
3931
|
+
onSubmitted?.(state.submission);
|
|
3932
|
+
onClose();
|
|
3933
|
+
}
|
|
3934
|
+
}, [state]);
|
|
3935
|
+
if (!isOpen || state.type === "SUBMITTED") return null;
|
|
3936
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "clcosdk:fixed clcosdk:inset-0 clcosdk:z-50 clcosdk:flex clcosdk:items-center clcosdk:justify-center clcosdk:bg-black/50 clcosdk:p-4", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
3937
|
+
"div",
|
|
3938
|
+
{
|
|
3939
|
+
className: cn(
|
|
3940
|
+
"clcosdk:flex clcosdk:w-full clcosdk:max-w-md clcosdk:flex-col clcosdk:gap-6 clcosdk:rounded-2xl clcosdk:bg-background clcosdk:p-6",
|
|
3941
|
+
className
|
|
3942
|
+
),
|
|
3943
|
+
children: [
|
|
3944
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "clcosdk:flex clcosdk:items-start clcosdk:justify-between clcosdk:gap-4", children: [
|
|
3945
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(TaxDocumentModalHeading, { state }),
|
|
3946
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(CloseButton, { onClick: onClose })
|
|
3947
|
+
] }),
|
|
3948
|
+
state.type === "LOADING" && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(LoadingScreen, {}),
|
|
3949
|
+
state.type === "ERROR" && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ErrorScreen, { reason: state.reason }),
|
|
3950
|
+
state.type === "REVIEW" && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
3951
|
+
ReviewScreen,
|
|
3952
|
+
{
|
|
3953
|
+
fields: state.fields,
|
|
3954
|
+
piiUnavailable: state.piiUnavailable,
|
|
3955
|
+
sign: state.sign,
|
|
3956
|
+
onStartEdit,
|
|
3957
|
+
onSign
|
|
3958
|
+
}
|
|
3959
|
+
),
|
|
3960
|
+
state.type === "EDITING" && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
3961
|
+
EditScreen,
|
|
3962
|
+
{
|
|
3963
|
+
fields: state.fields,
|
|
3964
|
+
onEditField,
|
|
3965
|
+
onSaveEdit,
|
|
3966
|
+
onCancelEdit
|
|
3967
|
+
}
|
|
3968
|
+
),
|
|
3969
|
+
state.type === "SIGN_ONLY" && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(SignOnlyScreen, { sign: state.sign, onSign })
|
|
3970
|
+
]
|
|
3971
|
+
}
|
|
3972
|
+
) });
|
|
3973
|
+
}
|
|
3974
|
+
function TaxDocumentModalHeading({
|
|
3975
|
+
state
|
|
3976
|
+
}) {
|
|
3977
|
+
const title = state.type === "EDITING" ? "Edit your W-8BEN" : state.type === "REVIEW" ? "Confirm your W-8BEN" : state.type === "SIGN_ONLY" ? "Confirm your W-8BEN-E" : "Tax document";
|
|
3978
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("h3", { className: cn(typeClasses.h3, "clcosdk:text-text-primary"), children: title });
|
|
3979
|
+
}
|
|
3980
|
+
function LoadingScreen() {
|
|
3981
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
3982
|
+
"output",
|
|
3983
|
+
{
|
|
3984
|
+
"aria-live": "polite",
|
|
3985
|
+
className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-4",
|
|
3986
|
+
children: FIELD_ROWS.map(({ field }) => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
3987
|
+
"div",
|
|
3988
|
+
{
|
|
3989
|
+
className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-1",
|
|
3990
|
+
children: [
|
|
3991
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "clcosdk:h-3 clcosdk:w-28 clcosdk:animate-pulse clcosdk:rounded clcosdk:bg-surface" }),
|
|
3992
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "clcosdk:h-5 clcosdk:w-48 clcosdk:animate-pulse clcosdk:rounded clcosdk:bg-surface" })
|
|
3993
|
+
]
|
|
3994
|
+
},
|
|
3995
|
+
field
|
|
3996
|
+
))
|
|
3997
|
+
}
|
|
3998
|
+
);
|
|
3999
|
+
}
|
|
4000
|
+
function ErrorScreen({
|
|
4001
|
+
reason
|
|
4002
|
+
}) {
|
|
4003
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
4004
|
+
AlertBanner,
|
|
4005
|
+
{
|
|
4006
|
+
variant: "error",
|
|
4007
|
+
icon: true,
|
|
4008
|
+
content: reason === "not-authenticated" ? "Sign in to complete your tax document." : "Unable to load your tax information right now. Please try again."
|
|
4009
|
+
}
|
|
4010
|
+
);
|
|
4011
|
+
}
|
|
4012
|
+
function ReviewScreen({
|
|
4013
|
+
fields,
|
|
4014
|
+
piiUnavailable,
|
|
4015
|
+
sign,
|
|
4016
|
+
onStartEdit,
|
|
4017
|
+
onSign
|
|
4018
|
+
}) {
|
|
4019
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-6", children: [
|
|
4020
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { className: cn(typeClasses.body, "clcosdk:text-text-secondary"), children: "Review your information below. If anything looks incorrect, edit before signing." }),
|
|
4021
|
+
piiUnavailable && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
4022
|
+
AlertBanner,
|
|
4023
|
+
{
|
|
4024
|
+
variant: "info",
|
|
4025
|
+
icon: true,
|
|
4026
|
+
content: "We don't have this information on file yet \u2014 please fill it in below."
|
|
4027
|
+
}
|
|
4028
|
+
),
|
|
4029
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-4 clcosdk:border-t clcosdk:border-divider clcosdk:pt-4", children: FIELD_ROWS.map(({ field, label }) => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
4030
|
+
"div",
|
|
4031
|
+
{
|
|
4032
|
+
className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-1",
|
|
4033
|
+
children: [
|
|
4034
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
4035
|
+
"span",
|
|
4036
|
+
{
|
|
4037
|
+
className: cn(typeClasses.label, "clcosdk:text-text-secondary"),
|
|
4038
|
+
children: label
|
|
4039
|
+
}
|
|
4040
|
+
),
|
|
4041
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: cn(typeClasses.body, "clcosdk:text-text-primary"), children: fields[field] || "\u2014" })
|
|
4042
|
+
]
|
|
4043
|
+
},
|
|
4044
|
+
field
|
|
4045
|
+
)) }),
|
|
4046
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { className: cn(typeClasses.caption, "clcosdk:text-text-secondary"), children: "By signing, you certify that the information above is accurate and that you are the beneficial owner of the income this form relates to. This document cannot be edited once signed." }),
|
|
4047
|
+
sign.type === "idle" && sign.error && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(AlertBanner, { variant: "error", icon: true, content: sign.error }),
|
|
4048
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-2", children: [
|
|
4049
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
4050
|
+
ClButton,
|
|
4051
|
+
{
|
|
4052
|
+
fullWidth: true,
|
|
4053
|
+
onClick: onSign,
|
|
4054
|
+
isLoading: sign.type === "signing",
|
|
4055
|
+
loadingText: "Signing...",
|
|
4056
|
+
children: "Sign W-8BEN"
|
|
4057
|
+
}
|
|
4058
|
+
),
|
|
4059
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
4060
|
+
ClButton,
|
|
4061
|
+
{
|
|
4062
|
+
fullWidth: true,
|
|
4063
|
+
variant: "secondary",
|
|
4064
|
+
onClick: onStartEdit,
|
|
4065
|
+
disabled: sign.type === "signing",
|
|
4066
|
+
children: "Edit information"
|
|
4067
|
+
}
|
|
4068
|
+
)
|
|
4069
|
+
] })
|
|
4070
|
+
] });
|
|
4071
|
+
}
|
|
4072
|
+
function EditScreen({
|
|
4073
|
+
fields,
|
|
4074
|
+
onEditField,
|
|
4075
|
+
onSaveEdit,
|
|
4076
|
+
onCancelEdit
|
|
4077
|
+
}) {
|
|
4078
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-6", children: [
|
|
4079
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-4 clcosdk:border-t clcosdk:border-divider clcosdk:pt-4", children: FIELD_ROWS.map(({ field, label, placeholder }) => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
4080
|
+
"label",
|
|
4081
|
+
{
|
|
4082
|
+
className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-1",
|
|
4083
|
+
children: [
|
|
4084
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
4085
|
+
"span",
|
|
4086
|
+
{
|
|
4087
|
+
className: cn(typeClasses.label, "clcosdk:text-text-secondary"),
|
|
4088
|
+
children: label
|
|
4089
|
+
}
|
|
4090
|
+
),
|
|
4091
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
4092
|
+
"input",
|
|
4093
|
+
{
|
|
4094
|
+
type: "text",
|
|
4095
|
+
value: fields[field],
|
|
4096
|
+
placeholder,
|
|
4097
|
+
onChange: (e) => onEditField(field, e.target.value),
|
|
4098
|
+
className: cn(
|
|
4099
|
+
typeClasses.body,
|
|
4100
|
+
"clcosdk:rounded-lg clcosdk:border clcosdk:border-border clcosdk:bg-background clcosdk:px-3 clcosdk:py-2 clcosdk:text-text-primary clcosdk:focus-visible:outline-none clcosdk:focus-visible:ring-2 clcosdk:focus-visible:ring-gray-400"
|
|
4101
|
+
)
|
|
4102
|
+
}
|
|
4103
|
+
)
|
|
4104
|
+
]
|
|
4105
|
+
},
|
|
4106
|
+
field
|
|
4107
|
+
)) }),
|
|
4108
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-2", children: [
|
|
4109
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ClButton, { fullWidth: true, onClick: onSaveEdit, children: "Save & review" }),
|
|
4110
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ClButton, { fullWidth: true, variant: "secondary", onClick: onCancelEdit, children: "Cancel" })
|
|
4111
|
+
] })
|
|
4112
|
+
] });
|
|
4113
|
+
}
|
|
4114
|
+
function SignOnlyScreen({
|
|
4115
|
+
sign,
|
|
4116
|
+
onSign
|
|
4117
|
+
}) {
|
|
4118
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-6", children: [
|
|
4119
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { className: cn(typeClasses.body, "clcosdk:text-text-secondary"), children: "As an entity investor, you must complete a W-8BEN-E to confirm your foreign tax status and claim applicable treaty benefits. You'll receive an email to complete the signing." }),
|
|
4120
|
+
sign.type === "idle" && sign.error && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(AlertBanner, { variant: "error", icon: true, content: sign.error }),
|
|
4121
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
4122
|
+
ClButton,
|
|
4123
|
+
{
|
|
4124
|
+
fullWidth: true,
|
|
4125
|
+
onClick: onSign,
|
|
4126
|
+
isLoading: sign.type === "signing",
|
|
4127
|
+
loadingText: "Signing...",
|
|
4128
|
+
children: "Sign W-8BEN-E"
|
|
4129
|
+
}
|
|
4130
|
+
)
|
|
4131
|
+
] });
|
|
4132
|
+
}
|
|
4133
|
+
|
|
4134
|
+
// src/client/hooks/useOptionAddresses.ts
|
|
4135
|
+
var import_react13 = require("react");
|
|
4136
|
+
var LOADING_STATE4 = { type: "LOADING" };
|
|
4137
|
+
var EMPTY_STATE = {
|
|
4138
|
+
type: "CONTENT",
|
|
4139
|
+
addresses: []
|
|
4140
|
+
};
|
|
4141
|
+
function useOptionAddresses(offerId, offerOptionId, options = {}) {
|
|
4142
|
+
const { coinlist, isReady } = useCoinList();
|
|
4143
|
+
const { data, enabled = true } = options;
|
|
4144
|
+
const [addressesState, setAddressesState] = (0, import_react13.useState)(
|
|
4145
|
+
data !== void 0 ? { type: "CONTENT", addresses: data } : LOADING_STATE4
|
|
4146
|
+
);
|
|
4147
|
+
const [fetchKey, setFetchKey] = (0, import_react13.useState)(0);
|
|
4148
|
+
const refetch = (0, import_react13.useCallback)(() => setFetchKey((k) => k + 1), []);
|
|
4149
|
+
const disconnect = (0, import_react13.useCallback)(
|
|
4150
|
+
async (addressId) => {
|
|
4151
|
+
await coinlist.removeOptionAddress(offerId, addressId);
|
|
4152
|
+
refetch();
|
|
4153
|
+
},
|
|
4154
|
+
[coinlist, offerId, refetch]
|
|
4155
|
+
);
|
|
4156
|
+
(0, import_react13.useEffect)(() => {
|
|
4157
|
+
let isCancelled = false;
|
|
4158
|
+
if (!enabled) {
|
|
4159
|
+
setAddressesState(
|
|
4160
|
+
data !== void 0 ? { type: "CONTENT", addresses: data } : EMPTY_STATE
|
|
4161
|
+
);
|
|
4162
|
+
return () => {
|
|
4163
|
+
isCancelled = true;
|
|
4164
|
+
};
|
|
4165
|
+
}
|
|
4166
|
+
if (!isReady) {
|
|
4167
|
+
if (data === void 0) {
|
|
4168
|
+
setAddressesState(LOADING_STATE4);
|
|
4169
|
+
}
|
|
4170
|
+
return () => {
|
|
4171
|
+
isCancelled = true;
|
|
4172
|
+
};
|
|
4173
|
+
}
|
|
4174
|
+
if (data !== void 0 && fetchKey === 0) {
|
|
4175
|
+
return () => {
|
|
4176
|
+
isCancelled = true;
|
|
4177
|
+
};
|
|
4178
|
+
}
|
|
4179
|
+
if (coinlist.getAuthState() === "logged-out") {
|
|
4180
|
+
setAddressesState({ type: "ERROR", reason: "not-authenticated" });
|
|
4181
|
+
return () => {
|
|
4182
|
+
isCancelled = true;
|
|
4183
|
+
};
|
|
4184
|
+
}
|
|
4185
|
+
setAddressesState(LOADING_STATE4);
|
|
4186
|
+
coinlist.listOptionAddresses(offerId, offerOptionId).then((addresses) => {
|
|
4187
|
+
if (!isCancelled) {
|
|
4188
|
+
setAddressesState({ type: "CONTENT", addresses });
|
|
4189
|
+
}
|
|
4190
|
+
}).catch((error) => {
|
|
4191
|
+
if (!isCancelled) {
|
|
4192
|
+
const reason = error instanceof NotAuthenticatedError ? "not-authenticated" : "generic-error";
|
|
4193
|
+
setAddressesState({ type: "ERROR", reason });
|
|
4194
|
+
}
|
|
4195
|
+
});
|
|
4196
|
+
return () => {
|
|
4197
|
+
isCancelled = true;
|
|
4198
|
+
};
|
|
4199
|
+
}, [coinlist, isReady, enabled, offerId, offerOptionId, fetchKey]);
|
|
4200
|
+
return { addressesState, refetch, disconnect };
|
|
4201
|
+
}
|
|
4202
|
+
|
|
4203
|
+
// src/client/hooks/useRequirements.ts
|
|
4204
|
+
var import_react14 = require("react");
|
|
4205
|
+
var LOADING_STATE5 = { type: "LOADING" };
|
|
4206
|
+
function useRequirements(offerId, options = {}) {
|
|
4207
|
+
const { coinlist, isReady } = useCoinList();
|
|
4208
|
+
const { data } = options;
|
|
4209
|
+
const [requirementsState, setRequirementsState] = (0, import_react14.useState)(
|
|
4210
|
+
data !== void 0 ? { type: "CONTENT", ...data } : LOADING_STATE5
|
|
4211
|
+
);
|
|
4212
|
+
const [fetchKey, setFetchKey] = (0, import_react14.useState)(0);
|
|
4213
|
+
const refetch = (0, import_react14.useCallback)(() => setFetchKey((k) => k + 1), []);
|
|
4214
|
+
(0, import_react14.useEffect)(() => {
|
|
4215
|
+
let isCancelled = false;
|
|
4216
|
+
if (!isReady) {
|
|
4217
|
+
if (data === void 0) {
|
|
4218
|
+
setRequirementsState(LOADING_STATE5);
|
|
4219
|
+
}
|
|
4220
|
+
return () => {
|
|
4221
|
+
isCancelled = true;
|
|
1989
4222
|
};
|
|
1990
4223
|
}
|
|
1991
4224
|
if (data !== void 0 && fetchKey === 0) {
|
|
@@ -1993,7 +4226,13 @@ function useRequirements(offerId, options = {}) {
|
|
|
1993
4226
|
isCancelled = true;
|
|
1994
4227
|
};
|
|
1995
4228
|
}
|
|
1996
|
-
|
|
4229
|
+
if (coinlist.getAuthState() === "logged-out") {
|
|
4230
|
+
setRequirementsState({ type: "ERROR", reason: "not-authenticated" });
|
|
4231
|
+
return () => {
|
|
4232
|
+
isCancelled = true;
|
|
4233
|
+
};
|
|
4234
|
+
}
|
|
4235
|
+
setRequirementsState(LOADING_STATE5);
|
|
1997
4236
|
Promise.all([
|
|
1998
4237
|
coinlist.fetchOfferRequirements(offerId),
|
|
1999
4238
|
coinlist.fetchRequirementStatuses(offerId)
|
|
@@ -2019,7 +4258,8 @@ function useRequirements(offerId, options = {}) {
|
|
|
2019
4258
|
}
|
|
2020
4259
|
|
|
2021
4260
|
// src/client/components/requirements/RequirementsChecklist.tsx
|
|
2022
|
-
var
|
|
4261
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
4262
|
+
var isWalletRequirement = (requirement) => RequirementVariant.fromType(requirement.type) === "wallet";
|
|
2023
4263
|
var DEFAULT_LABELS = {
|
|
2024
4264
|
kyc_approved: "KYC Verification",
|
|
2025
4265
|
identity_verified: "Identity Verification",
|
|
@@ -2028,7 +4268,8 @@ var DEFAULT_LABELS = {
|
|
|
2028
4268
|
external_wallet: "External Wallet",
|
|
2029
4269
|
whitelisted_wallet: "Whitelisted Wallet",
|
|
2030
4270
|
jurisdiction: "Jurisdiction Check",
|
|
2031
|
-
accreditation: "Accreditation"
|
|
4271
|
+
accreditation: "Accreditation",
|
|
4272
|
+
document: "Document"
|
|
2032
4273
|
};
|
|
2033
4274
|
var DEFAULT_DESCRIPTIONS = {
|
|
2034
4275
|
kyc_approved: "Complete Know Your Customer verification.",
|
|
@@ -2038,9 +4279,39 @@ var DEFAULT_DESCRIPTIONS = {
|
|
|
2038
4279
|
external_wallet: "Connect an external wallet.",
|
|
2039
4280
|
whitelisted_wallet: "Connect a whitelisted wallet.",
|
|
2040
4281
|
jurisdiction: "Confirm your jurisdiction eligibility.",
|
|
2041
|
-
accreditation: "Verify your accreditation status."
|
|
4282
|
+
accreditation: "Verify your accreditation status.",
|
|
4283
|
+
document: "Confirm your Tax Documents."
|
|
2042
4284
|
};
|
|
2043
|
-
|
|
4285
|
+
var VERIFICATION_POLL_INTERVAL_MS = 5e3;
|
|
4286
|
+
var VERIFICATION_POLL_TIMEOUT_MS = 12e4;
|
|
4287
|
+
function sleep(ms) {
|
|
4288
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
4289
|
+
}
|
|
4290
|
+
function VerificationOverlay({
|
|
4291
|
+
onClose,
|
|
4292
|
+
children
|
|
4293
|
+
}) {
|
|
4294
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4295
|
+
"div",
|
|
4296
|
+
{
|
|
4297
|
+
role: "dialog",
|
|
4298
|
+
"aria-modal": "true",
|
|
4299
|
+
"aria-label": "Identity verification",
|
|
4300
|
+
className: "clcosdk:fixed clcosdk:inset-0 clcosdk:z-50 clcosdk:flex clcosdk:items-center clcosdk:justify-center clcosdk:bg-overlay clcosdk:p-4",
|
|
4301
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "clcosdk:relative clcosdk:flex clcosdk:max-h-[92vh] clcosdk:w-full clcosdk:max-w-[760px] clcosdk:flex-col clcosdk:overflow-y-auto clcosdk:rounded-2xl clcosdk:bg-background clcosdk:p-6 clcosdk:pt-14", children: [
|
|
4302
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4303
|
+
CloseButton,
|
|
4304
|
+
{
|
|
4305
|
+
onClick: onClose,
|
|
4306
|
+
className: "clcosdk:absolute clcosdk:top-4 clcosdk:right-4"
|
|
4307
|
+
}
|
|
4308
|
+
),
|
|
4309
|
+
children
|
|
4310
|
+
] })
|
|
4311
|
+
}
|
|
4312
|
+
);
|
|
4313
|
+
}
|
|
4314
|
+
function RequirementsChecklistBody({
|
|
2044
4315
|
offerId,
|
|
2045
4316
|
optionId,
|
|
2046
4317
|
title,
|
|
@@ -2048,38 +4319,106 @@ function RequirementsChecklist({
|
|
|
2048
4319
|
onContinue,
|
|
2049
4320
|
onRequirementActionOverride,
|
|
2050
4321
|
onContactSupportOverride,
|
|
4322
|
+
wallet,
|
|
4323
|
+
onRequestConnect,
|
|
2051
4324
|
getLabel,
|
|
2052
4325
|
getDescription,
|
|
2053
4326
|
loading,
|
|
4327
|
+
unauthenticatedState,
|
|
2054
4328
|
error,
|
|
2055
4329
|
className,
|
|
2056
|
-
data
|
|
4330
|
+
data,
|
|
4331
|
+
identityVerificationOptions
|
|
2057
4332
|
}) {
|
|
2058
4333
|
const { coinlist } = useCoinList();
|
|
2059
|
-
const { requirementsState } = useRequirements(offerId, { data });
|
|
2060
|
-
const [expandedIndex, setExpandedIndex] = (0,
|
|
2061
|
-
const
|
|
4334
|
+
const { requirementsState, refetch } = useRequirements(offerId, { data });
|
|
4335
|
+
const [expandedIndex, setExpandedIndex] = (0, import_react15.useState)(null);
|
|
4336
|
+
const [taxDocumentOpen, setTaxDocumentOpen] = (0, import_react15.useState)(false);
|
|
4337
|
+
const [walletConnectOpen, setConnectWalletOpen] = (0, import_react15.useState)(false);
|
|
4338
|
+
const [verifyingRequirementId, setVerifyingRequirementId] = (0, import_react15.useState)(null);
|
|
4339
|
+
const isMountedRef = (0, import_react15.useRef)(true);
|
|
4340
|
+
(0, import_react15.useEffect)(() => {
|
|
4341
|
+
isMountedRef.current = true;
|
|
4342
|
+
return () => {
|
|
4343
|
+
isMountedRef.current = false;
|
|
4344
|
+
};
|
|
4345
|
+
}, []);
|
|
4346
|
+
const [hasWalletRequirement, setHasWalletRequirement] = (0, import_react15.useState)(false);
|
|
4347
|
+
(0, import_react15.useEffect)(() => {
|
|
4348
|
+
if (requirementsState.type === "CONTENT") {
|
|
4349
|
+
setHasWalletRequirement(
|
|
4350
|
+
(requirementsState.requirements[optionId] ?? []).some(
|
|
4351
|
+
isWalletRequirement
|
|
4352
|
+
)
|
|
4353
|
+
);
|
|
4354
|
+
}
|
|
4355
|
+
}, [requirementsState, optionId]);
|
|
4356
|
+
const {
|
|
4357
|
+
addressesState,
|
|
4358
|
+
refetch: refetchAddresses,
|
|
4359
|
+
disconnect
|
|
4360
|
+
} = useOptionAddresses(offerId, optionId, {
|
|
4361
|
+
enabled: hasWalletRequirement
|
|
4362
|
+
});
|
|
4363
|
+
const optionAddresses = addressesState.type === "CONTENT" ? addressesState.addresses : [];
|
|
4364
|
+
const walletsStatus = addressesState.type === "ERROR" ? "error" : addressesState.type === "LOADING" ? "loading" : "ready";
|
|
4365
|
+
const onRemoveWallet = async (id) => {
|
|
4366
|
+
await disconnect(OfferOptionAddressId(id));
|
|
4367
|
+
refetch();
|
|
4368
|
+
};
|
|
4369
|
+
const onRequirementAction = onRequirementActionOverride !== void 0 ? onRequirementActionOverride : (requirement) => {
|
|
4370
|
+
if (requirement.type === "document") {
|
|
4371
|
+
setTaxDocumentOpen(true);
|
|
4372
|
+
return;
|
|
4373
|
+
}
|
|
4374
|
+
if ((requirement.type === "external_wallet" || requirement.type === "whitelisted_wallet") && wallet !== void 0 && (wallet !== null || onRequestConnect !== void 0)) {
|
|
4375
|
+
setConnectWalletOpen(true);
|
|
4376
|
+
return;
|
|
4377
|
+
}
|
|
4378
|
+
coinlist.handleRequirement(requirement);
|
|
4379
|
+
};
|
|
2062
4380
|
const onContactSupport = onContactSupportOverride !== void 0 ? onContactSupportOverride : () => coinlist.contactSupport();
|
|
4381
|
+
const awaitVerificationResult = (requirementId, statusBeforeSubmit) => {
|
|
4382
|
+
void (async () => {
|
|
4383
|
+
const deadline = Date.now() + VERIFICATION_POLL_TIMEOUT_MS;
|
|
4384
|
+
while (Date.now() < deadline) {
|
|
4385
|
+
await sleep(VERIFICATION_POLL_INTERVAL_MS);
|
|
4386
|
+
if (!isMountedRef.current) return;
|
|
4387
|
+
try {
|
|
4388
|
+
const statuses2 = await coinlist.fetchRequirementStatuses(offerId);
|
|
4389
|
+
const current = statuses2.find((s) => s.id === requirementId)?.status;
|
|
4390
|
+
if (current !== void 0 && current !== statusBeforeSubmit) break;
|
|
4391
|
+
} catch (_) {
|
|
4392
|
+
}
|
|
4393
|
+
}
|
|
4394
|
+
if (isMountedRef.current) {
|
|
4395
|
+
setVerifyingRequirementId(null);
|
|
4396
|
+
refetch();
|
|
4397
|
+
}
|
|
4398
|
+
})();
|
|
4399
|
+
};
|
|
2063
4400
|
if (requirementsState.type === "LOADING") {
|
|
2064
4401
|
if (loading) return loading;
|
|
2065
|
-
return /* @__PURE__ */ (0,
|
|
4402
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2066
4403
|
"output",
|
|
2067
4404
|
{
|
|
2068
4405
|
"aria-live": "polite",
|
|
2069
4406
|
className: "clcosdk:flex clcosdk:min-h-40 clcosdk:items-center clcosdk:justify-center clcosdk:rounded-2xl clcosdk:border clcosdk:border-border clcosdk:bg-background clcosdk:p-6",
|
|
2070
|
-
children: /* @__PURE__ */ (0,
|
|
4407
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { className: cn(typeClasses.body, "clcosdk:text-text-secondary"), children: "Loading requirements..." })
|
|
2071
4408
|
}
|
|
2072
4409
|
);
|
|
2073
4410
|
}
|
|
2074
4411
|
if (requirementsState.type === "ERROR") {
|
|
4412
|
+
if (requirementsState.reason === "not-authenticated") {
|
|
4413
|
+
return unauthenticatedState !== void 0 ? unauthenticatedState : /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(CoinListSignInCard, {});
|
|
4414
|
+
}
|
|
2075
4415
|
if (error) return error;
|
|
2076
|
-
|
|
2077
|
-
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
4416
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2078
4417
|
AlertBanner,
|
|
2079
4418
|
{
|
|
2080
4419
|
variant: "error",
|
|
2081
4420
|
icon: true,
|
|
2082
|
-
content:
|
|
4421
|
+
content: "Unable to load requirements right now. Please try again.",
|
|
2083
4422
|
className: "clcosdk:w-full clcosdk:max-w-[28rem]"
|
|
2084
4423
|
}
|
|
2085
4424
|
);
|
|
@@ -2090,7 +4429,7 @@ function RequirementsChecklist({
|
|
|
2090
4429
|
const optionStatuses = statuses.filter((s) => requirementIds.has(s.id));
|
|
2091
4430
|
const statusByRequirementId = new Map(optionStatuses.map((s) => [s.id, s]));
|
|
2092
4431
|
const checklistStatus = ChecklistStatus.derive(optionStatuses);
|
|
2093
|
-
return /* @__PURE__ */ (0,
|
|
4432
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
2094
4433
|
"div",
|
|
2095
4434
|
{
|
|
2096
4435
|
className: cn(
|
|
@@ -2098,17 +4437,20 @@ function RequirementsChecklist({
|
|
|
2098
4437
|
className
|
|
2099
4438
|
),
|
|
2100
4439
|
children: [
|
|
2101
|
-
/* @__PURE__ */ (0,
|
|
2102
|
-
/* @__PURE__ */ (0,
|
|
2103
|
-
/* @__PURE__ */ (0,
|
|
4440
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-2", children: [
|
|
4441
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("h3", { className: cn(typeClasses.h3, "clcosdk:text-text-primary"), children: title }),
|
|
4442
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { className: cn(typeClasses.body, "clcosdk:text-text-secondary"), children: description })
|
|
2104
4443
|
] }),
|
|
2105
|
-
/* @__PURE__ */ (0,
|
|
4444
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:divide-y clcosdk:divide-divider", children: requirements.map((req, index) => {
|
|
2106
4445
|
const statusInfo = statusByRequirementId.get(req.id);
|
|
2107
4446
|
const label = getLabel ? getLabel(req) : DEFAULT_LABELS[req.type];
|
|
2108
4447
|
const itemDescription = (getDescription ? getDescription(req) : null) ?? DEFAULT_DESCRIPTIONS[req.type];
|
|
4448
|
+
const inlineVerification = statusInfo?.kycLevel !== void 0 && onRequirementActionOverride === void 0;
|
|
2109
4449
|
let onActionBound;
|
|
2110
4450
|
if (onRequirementAction === null) {
|
|
2111
4451
|
onActionBound = null;
|
|
4452
|
+
} else if (inlineVerification) {
|
|
4453
|
+
onActionBound = () => setVerifyingRequirementId(req.id);
|
|
2112
4454
|
} else if (onRequirementAction) {
|
|
2113
4455
|
onActionBound = () => onRequirementAction(req);
|
|
2114
4456
|
}
|
|
@@ -2118,24 +4460,28 @@ function RequirementsChecklist({
|
|
|
2118
4460
|
} else if (onContactSupport) {
|
|
2119
4461
|
onContactSupportBound = () => onContactSupport(req);
|
|
2120
4462
|
}
|
|
2121
|
-
|
|
4463
|
+
const walletRequirement = isWalletRequirement(req);
|
|
4464
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2122
4465
|
RequirementItem,
|
|
2123
4466
|
{
|
|
2124
4467
|
ui: RequirementItemUi.fromDomain(
|
|
2125
4468
|
req,
|
|
2126
4469
|
statusInfo,
|
|
2127
4470
|
label,
|
|
2128
|
-
itemDescription
|
|
4471
|
+
itemDescription,
|
|
4472
|
+
walletRequirement ? optionAddresses : []
|
|
2129
4473
|
),
|
|
2130
4474
|
expanded: expandedIndex === index,
|
|
2131
4475
|
onToggle: () => setExpandedIndex((prev) => prev === index ? null : index),
|
|
2132
4476
|
onAction: onActionBound,
|
|
4477
|
+
onRemoveWallet: walletRequirement ? onRemoveWallet : void 0,
|
|
4478
|
+
walletsStatus: walletRequirement ? walletsStatus : void 0,
|
|
2133
4479
|
onContactSupport: onContactSupportBound
|
|
2134
4480
|
},
|
|
2135
4481
|
req.id
|
|
2136
4482
|
);
|
|
2137
4483
|
}) }),
|
|
2138
|
-
checklistStatus === "ineligible" && /* @__PURE__ */ (0,
|
|
4484
|
+
checklistStatus === "ineligible" && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2139
4485
|
AlertBanner,
|
|
2140
4486
|
{
|
|
2141
4487
|
variant: "error",
|
|
@@ -2143,7 +4489,7 @@ function RequirementsChecklist({
|
|
|
2143
4489
|
content: "You are not eligible to participate."
|
|
2144
4490
|
}
|
|
2145
4491
|
),
|
|
2146
|
-
onContinue && /* @__PURE__ */ (0,
|
|
4492
|
+
onContinue && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2147
4493
|
ClButton,
|
|
2148
4494
|
{
|
|
2149
4495
|
fullWidth: true,
|
|
@@ -2151,24 +4497,326 @@ function RequirementsChecklist({
|
|
|
2151
4497
|
onClick: onContinue,
|
|
2152
4498
|
children: "Continue"
|
|
2153
4499
|
}
|
|
4500
|
+
),
|
|
4501
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4502
|
+
TaxDocumentModal,
|
|
4503
|
+
{
|
|
4504
|
+
isOpen: taxDocumentOpen,
|
|
4505
|
+
onClose: () => setTaxDocumentOpen(false),
|
|
4506
|
+
onSubmitted: () => refetch()
|
|
4507
|
+
}
|
|
4508
|
+
),
|
|
4509
|
+
verifyingRequirementId !== null && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(VerificationOverlay, { onClose: () => setVerifyingRequirementId(null), children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4510
|
+
IdentityVerification,
|
|
4511
|
+
{
|
|
4512
|
+
levelName: identityVerificationOptions?.levelName ?? statusByRequirementId.get(verifyingRequirementId)?.kycLevel,
|
|
4513
|
+
reset: statusByRequirementId.get(verifyingRequirementId)?.kycReset ?? false,
|
|
4514
|
+
locale: identityVerificationOptions?.locale,
|
|
4515
|
+
onSubmitted: () => awaitVerificationResult(
|
|
4516
|
+
verifyingRequirementId,
|
|
4517
|
+
statusByRequirementId.get(verifyingRequirementId)?.status ?? "not_started"
|
|
4518
|
+
)
|
|
4519
|
+
}
|
|
4520
|
+
) }),
|
|
4521
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4522
|
+
ConnectWalletModal,
|
|
4523
|
+
{
|
|
4524
|
+
isOpen: walletConnectOpen,
|
|
4525
|
+
onClose: () => setConnectWalletOpen(false),
|
|
4526
|
+
offerId,
|
|
4527
|
+
optionId,
|
|
4528
|
+
wallet: wallet ?? null,
|
|
4529
|
+
onRequestConnect,
|
|
4530
|
+
onConnected: () => {
|
|
4531
|
+
refetch();
|
|
4532
|
+
refetchAddresses();
|
|
4533
|
+
}
|
|
4534
|
+
}
|
|
2154
4535
|
)
|
|
2155
4536
|
]
|
|
2156
4537
|
}
|
|
2157
4538
|
);
|
|
2158
4539
|
}
|
|
4540
|
+
function RequirementsChecklist(props) {
|
|
4541
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(CoinListStyleScope, { children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(RequirementsChecklistBody, { ...props }) });
|
|
4542
|
+
}
|
|
4543
|
+
|
|
4544
|
+
// src/client/hooks/swap/useSwapOutputToken.ts
|
|
4545
|
+
var import_react16 = require("react");
|
|
4546
|
+
var LOADING_STATE6 = { type: "LOADING" };
|
|
4547
|
+
function useSwapOutputToken(options) {
|
|
4548
|
+
const { contractAddress, chain, enabled } = options;
|
|
4549
|
+
const { coinlist, isReady } = useCoinList();
|
|
4550
|
+
const [outputTokenState, setOutputTokenState] = (0, import_react16.useState)(LOADING_STATE6);
|
|
4551
|
+
const fetchIdRef = (0, import_react16.useRef)(0);
|
|
4552
|
+
(0, import_react16.useEffect)(() => {
|
|
4553
|
+
if (!enabled || !isReady) return;
|
|
4554
|
+
const currentFetchId = ++fetchIdRef.current;
|
|
4555
|
+
const load = async () => {
|
|
4556
|
+
try {
|
|
4557
|
+
const outputToken = await coinlist.swap.getOutputToken({
|
|
4558
|
+
contractAddress,
|
|
4559
|
+
chain
|
|
4560
|
+
});
|
|
4561
|
+
if (currentFetchId !== fetchIdRef.current) return;
|
|
4562
|
+
setOutputTokenState({ type: "CONTENT", outputToken });
|
|
4563
|
+
} catch {
|
|
4564
|
+
if (currentFetchId !== fetchIdRef.current) return;
|
|
4565
|
+
setOutputTokenState({ type: "ERROR" });
|
|
4566
|
+
}
|
|
4567
|
+
};
|
|
4568
|
+
load();
|
|
4569
|
+
return () => {
|
|
4570
|
+
++fetchIdRef.current;
|
|
4571
|
+
};
|
|
4572
|
+
}, [coinlist, isReady, contractAddress, chain, enabled]);
|
|
4573
|
+
return { outputTokenState };
|
|
4574
|
+
}
|
|
4575
|
+
|
|
4576
|
+
// src/client/hooks/swap/useSwapQuote.ts
|
|
4577
|
+
var import_react17 = require("react");
|
|
4578
|
+
|
|
4579
|
+
// src/shared/core/blockchain/swap/constants.ts
|
|
4580
|
+
var SWAP_POLL_INTERVAL_MS = 15e3;
|
|
4581
|
+
var SLIPPAGE_OPTIONS_BPS = [25n, 50n, 100n, 200n, 500n].map(
|
|
4582
|
+
(n) => Bps(n)
|
|
4583
|
+
);
|
|
4584
|
+
var DEFAULT_SLIPPAGE_BPS = Bps(50n);
|
|
4585
|
+
var SUPERSTATE_SWAP_CONTRACT_ADDRESS_SEPOLIA = EvmContractAddress("0x84f8e9a6C9Cc12fe911259372EfCa5582C4ae557");
|
|
4586
|
+
|
|
4587
|
+
// src/shared/core/blockchain/swap/quote.ts
|
|
4588
|
+
var SwapQuote = {
|
|
4589
|
+
/**
|
|
4590
|
+
* Assembles a {@link SwapQuote} from a raw contract {@link SwapPreview}. The
|
|
4591
|
+
* input and fee are denominated in the input token; the output in the output
|
|
4592
|
+
* token.
|
|
4593
|
+
*/
|
|
4594
|
+
fromPreview: (preview, inputDecimals, outputDecimals) => ({
|
|
4595
|
+
inputTokenAmount: BlockchainAmount({
|
|
4596
|
+
raw: preview.inputAmount,
|
|
4597
|
+
decimals: inputDecimals
|
|
4598
|
+
}),
|
|
4599
|
+
fee: BlockchainAmount({ raw: preview.fee, decimals: inputDecimals }),
|
|
4600
|
+
outputTokenAmount: BlockchainAmount({
|
|
4601
|
+
raw: preview.outputAmount,
|
|
4602
|
+
decimals: outputDecimals
|
|
4603
|
+
})
|
|
4604
|
+
})
|
|
4605
|
+
};
|
|
4606
|
+
|
|
4607
|
+
// src/client/hooks/swap/useSwapQuote.ts
|
|
4608
|
+
function useSwapQuote(options) {
|
|
4609
|
+
const {
|
|
4610
|
+
contractAddress,
|
|
4611
|
+
chain,
|
|
4612
|
+
inputAmount,
|
|
4613
|
+
inputTokenAddress,
|
|
4614
|
+
outputTokenDecimals,
|
|
4615
|
+
pollIntervalMs = SWAP_POLL_INTERVAL_MS,
|
|
4616
|
+
enabled
|
|
4617
|
+
} = options;
|
|
4618
|
+
const { coinlist, isReady } = useCoinList();
|
|
4619
|
+
const [quote, setQuote] = (0, import_react17.useState)(null);
|
|
4620
|
+
const [isLoading, setIsLoading] = (0, import_react17.useState)(true);
|
|
4621
|
+
const [isRefreshing, setIsRefreshing] = (0, import_react17.useState)(false);
|
|
4622
|
+
const isFetchingRef = (0, import_react17.useRef)(false);
|
|
4623
|
+
const hasQuoteRef = (0, import_react17.useRef)(false);
|
|
4624
|
+
const fetchIdRef = (0, import_react17.useRef)(0);
|
|
4625
|
+
(0, import_react17.useEffect)(() => {
|
|
4626
|
+
if (!isReady) return;
|
|
4627
|
+
if (!enabled) {
|
|
4628
|
+
setIsLoading(false);
|
|
4629
|
+
return;
|
|
4630
|
+
}
|
|
4631
|
+
const currentFetchId = ++fetchIdRef.current;
|
|
4632
|
+
isFetchingRef.current = false;
|
|
4633
|
+
const loadQuote = async () => {
|
|
4634
|
+
if (outputTokenDecimals === null) return;
|
|
4635
|
+
if (isFetchingRef.current) return;
|
|
4636
|
+
isFetchingRef.current = true;
|
|
4637
|
+
if (hasQuoteRef.current) {
|
|
4638
|
+
setIsRefreshing(true);
|
|
4639
|
+
}
|
|
4640
|
+
try {
|
|
4641
|
+
const preview = await coinlist.swap.getPreview({
|
|
4642
|
+
contractAddress,
|
|
4643
|
+
chain,
|
|
4644
|
+
inputToken: inputTokenAddress,
|
|
4645
|
+
amount: inputAmount.raw
|
|
4646
|
+
});
|
|
4647
|
+
if (currentFetchId !== fetchIdRef.current) return;
|
|
4648
|
+
setQuote(
|
|
4649
|
+
SwapQuote.fromPreview(
|
|
4650
|
+
preview,
|
|
4651
|
+
inputAmount.decimals,
|
|
4652
|
+
outputTokenDecimals
|
|
4653
|
+
)
|
|
4654
|
+
);
|
|
4655
|
+
if (!hasQuoteRef.current) {
|
|
4656
|
+
hasQuoteRef.current = true;
|
|
4657
|
+
setIsLoading(false);
|
|
4658
|
+
}
|
|
4659
|
+
} catch {
|
|
4660
|
+
} finally {
|
|
4661
|
+
if (currentFetchId === fetchIdRef.current) {
|
|
4662
|
+
isFetchingRef.current = false;
|
|
4663
|
+
setIsRefreshing(false);
|
|
4664
|
+
}
|
|
4665
|
+
}
|
|
4666
|
+
};
|
|
4667
|
+
loadQuote();
|
|
4668
|
+
const interval = setInterval(loadQuote, pollIntervalMs);
|
|
4669
|
+
return () => {
|
|
4670
|
+
clearInterval(interval);
|
|
4671
|
+
++fetchIdRef.current;
|
|
4672
|
+
setIsRefreshing(false);
|
|
4673
|
+
};
|
|
4674
|
+
}, [
|
|
4675
|
+
coinlist,
|
|
4676
|
+
isReady,
|
|
4677
|
+
contractAddress,
|
|
4678
|
+
chain,
|
|
4679
|
+
inputAmount.raw,
|
|
4680
|
+
inputAmount.decimals,
|
|
4681
|
+
inputTokenAddress,
|
|
4682
|
+
outputTokenDecimals,
|
|
4683
|
+
pollIntervalMs,
|
|
4684
|
+
enabled
|
|
4685
|
+
]);
|
|
4686
|
+
return { quote, isLoading, isRefreshing };
|
|
4687
|
+
}
|
|
4688
|
+
|
|
4689
|
+
// src/client/hooks/swap/useSwapTokenBalances.ts
|
|
4690
|
+
var import_react18 = require("react");
|
|
4691
|
+
|
|
4692
|
+
// src/shared/core/blockchain/token-registry.ts
|
|
4693
|
+
var USDC_SYMBOL = StablecoinSymbol("USDC");
|
|
4694
|
+
var USDC = {
|
|
4695
|
+
name: "USD Coin",
|
|
4696
|
+
symbol: USDC_SYMBOL,
|
|
4697
|
+
decimals: AssetDecimals(6)
|
|
4698
|
+
};
|
|
4699
|
+
var USDT_SYMBOL = StablecoinSymbol("USDT");
|
|
4700
|
+
var USDT = {
|
|
4701
|
+
name: "Tether USD",
|
|
4702
|
+
symbol: USDT_SYMBOL,
|
|
4703
|
+
decimals: AssetDecimals(6)
|
|
4704
|
+
};
|
|
4705
|
+
var USDC_ADDRESSES = {
|
|
4706
|
+
ethereum_mainnet: EvmContractAddress(
|
|
4707
|
+
"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"
|
|
4708
|
+
),
|
|
4709
|
+
ethereum_sepolia: EvmContractAddress(
|
|
4710
|
+
"0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238"
|
|
4711
|
+
)
|
|
4712
|
+
};
|
|
4713
|
+
var USDT_ADDRESSES = {
|
|
4714
|
+
ethereum_mainnet: EvmContractAddress(
|
|
4715
|
+
"0xdac17f958d2ee523a2206206994597c13d831ec7"
|
|
4716
|
+
),
|
|
4717
|
+
ethereum_sepolia: EvmContractAddress(
|
|
4718
|
+
"0x7169D38820dfd117C3FA1f22a697dBA58d90BA06"
|
|
4719
|
+
)
|
|
4720
|
+
};
|
|
4721
|
+
var TOKEN_REGISTRY = {
|
|
4722
|
+
erc20: (symbol) => {
|
|
4723
|
+
switch (symbol) {
|
|
4724
|
+
case "USDC":
|
|
4725
|
+
return USDC;
|
|
4726
|
+
case "USDT":
|
|
4727
|
+
return USDT;
|
|
4728
|
+
default:
|
|
4729
|
+
throw new Error(`Unknown asset symbol: ${symbol}`);
|
|
4730
|
+
}
|
|
4731
|
+
},
|
|
4732
|
+
contractAddress: (symbol, chain) => {
|
|
4733
|
+
switch (symbol) {
|
|
4734
|
+
case "USDC":
|
|
4735
|
+
return USDC_ADDRESSES[chain];
|
|
4736
|
+
case "USDT":
|
|
4737
|
+
return USDT_ADDRESSES[chain];
|
|
4738
|
+
default:
|
|
4739
|
+
throw new Error(`Unknown asset symbol: ${symbol}`);
|
|
4740
|
+
}
|
|
4741
|
+
}
|
|
4742
|
+
};
|
|
4743
|
+
|
|
4744
|
+
// src/client/hooks/swap/useSwapTokenBalances.ts
|
|
4745
|
+
function useSwapTokenBalances(options) {
|
|
4746
|
+
const {
|
|
4747
|
+
address,
|
|
4748
|
+
chain,
|
|
4749
|
+
assets,
|
|
4750
|
+
pollIntervalMs = SWAP_POLL_INTERVAL_MS,
|
|
4751
|
+
enabled
|
|
4752
|
+
} = options;
|
|
4753
|
+
const { coinlist, isReady } = useCoinList();
|
|
4754
|
+
const [balances, setBalances] = (0, import_react18.useState)(/* @__PURE__ */ new Map());
|
|
4755
|
+
const [isLoading, setIsLoading] = (0, import_react18.useState)(true);
|
|
4756
|
+
const fetchIdRef = (0, import_react18.useRef)(0);
|
|
4757
|
+
const isFetchingRef = (0, import_react18.useRef)(false);
|
|
4758
|
+
const assetsKey = assets.join(",");
|
|
4759
|
+
(0, import_react18.useEffect)(() => {
|
|
4760
|
+
if (!isReady) return;
|
|
4761
|
+
if (!enabled) {
|
|
4762
|
+
setIsLoading(false);
|
|
4763
|
+
return;
|
|
4764
|
+
}
|
|
4765
|
+
const symbols = assetsKey.split(",");
|
|
4766
|
+
const currentFetchId = ++fetchIdRef.current;
|
|
4767
|
+
isFetchingRef.current = false;
|
|
4768
|
+
let isFirstFetch = true;
|
|
4769
|
+
async function fetchBalances() {
|
|
4770
|
+
if (isFetchingRef.current) return;
|
|
4771
|
+
isFetchingRef.current = true;
|
|
4772
|
+
if (isFirstFetch) {
|
|
4773
|
+
setIsLoading(true);
|
|
4774
|
+
}
|
|
4775
|
+
const results = await Promise.allSettled(
|
|
4776
|
+
symbols.map(
|
|
4777
|
+
(symbol) => coinlist.swap.getTokenBalance({
|
|
4778
|
+
tokenAddress: TOKEN_REGISTRY.contractAddress(symbol, chain),
|
|
4779
|
+
owner: address,
|
|
4780
|
+
chain
|
|
4781
|
+
})
|
|
4782
|
+
)
|
|
4783
|
+
);
|
|
4784
|
+
if (currentFetchId !== fetchIdRef.current) return;
|
|
4785
|
+
isFetchingRef.current = false;
|
|
4786
|
+
const next = /* @__PURE__ */ new Map();
|
|
4787
|
+
symbols.forEach((symbol, i) => {
|
|
4788
|
+
const result = results[i];
|
|
4789
|
+
next.set(
|
|
4790
|
+
symbol,
|
|
4791
|
+
result.status === "fulfilled" ? result.value.balance : null
|
|
4792
|
+
);
|
|
4793
|
+
});
|
|
4794
|
+
setBalances(next);
|
|
4795
|
+
setIsLoading(false);
|
|
4796
|
+
isFirstFetch = false;
|
|
4797
|
+
}
|
|
4798
|
+
fetchBalances();
|
|
4799
|
+
const interval = setInterval(fetchBalances, pollIntervalMs);
|
|
4800
|
+
return () => {
|
|
4801
|
+
clearInterval(interval);
|
|
4802
|
+
++fetchIdRef.current;
|
|
4803
|
+
};
|
|
4804
|
+
}, [coinlist, isReady, address, chain, assetsKey, pollIntervalMs, enabled]);
|
|
4805
|
+
return { balances, isLoading };
|
|
4806
|
+
}
|
|
2159
4807
|
|
|
2160
4808
|
// src/client/hooks/useCompleteOAuth.ts
|
|
2161
|
-
var
|
|
4809
|
+
var import_react19 = require("react");
|
|
2162
4810
|
function useCompleteOAuth(options) {
|
|
2163
4811
|
const { coinlist } = useCoinList();
|
|
2164
|
-
const postOAuthCompleteRef = (0,
|
|
2165
|
-
const onFailureRef = (0,
|
|
2166
|
-
const onSuccessRef = (0,
|
|
4812
|
+
const postOAuthCompleteRef = (0, import_react19.useRef)(options.postOAuthComplete);
|
|
4813
|
+
const onFailureRef = (0, import_react19.useRef)(options.onFailure);
|
|
4814
|
+
const onSuccessRef = (0, import_react19.useRef)(options.onSuccess);
|
|
2167
4815
|
postOAuthCompleteRef.current = options.postOAuthComplete;
|
|
2168
4816
|
onFailureRef.current = options.onFailure;
|
|
2169
4817
|
onSuccessRef.current = options.onSuccess;
|
|
2170
|
-
const hasStartedExchangeRef = (0,
|
|
2171
|
-
(0,
|
|
4818
|
+
const hasStartedExchangeRef = (0, import_react19.useRef)(false);
|
|
4819
|
+
(0, import_react19.useEffect)(() => {
|
|
2172
4820
|
if (typeof window === "undefined") return;
|
|
2173
4821
|
const params = new URLSearchParams(window.location.search);
|
|
2174
4822
|
if (!params.has("code") && !params.has("error")) return;
|
|
@@ -2212,19 +4860,19 @@ function useCompleteOAuth(options) {
|
|
|
2212
4860
|
}
|
|
2213
4861
|
|
|
2214
4862
|
// src/client/hooks/useOfferDetails.ts
|
|
2215
|
-
var
|
|
2216
|
-
var
|
|
4863
|
+
var import_react20 = require("react");
|
|
4864
|
+
var LOADING_STATE7 = { type: "LOADING" };
|
|
2217
4865
|
function useOfferDetails(offerId, options = {}) {
|
|
2218
4866
|
const { coinlist, isReady } = useCoinList();
|
|
2219
4867
|
const { data } = options;
|
|
2220
|
-
const [offerDetailsState, setOfferDetailsState] = (0,
|
|
2221
|
-
data !== void 0 ? { type: "CONTENT", offerDetail: data } :
|
|
4868
|
+
const [offerDetailsState, setOfferDetailsState] = (0, import_react20.useState)(
|
|
4869
|
+
data !== void 0 ? { type: "CONTENT", offerDetail: data } : LOADING_STATE7
|
|
2222
4870
|
);
|
|
2223
|
-
(0,
|
|
4871
|
+
(0, import_react20.useEffect)(() => {
|
|
2224
4872
|
let isCancelled = false;
|
|
2225
4873
|
if (!isReady) {
|
|
2226
4874
|
if (data === void 0) {
|
|
2227
|
-
setOfferDetailsState(
|
|
4875
|
+
setOfferDetailsState(LOADING_STATE7);
|
|
2228
4876
|
}
|
|
2229
4877
|
return () => {
|
|
2230
4878
|
isCancelled = true;
|
|
@@ -2235,7 +4883,7 @@ function useOfferDetails(offerId, options = {}) {
|
|
|
2235
4883
|
isCancelled = true;
|
|
2236
4884
|
};
|
|
2237
4885
|
}
|
|
2238
|
-
setOfferDetailsState(
|
|
4886
|
+
setOfferDetailsState(LOADING_STATE7);
|
|
2239
4887
|
coinlist.fetchOfferDetails(offerId).then((offerDetail) => {
|
|
2240
4888
|
if (!isCancelled) {
|
|
2241
4889
|
setOfferDetailsState({ type: "CONTENT", offerDetail });
|
|
@@ -2254,19 +4902,19 @@ function useOfferDetails(offerId, options = {}) {
|
|
|
2254
4902
|
}
|
|
2255
4903
|
|
|
2256
4904
|
// src/client/hooks/useParticipations.ts
|
|
2257
|
-
var
|
|
2258
|
-
var
|
|
4905
|
+
var import_react21 = require("react");
|
|
4906
|
+
var LOADING_STATE8 = { type: "LOADING" };
|
|
2259
4907
|
function useParticipations(offerId, options = {}) {
|
|
2260
4908
|
const { coinlist, isReady } = useCoinList();
|
|
2261
4909
|
const { data } = options;
|
|
2262
|
-
const [participationsState, setParticipationsState] = (0,
|
|
2263
|
-
data !== void 0 ? { type: "CONTENT", participations: data } :
|
|
4910
|
+
const [participationsState, setParticipationsState] = (0, import_react21.useState)(
|
|
4911
|
+
data !== void 0 ? { type: "CONTENT", participations: data } : LOADING_STATE8
|
|
2264
4912
|
);
|
|
2265
|
-
(0,
|
|
4913
|
+
(0, import_react21.useEffect)(() => {
|
|
2266
4914
|
let isCancelled = false;
|
|
2267
4915
|
if (!isReady) {
|
|
2268
4916
|
if (data === void 0) {
|
|
2269
|
-
setParticipationsState(
|
|
4917
|
+
setParticipationsState(LOADING_STATE8);
|
|
2270
4918
|
}
|
|
2271
4919
|
return () => {
|
|
2272
4920
|
isCancelled = true;
|
|
@@ -2277,7 +4925,7 @@ function useParticipations(offerId, options = {}) {
|
|
|
2277
4925
|
isCancelled = true;
|
|
2278
4926
|
};
|
|
2279
4927
|
}
|
|
2280
|
-
setParticipationsState(
|
|
4928
|
+
setParticipationsState(LOADING_STATE8);
|
|
2281
4929
|
coinlist.fetchParticipations(offerId).then((participations) => {
|
|
2282
4930
|
if (!isCancelled) {
|
|
2283
4931
|
setParticipationsState({ type: "CONTENT", participations });
|
|
@@ -2297,12 +4945,17 @@ function useParticipations(offerId, options = {}) {
|
|
|
2297
4945
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2298
4946
|
0 && (module.exports = {
|
|
2299
4947
|
ChecklistStatus,
|
|
4948
|
+
ClientSwapNamespaceImpl,
|
|
2300
4949
|
CoinListClientInitializationError,
|
|
2301
4950
|
CoinListContext,
|
|
2302
4951
|
CoinListContextProvider,
|
|
2303
4952
|
CoinListProvider,
|
|
2304
4953
|
CoinListSignInCard,
|
|
2305
4954
|
CoinListStyleScope,
|
|
4955
|
+
ConnectWalletModal,
|
|
4956
|
+
ConnectedWalletList,
|
|
4957
|
+
IdentityVerification,
|
|
4958
|
+
KycToken,
|
|
2306
4959
|
OAUTH_CODE_VERIFIER_KEY,
|
|
2307
4960
|
OAUTH_STATE_KEY,
|
|
2308
4961
|
OfferCard,
|
|
@@ -2313,12 +4966,24 @@ function useParticipations(offerId, options = {}) {
|
|
|
2313
4966
|
RequirementStatus,
|
|
2314
4967
|
RequirementVariant,
|
|
2315
4968
|
RequirementsChecklist,
|
|
4969
|
+
TaxDocumentModal,
|
|
4970
|
+
authorizeWallet,
|
|
4971
|
+
classifyWalletError,
|
|
4972
|
+
connectExternalWalletFlow,
|
|
2316
4973
|
createCoinListClient,
|
|
4974
|
+
executeSwap,
|
|
2317
4975
|
useCoinList,
|
|
2318
4976
|
useCompleteOAuth,
|
|
4977
|
+
useConnectWallet,
|
|
4978
|
+
useKycToken,
|
|
2319
4979
|
useOfferDetails,
|
|
2320
4980
|
useOffers,
|
|
4981
|
+
useOptionAddresses,
|
|
2321
4982
|
useParticipations,
|
|
2322
|
-
useRequirements
|
|
4983
|
+
useRequirements,
|
|
4984
|
+
useSwapOutputToken,
|
|
4985
|
+
useSwapQuote,
|
|
4986
|
+
useSwapTokenBalances,
|
|
4987
|
+
useTaxDocument
|
|
2323
4988
|
});
|
|
2324
4989
|
//# sourceMappingURL=index.cjs.map
|