@coinlist-co/react 0.5.1 → 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-N3WBC2VS.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 +3360 -556
- package/dist/client/index.cjs.map +1 -1
- package/dist/client/index.d.cts +921 -18
- package/dist/client/index.d.ts +921 -18
- package/dist/client/index.js +2275 -392
- 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 +1264 -42
- package/dist/shared/index.cjs.map +1 -1
- package/dist/shared/index.d.cts +644 -3
- package/dist/shared/index.d.ts +644 -3
- package/dist/shared/index.js +220 -5
- package/dist/shared/index.js.map +1 -1
- package/package.json +33 -30
- package/dist/chunk-5E3P7AMH.js.map +0 -1
- package/dist/chunk-CRACFEJ4.js +0 -17
- package/dist/chunk-CRACFEJ4.js.map +0 -1
- package/dist/chunk-N3WBC2VS.js.map +0 -1
- package/dist/chunk-V6WO67RO.js +0 -311
- package/dist/chunk-V6WO67RO.js.map +0 -1
- package/dist/client/styles.css +0 -2
- package/dist/requirement-BEO42QOr.d.cts +0 -387
- package/dist/requirement-BEO42QOr.d.ts +0 -387
package/dist/client/index.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
2
|
API_VERSION,
|
|
3
|
-
Attributes,
|
|
4
3
|
AuthenticatedApiClient,
|
|
5
4
|
COINLIST_BASE_URL,
|
|
6
5
|
HEADER_USER_AGENT,
|
|
@@ -13,6 +12,7 @@ import {
|
|
|
13
12
|
VERIFY_IDENTITY_SOURCE_OF_FUNDS_PATH,
|
|
14
13
|
VERIFY_IDENTITY_VERIFIED_PATH,
|
|
15
14
|
WALLET_PATH,
|
|
15
|
+
createKycToken,
|
|
16
16
|
createParticipation,
|
|
17
17
|
fetchOfferDetails,
|
|
18
18
|
fetchOfferRequirements,
|
|
@@ -21,22 +21,38 @@ import {
|
|
|
21
21
|
fetchParticipation,
|
|
22
22
|
fetchParticipations,
|
|
23
23
|
fetchParticipationsPage,
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
fetchPii,
|
|
25
|
+
fetchRequirementStatuses,
|
|
26
|
+
submitDocument
|
|
27
|
+
} from "../chunk-MKCOK3DF.js";
|
|
26
28
|
import {
|
|
27
29
|
AuthorizationCode,
|
|
28
|
-
CodeVerifier
|
|
29
|
-
|
|
30
|
+
CodeVerifier,
|
|
31
|
+
ERC20_ABI,
|
|
32
|
+
SUPERSTATE_SWAP_ABI,
|
|
33
|
+
SWAP_POLL_INTERVAL_MS,
|
|
34
|
+
SwapQuote,
|
|
35
|
+
TOKEN_REGISTRY,
|
|
36
|
+
computePrice,
|
|
37
|
+
computeSlip,
|
|
38
|
+
decodeSwappedOutputAmount,
|
|
39
|
+
generatePKCEParams,
|
|
40
|
+
isStopped,
|
|
41
|
+
shortenAddress
|
|
42
|
+
} from "../chunk-I5YTJ5SL.js";
|
|
30
43
|
import {
|
|
44
|
+
Attributes,
|
|
45
|
+
BlockchainAmount,
|
|
46
|
+
KycToken,
|
|
31
47
|
NotAuthenticatedError,
|
|
32
|
-
|
|
33
|
-
|
|
48
|
+
OfferOptionAddressId,
|
|
49
|
+
SwapNamespaceImpl,
|
|
50
|
+
connectExternalWallet,
|
|
51
|
+
createWalletOwnershipChallenge,
|
|
34
52
|
getUUIDv4,
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
// src/client/index.ts
|
|
39
|
-
import "./styles.css";
|
|
53
|
+
listOptionAddresses,
|
|
54
|
+
removeOptionAddress
|
|
55
|
+
} from "../chunk-Z2HAA2TI.js";
|
|
40
56
|
|
|
41
57
|
// src/client/CoinListProvider.tsx
|
|
42
58
|
import {
|
|
@@ -93,6 +109,286 @@ var ApiClient = class {
|
|
|
93
109
|
}
|
|
94
110
|
};
|
|
95
111
|
|
|
112
|
+
// src/client/core/blockchain/wallet-error.ts
|
|
113
|
+
import {
|
|
114
|
+
ContractFunctionRevertedError,
|
|
115
|
+
InsufficientFundsError,
|
|
116
|
+
UserRejectedRequestError,
|
|
117
|
+
WaitForTransactionReceiptTimeoutError
|
|
118
|
+
} from "viem";
|
|
119
|
+
function classifyWalletError(error, ctx) {
|
|
120
|
+
if (error instanceof UserRejectedRequestError) {
|
|
121
|
+
return { type: "user_rejected" };
|
|
122
|
+
}
|
|
123
|
+
if (error instanceof InsufficientFundsError) {
|
|
124
|
+
return { type: "insufficient_funds" };
|
|
125
|
+
}
|
|
126
|
+
if (error instanceof ContractFunctionRevertedError) {
|
|
127
|
+
return { type: "contract_reverted", reason: error.reason ?? error.message };
|
|
128
|
+
}
|
|
129
|
+
if (error instanceof WaitForTransactionReceiptTimeoutError && ctx?.hash) {
|
|
130
|
+
return { type: "timeout", hash: ctx.hash };
|
|
131
|
+
}
|
|
132
|
+
return { type: "unknown", cause: error };
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// src/client/core/blockchain/swap-flows.ts
|
|
136
|
+
async function executeSwap(params) {
|
|
137
|
+
const {
|
|
138
|
+
swap,
|
|
139
|
+
wallet,
|
|
140
|
+
contractAddress,
|
|
141
|
+
chain,
|
|
142
|
+
inputTokenAddress,
|
|
143
|
+
quote,
|
|
144
|
+
slippageBps,
|
|
145
|
+
onProgress
|
|
146
|
+
} = params;
|
|
147
|
+
const emit = (phase) => onProgress?.(phase);
|
|
148
|
+
const inputAmount = BlockchainAmount.add(
|
|
149
|
+
quote.inputTokenAmount,
|
|
150
|
+
quote.fee
|
|
151
|
+
).raw;
|
|
152
|
+
const minOut = computeSlip(quote.outputTokenAmount, slippageBps).raw;
|
|
153
|
+
emit("checking-status");
|
|
154
|
+
let status;
|
|
155
|
+
try {
|
|
156
|
+
status = await swap.getStatus({ contractAddress, chain });
|
|
157
|
+
} catch {
|
|
158
|
+
return { type: "error", error: { step: "status-check" } };
|
|
159
|
+
}
|
|
160
|
+
if (isStopped(status)) {
|
|
161
|
+
return { type: "error", error: { step: "swap-stopped" } };
|
|
162
|
+
}
|
|
163
|
+
emit("checking-allowance");
|
|
164
|
+
let allowance;
|
|
165
|
+
try {
|
|
166
|
+
allowance = await swap.getTokenAllowance({
|
|
167
|
+
tokenAddress: inputTokenAddress,
|
|
168
|
+
owner: wallet.address,
|
|
169
|
+
spender: contractAddress,
|
|
170
|
+
chain
|
|
171
|
+
});
|
|
172
|
+
} catch {
|
|
173
|
+
return { type: "error", error: { step: "allowance-check" } };
|
|
174
|
+
}
|
|
175
|
+
if (allowance.allowance < inputAmount) {
|
|
176
|
+
if (allowance.allowance > 0n) {
|
|
177
|
+
const reset = await submitApproval({
|
|
178
|
+
wallet,
|
|
179
|
+
tokenAddress: inputTokenAddress,
|
|
180
|
+
spender: contractAddress,
|
|
181
|
+
chain,
|
|
182
|
+
value: 0n,
|
|
183
|
+
pending: "resetting-allowance",
|
|
184
|
+
confirming: "confirming-allowance-reset",
|
|
185
|
+
emit
|
|
186
|
+
});
|
|
187
|
+
if (reset.type === "error") return { type: "error", error: reset.error };
|
|
188
|
+
}
|
|
189
|
+
const approve = await submitApproval({
|
|
190
|
+
wallet,
|
|
191
|
+
tokenAddress: inputTokenAddress,
|
|
192
|
+
spender: contractAddress,
|
|
193
|
+
chain,
|
|
194
|
+
value: inputAmount,
|
|
195
|
+
pending: "approving",
|
|
196
|
+
confirming: "confirming-approval",
|
|
197
|
+
emit
|
|
198
|
+
});
|
|
199
|
+
if (approve.type === "error")
|
|
200
|
+
return { type: "error", error: approve.error };
|
|
201
|
+
}
|
|
202
|
+
emit("swapping");
|
|
203
|
+
let swapTxHash;
|
|
204
|
+
try {
|
|
205
|
+
swapTxHash = await wallet.writeContract({
|
|
206
|
+
abi: SUPERSTATE_SWAP_ABI,
|
|
207
|
+
address: contractAddress,
|
|
208
|
+
functionName: "swap",
|
|
209
|
+
args: [inputTokenAddress, inputAmount, minOut],
|
|
210
|
+
chain
|
|
211
|
+
});
|
|
212
|
+
} catch (error) {
|
|
213
|
+
return {
|
|
214
|
+
type: "error",
|
|
215
|
+
error: { step: "swap", cause: classifyWalletError(error) }
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
emit("confirming-swap");
|
|
219
|
+
let receipt;
|
|
220
|
+
try {
|
|
221
|
+
receipt = await wallet.awaitTx(swapTxHash, chain);
|
|
222
|
+
} catch (error) {
|
|
223
|
+
return {
|
|
224
|
+
type: "error",
|
|
225
|
+
error: {
|
|
226
|
+
step: "swap",
|
|
227
|
+
cause: classifyWalletError(error, { hash: swapTxHash })
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
if (receipt.status !== "success") {
|
|
232
|
+
return { type: "error", error: { step: "swap-reverted" } };
|
|
233
|
+
}
|
|
234
|
+
const outputAmount = decodeSwappedOutputAmount(receipt, quote.outputTokenAmount.decimals) ?? quote.outputTokenAmount;
|
|
235
|
+
const finalQuote = { ...quote, outputTokenAmount: outputAmount };
|
|
236
|
+
return {
|
|
237
|
+
type: "success",
|
|
238
|
+
swapTxHash,
|
|
239
|
+
inputAmount: finalQuote.inputTokenAmount,
|
|
240
|
+
fee: finalQuote.fee,
|
|
241
|
+
outputAmount,
|
|
242
|
+
pricePerShare: computePrice(finalQuote),
|
|
243
|
+
recipientAddress: wallet.address
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
async function submitApproval(args) {
|
|
247
|
+
const {
|
|
248
|
+
wallet,
|
|
249
|
+
tokenAddress,
|
|
250
|
+
spender,
|
|
251
|
+
chain,
|
|
252
|
+
value,
|
|
253
|
+
pending,
|
|
254
|
+
confirming,
|
|
255
|
+
emit
|
|
256
|
+
} = args;
|
|
257
|
+
emit(pending);
|
|
258
|
+
let hash;
|
|
259
|
+
try {
|
|
260
|
+
hash = await wallet.writeContract({
|
|
261
|
+
abi: ERC20_ABI,
|
|
262
|
+
address: tokenAddress,
|
|
263
|
+
functionName: "approve",
|
|
264
|
+
args: [spender, value],
|
|
265
|
+
chain
|
|
266
|
+
});
|
|
267
|
+
} catch (error) {
|
|
268
|
+
return {
|
|
269
|
+
type: "error",
|
|
270
|
+
error: { step: "approval", cause: classifyWalletError(error) }
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
emit(confirming);
|
|
274
|
+
let receipt;
|
|
275
|
+
try {
|
|
276
|
+
receipt = await wallet.awaitTx(hash, chain);
|
|
277
|
+
} catch (error) {
|
|
278
|
+
return {
|
|
279
|
+
type: "error",
|
|
280
|
+
error: { step: "approval", cause: classifyWalletError(error, { hash }) }
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
if (receipt.status !== "success") {
|
|
284
|
+
return { type: "error", error: { step: "approval-reverted" } };
|
|
285
|
+
}
|
|
286
|
+
return { type: "ok" };
|
|
287
|
+
}
|
|
288
|
+
async function authorizeWallet(params) {
|
|
289
|
+
const { swap, wallet, offerId, contractAddress, chain, onProgress } = params;
|
|
290
|
+
const emit = (phase) => onProgress?.(phase);
|
|
291
|
+
const walletAddress = wallet.address;
|
|
292
|
+
emit("checking-authorization");
|
|
293
|
+
let auth;
|
|
294
|
+
try {
|
|
295
|
+
auth = await swap.getAuthorization({
|
|
296
|
+
walletAddress,
|
|
297
|
+
contractAddress,
|
|
298
|
+
chain
|
|
299
|
+
});
|
|
300
|
+
} catch {
|
|
301
|
+
return { type: "error", error: { step: "authorization-check" } };
|
|
302
|
+
}
|
|
303
|
+
if (auth.authorized) return { type: "success" };
|
|
304
|
+
emit("requesting-challenge");
|
|
305
|
+
let challenge;
|
|
306
|
+
try {
|
|
307
|
+
challenge = await swap.requestWalletOwnershipChallenge({
|
|
308
|
+
walletAddress,
|
|
309
|
+
chain,
|
|
310
|
+
challengeType: "plain"
|
|
311
|
+
});
|
|
312
|
+
} catch {
|
|
313
|
+
return { type: "error", error: { step: "challenge-request" } };
|
|
314
|
+
}
|
|
315
|
+
emit("signing-message");
|
|
316
|
+
let signature;
|
|
317
|
+
try {
|
|
318
|
+
signature = await wallet.signMessage(challenge.message);
|
|
319
|
+
} catch (error) {
|
|
320
|
+
return {
|
|
321
|
+
type: "error",
|
|
322
|
+
error: { step: "signing", cause: classifyWalletError(error) }
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
emit("submitting-signature");
|
|
326
|
+
let allow;
|
|
327
|
+
try {
|
|
328
|
+
allow = await swap.allowWallet({
|
|
329
|
+
offerId,
|
|
330
|
+
walletAddress,
|
|
331
|
+
chain,
|
|
332
|
+
signature
|
|
333
|
+
});
|
|
334
|
+
} catch {
|
|
335
|
+
return { type: "error", error: { step: "allow-wallet" } };
|
|
336
|
+
}
|
|
337
|
+
if (allow.action === "broadcast_transaction") {
|
|
338
|
+
emit("broadcasting-transaction");
|
|
339
|
+
let hash;
|
|
340
|
+
try {
|
|
341
|
+
hash = await wallet.broadcastRawTx({
|
|
342
|
+
to: allow.to,
|
|
343
|
+
data: allow.data,
|
|
344
|
+
chain
|
|
345
|
+
});
|
|
346
|
+
} catch (error) {
|
|
347
|
+
return {
|
|
348
|
+
type: "error",
|
|
349
|
+
error: { step: "broadcast", cause: classifyWalletError(error) }
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
emit("awaiting-confirmation");
|
|
353
|
+
try {
|
|
354
|
+
await wallet.awaitTx(hash, chain);
|
|
355
|
+
} catch (error) {
|
|
356
|
+
return {
|
|
357
|
+
type: "error",
|
|
358
|
+
error: {
|
|
359
|
+
step: "broadcast",
|
|
360
|
+
cause: classifyWalletError(error, { hash })
|
|
361
|
+
}
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
emit("verifying-authorization");
|
|
366
|
+
let reCheck;
|
|
367
|
+
try {
|
|
368
|
+
reCheck = await swap.getAuthorization({
|
|
369
|
+
walletAddress,
|
|
370
|
+
contractAddress,
|
|
371
|
+
chain
|
|
372
|
+
});
|
|
373
|
+
} catch {
|
|
374
|
+
return { type: "error", error: { step: "authorization-check" } };
|
|
375
|
+
}
|
|
376
|
+
if (!reCheck.authorized) {
|
|
377
|
+
return { type: "error", error: { step: "not-authorized" } };
|
|
378
|
+
}
|
|
379
|
+
return { type: "success" };
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
// src/client/core/client-swap-namespace.ts
|
|
383
|
+
var ClientSwapNamespaceImpl = class extends SwapNamespaceImpl {
|
|
384
|
+
executeSwap(params) {
|
|
385
|
+
return executeSwap({ ...params, swap: this });
|
|
386
|
+
}
|
|
387
|
+
authorizeWallet(params) {
|
|
388
|
+
return authorizeWallet({ ...params, swap: this });
|
|
389
|
+
}
|
|
390
|
+
};
|
|
391
|
+
|
|
96
392
|
// src/client/core/coinlist-client.ts
|
|
97
393
|
var OAUTH_STATE_KEY = "coinlist.oauth_state";
|
|
98
394
|
var OAUTH_CODE_VERIFIER_KEY = "coinlist.oauth_code_verifier";
|
|
@@ -108,6 +404,10 @@ var CoinListClientImpl = class {
|
|
|
108
404
|
},
|
|
109
405
|
this.fetchAccessToken.bind(this)
|
|
110
406
|
);
|
|
407
|
+
this.swap = new ClientSwapNamespaceImpl({
|
|
408
|
+
api: this.api,
|
|
409
|
+
ensureUserAuthenticated: async () => this.ensureAuthenticated()
|
|
410
|
+
});
|
|
111
411
|
}
|
|
112
412
|
async init() {
|
|
113
413
|
await this.fetchAccessToken(true);
|
|
@@ -131,19 +431,16 @@ var CoinListClientImpl = class {
|
|
|
131
431
|
return this._accessToken !== null ? "logged-in" : "logged-out";
|
|
132
432
|
}
|
|
133
433
|
async startOAuth() {
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
const codeChallenge = arrayBufferToBase64Url(codeChallengeRaw, false);
|
|
138
|
-
sessionStorage.setItem(OAUTH_STATE_KEY, state);
|
|
139
|
-
sessionStorage.setItem(OAUTH_CODE_VERIFIER_KEY, codeVerifier);
|
|
434
|
+
const pkceParams = await generatePKCEParams(this._config);
|
|
435
|
+
sessionStorage.setItem(OAUTH_STATE_KEY, pkceParams.state);
|
|
436
|
+
sessionStorage.setItem(OAUTH_CODE_VERIFIER_KEY, pkceParams.codeVerifier);
|
|
140
437
|
const params = new URLSearchParams({
|
|
141
|
-
client_id:
|
|
142
|
-
response_type:
|
|
143
|
-
redirect_uri:
|
|
144
|
-
code_challenge: codeChallenge,
|
|
145
|
-
code_challenge_method:
|
|
146
|
-
state
|
|
438
|
+
client_id: pkceParams.clientId,
|
|
439
|
+
response_type: pkceParams.responseType,
|
|
440
|
+
redirect_uri: pkceParams.redirectUri,
|
|
441
|
+
code_challenge: pkceParams.codeChallenge,
|
|
442
|
+
code_challenge_method: pkceParams.codeChallengeMethod,
|
|
443
|
+
state: pkceParams.state
|
|
147
444
|
});
|
|
148
445
|
const baseUrl = this._config.coinlistBaseUrl ?? COINLIST_BASE_URL;
|
|
149
446
|
const url = `${baseUrl}${OAUTH_PAGE_PATH}?${params.toString()}`;
|
|
@@ -182,15 +479,15 @@ var CoinListClientImpl = class {
|
|
|
182
479
|
}
|
|
183
480
|
async fetchOffers() {
|
|
184
481
|
this.ensureAuthenticated();
|
|
185
|
-
return fetchOffers(this.api);
|
|
482
|
+
return fetchOffers(this.api, void 0);
|
|
186
483
|
}
|
|
187
484
|
async fetchOffersPage(params) {
|
|
188
485
|
this.ensureAuthenticated();
|
|
189
|
-
return fetchOffersPage(this.api, params);
|
|
486
|
+
return fetchOffersPage(this.api, params, void 0);
|
|
190
487
|
}
|
|
191
488
|
async fetchOfferDetails(id) {
|
|
192
489
|
this.ensureAuthenticated();
|
|
193
|
-
return fetchOfferDetails(this.api, id);
|
|
490
|
+
return fetchOfferDetails(this.api, id, void 0);
|
|
194
491
|
}
|
|
195
492
|
async fetchParticipations(offerId) {
|
|
196
493
|
this.ensureAuthenticated();
|
|
@@ -208,14 +505,46 @@ var CoinListClientImpl = class {
|
|
|
208
505
|
this.ensureAuthenticated();
|
|
209
506
|
return createParticipation(this.api, params);
|
|
210
507
|
}
|
|
508
|
+
async createWalletOwnershipChallenge(params) {
|
|
509
|
+
this.ensureAuthenticated();
|
|
510
|
+
return createWalletOwnershipChallenge(this.api, params);
|
|
511
|
+
}
|
|
512
|
+
async connectExternalWallet(offerId, params) {
|
|
513
|
+
this.ensureAuthenticated();
|
|
514
|
+
return connectExternalWallet(this.api, offerId, params);
|
|
515
|
+
}
|
|
516
|
+
async listOptionAddresses(offerId, offerOptionId) {
|
|
517
|
+
this.ensureAuthenticated();
|
|
518
|
+
return listOptionAddresses(
|
|
519
|
+
this.api,
|
|
520
|
+
offerId,
|
|
521
|
+
offerOptionId
|
|
522
|
+
);
|
|
523
|
+
}
|
|
524
|
+
async removeOptionAddress(offerId, addressId) {
|
|
525
|
+
this.ensureAuthenticated();
|
|
526
|
+
return removeOptionAddress(this.api, offerId, addressId);
|
|
527
|
+
}
|
|
211
528
|
async fetchOfferRequirements(offerId) {
|
|
212
529
|
this.ensureAuthenticated();
|
|
213
|
-
return fetchOfferRequirements(this.api, offerId);
|
|
530
|
+
return fetchOfferRequirements(this.api, offerId, void 0);
|
|
214
531
|
}
|
|
215
532
|
async fetchRequirementStatuses(offerId) {
|
|
216
533
|
this.ensureAuthenticated();
|
|
217
534
|
return fetchRequirementStatuses(this.api, offerId);
|
|
218
535
|
}
|
|
536
|
+
async fetchPii() {
|
|
537
|
+
this.ensureAuthenticated();
|
|
538
|
+
return fetchPii(this.api);
|
|
539
|
+
}
|
|
540
|
+
async submitDocument(documentType, fields) {
|
|
541
|
+
this.ensureAuthenticated();
|
|
542
|
+
return submitDocument(this.api, documentType, fields);
|
|
543
|
+
}
|
|
544
|
+
async createKycToken(levelName, reset) {
|
|
545
|
+
this.ensureAuthenticated();
|
|
546
|
+
return createKycToken(this.api, levelName, reset);
|
|
547
|
+
}
|
|
219
548
|
handleRequirement(requirement) {
|
|
220
549
|
const baseUrl = this._config.coinlistBaseUrl ?? COINLIST_BASE_URL;
|
|
221
550
|
let path;
|
|
@@ -242,6 +571,9 @@ var CoinListClientImpl = class {
|
|
|
242
571
|
case "jurisdiction":
|
|
243
572
|
path = null;
|
|
244
573
|
break;
|
|
574
|
+
case "document":
|
|
575
|
+
path = null;
|
|
576
|
+
break;
|
|
245
577
|
default: {
|
|
246
578
|
const _exhaustive = requirement.type;
|
|
247
579
|
return;
|
|
@@ -269,7 +601,10 @@ function createCoinListClient(config) {
|
|
|
269
601
|
// src/client/CoinListProvider.tsx
|
|
270
602
|
import { jsx } from "react/jsx-runtime";
|
|
271
603
|
var CoinListContext = createContext(null);
|
|
272
|
-
function
|
|
604
|
+
function CoinListContextProvider({
|
|
605
|
+
config,
|
|
606
|
+
children
|
|
607
|
+
}) {
|
|
273
608
|
const [isReady, setIsReady] = useState(false);
|
|
274
609
|
const coinlist = useMemo(() => createCoinListClient(config), [config]);
|
|
275
610
|
useEffect(() => {
|
|
@@ -294,23 +629,69 @@ function CoinListProvider({ config, children }) {
|
|
|
294
629
|
const value = useMemo(() => ({ coinlist, isReady }), [coinlist, isReady]);
|
|
295
630
|
return /* @__PURE__ */ jsx(CoinListContext.Provider, { value, children });
|
|
296
631
|
}
|
|
632
|
+
var CoinListProvider = CoinListContextProvider;
|
|
633
|
+
|
|
634
|
+
// src/client/CoinListStyleScope.tsx
|
|
635
|
+
import { createContext as createContext2, useContext } from "react";
|
|
636
|
+
|
|
637
|
+
// src/client/generated/sdk-styles.gen.ts
|
|
638
|
+
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}}';
|
|
639
|
+
|
|
640
|
+
// src/client/CoinListStyleScope.tsx
|
|
641
|
+
import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
642
|
+
var ScopeContext = createContext2(false);
|
|
643
|
+
function CoinListStyleScope({ children }) {
|
|
644
|
+
const alreadyScoped = useContext(ScopeContext);
|
|
645
|
+
if (alreadyScoped) {
|
|
646
|
+
return /* @__PURE__ */ jsx2(Fragment, { children });
|
|
647
|
+
}
|
|
648
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
649
|
+
/* @__PURE__ */ jsx2("link", { rel: "preconnect", href: "https://fonts.googleapis.com" }),
|
|
650
|
+
/* @__PURE__ */ jsx2(
|
|
651
|
+
"link",
|
|
652
|
+
{
|
|
653
|
+
rel: "preconnect",
|
|
654
|
+
href: "https://fonts.gstatic.com",
|
|
655
|
+
crossOrigin: "anonymous"
|
|
656
|
+
}
|
|
657
|
+
),
|
|
658
|
+
/* @__PURE__ */ jsx2(
|
|
659
|
+
"link",
|
|
660
|
+
{
|
|
661
|
+
rel: "stylesheet",
|
|
662
|
+
href: "https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap"
|
|
663
|
+
}
|
|
664
|
+
),
|
|
665
|
+
/* @__PURE__ */ jsxs("div", { className: "clco-sdk-root", style: { display: "contents" }, children: [
|
|
666
|
+
/* @__PURE__ */ jsx2(
|
|
667
|
+
"style",
|
|
668
|
+
{
|
|
669
|
+
href: "clco-sdk-styles",
|
|
670
|
+
precedence: "default",
|
|
671
|
+
dangerouslySetInnerHTML: { __html: sdkStyles }
|
|
672
|
+
}
|
|
673
|
+
),
|
|
674
|
+
/* @__PURE__ */ jsx2(ScopeContext.Provider, { value: true, children })
|
|
675
|
+
] })
|
|
676
|
+
] });
|
|
677
|
+
}
|
|
297
678
|
|
|
298
679
|
// src/client/components/design-system/AlertBanner.tsx
|
|
299
680
|
import { CircleCheck, Info } from "lucide-react";
|
|
300
681
|
|
|
301
682
|
// src/client/components/design-system/tokens/typography.ts
|
|
302
683
|
var typeClasses = {
|
|
303
|
-
hero: "text-[64px] leading-[110%] font-semibold",
|
|
304
|
-
display: "text-[48px] leading-[110%] font-semibold",
|
|
305
|
-
h1: "text-[36px] leading-[120%] font-semibold",
|
|
306
|
-
h2: "text-[28px] leading-[125%] font-semibold",
|
|
307
|
-
h3: "text-[22px] leading-[130%] font-semibold",
|
|
308
|
-
h4: "text-[18px] leading-[135%] font-medium",
|
|
309
|
-
body: "text-[16px] leading-[150%] font-normal",
|
|
310
|
-
subhead: "text-[14px] leading-[150%] font-normal",
|
|
311
|
-
caption: "text-[12px] leading-[140%] font-normal",
|
|
312
|
-
label: "text-[14px] leading-[140%] font-medium",
|
|
313
|
-
data: "text-[14px] leading-[140%] font-normal"
|
|
684
|
+
hero: "clcosdk:text-[64px] clcosdk:leading-[110%] clcosdk:font-semibold",
|
|
685
|
+
display: "clcosdk:text-[48px] clcosdk:leading-[110%] clcosdk:font-semibold",
|
|
686
|
+
h1: "clcosdk:text-[36px] clcosdk:leading-[120%] clcosdk:font-semibold",
|
|
687
|
+
h2: "clcosdk:text-[28px] clcosdk:leading-[125%] clcosdk:font-semibold",
|
|
688
|
+
h3: "clcosdk:text-[22px] clcosdk:leading-[130%] clcosdk:font-semibold",
|
|
689
|
+
h4: "clcosdk:text-[18px] clcosdk:leading-[135%] clcosdk:font-medium",
|
|
690
|
+
body: "clcosdk:text-[16px] clcosdk:leading-[150%] clcosdk:font-normal",
|
|
691
|
+
subhead: "clcosdk:text-[14px] clcosdk:leading-[150%] clcosdk:font-normal",
|
|
692
|
+
caption: "clcosdk:text-[12px] clcosdk:leading-[140%] clcosdk:font-normal",
|
|
693
|
+
label: "clcosdk:text-[14px] clcosdk:leading-[140%] clcosdk:font-medium",
|
|
694
|
+
data: "clcosdk:text-[14px] clcosdk:leading-[140%] clcosdk:font-normal"
|
|
314
695
|
};
|
|
315
696
|
|
|
316
697
|
// src/client/components/design-system/utils.ts
|
|
@@ -320,26 +701,26 @@ function cn(...inputs) {
|
|
|
320
701
|
}
|
|
321
702
|
|
|
322
703
|
// src/client/components/design-system/AlertBanner.tsx
|
|
323
|
-
import { jsx as
|
|
704
|
+
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
324
705
|
var variantConfig = {
|
|
325
706
|
info: {
|
|
326
|
-
container: "bg-surface border-border",
|
|
327
|
-
text: "text-text-secondary",
|
|
707
|
+
container: "clcosdk:bg-surface clcosdk:border-border",
|
|
708
|
+
text: "clcosdk:text-text-secondary",
|
|
328
709
|
Icon: Info
|
|
329
710
|
},
|
|
330
711
|
success: {
|
|
331
|
-
container: "bg-success-subtle border-success-border",
|
|
332
|
-
text: "text-success",
|
|
712
|
+
container: "clcosdk:bg-success-subtle clcosdk:border-success-border",
|
|
713
|
+
text: "clcosdk:text-success",
|
|
333
714
|
Icon: CircleCheck
|
|
334
715
|
},
|
|
335
716
|
warning: {
|
|
336
|
-
container: "bg-warning-subtle border-warning-border",
|
|
337
|
-
text: "text-warning",
|
|
717
|
+
container: "clcosdk:bg-warning-subtle clcosdk:border-warning-border",
|
|
718
|
+
text: "clcosdk:text-warning",
|
|
338
719
|
Icon: Info
|
|
339
720
|
},
|
|
340
721
|
error: {
|
|
341
|
-
container: "bg-error-subtle border-error-border",
|
|
342
|
-
text: "text-error",
|
|
722
|
+
container: "clcosdk:bg-error-subtle clcosdk:border-error-border",
|
|
723
|
+
text: "clcosdk:text-error",
|
|
343
724
|
Icon: Info
|
|
344
725
|
}
|
|
345
726
|
};
|
|
@@ -350,18 +731,24 @@ function AlertBanner({
|
|
|
350
731
|
className
|
|
351
732
|
}) {
|
|
352
733
|
const { container, text, Icon } = variantConfig[variant];
|
|
353
|
-
return /* @__PURE__ */
|
|
734
|
+
return /* @__PURE__ */ jsxs2(
|
|
354
735
|
"div",
|
|
355
736
|
{
|
|
356
737
|
className: cn(
|
|
357
|
-
"flex items-center rounded-btn border p-3",
|
|
358
|
-
icon && "gap-2",
|
|
738
|
+
"clcosdk:flex clcosdk:items-center clcosdk:rounded-btn clcosdk:border clcosdk:p-3",
|
|
739
|
+
icon && "clcosdk:gap-2",
|
|
359
740
|
container,
|
|
360
741
|
className
|
|
361
742
|
),
|
|
362
743
|
children: [
|
|
363
|
-
icon && /* @__PURE__ */
|
|
364
|
-
|
|
744
|
+
icon && /* @__PURE__ */ jsx3(
|
|
745
|
+
Icon,
|
|
746
|
+
{
|
|
747
|
+
className: cn("clcosdk:h-4 clcosdk:w-4 clcosdk:shrink-0", text),
|
|
748
|
+
"aria-hidden": "true"
|
|
749
|
+
}
|
|
750
|
+
),
|
|
751
|
+
/* @__PURE__ */ jsx3("p", { className: cn(typeClasses.subhead, text), children: content })
|
|
365
752
|
]
|
|
366
753
|
}
|
|
367
754
|
);
|
|
@@ -369,31 +756,31 @@ function AlertBanner({
|
|
|
369
756
|
|
|
370
757
|
// src/client/components/design-system/CloseButton.tsx
|
|
371
758
|
import { X } from "lucide-react";
|
|
372
|
-
import { jsx as
|
|
759
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
373
760
|
function CloseButton({
|
|
374
761
|
onClick,
|
|
375
762
|
"aria-label": ariaLabel = "Close",
|
|
376
763
|
className
|
|
377
764
|
}) {
|
|
378
|
-
return /* @__PURE__ */
|
|
765
|
+
return /* @__PURE__ */ jsx4(
|
|
379
766
|
"button",
|
|
380
767
|
{
|
|
381
768
|
type: "button",
|
|
382
769
|
onClick,
|
|
383
770
|
"aria-label": ariaLabel,
|
|
384
771
|
className: cn(
|
|
385
|
-
"cursor-pointer rounded-full p-1.5 text-text-secondary transition-colors hover:bg-surface hover:text-text-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-gray-400 focus-visible:ring-offset-2",
|
|
772
|
+
"clcosdk:cursor-pointer clcosdk:rounded-full clcosdk:p-1.5 clcosdk:text-text-secondary clcosdk:transition-colors clcosdk:hover:bg-surface clcosdk:hover:text-text-primary clcosdk:focus-visible:outline-none clcosdk:focus-visible:ring-2 clcosdk:focus-visible:ring-gray-400 clcosdk:focus-visible:ring-offset-2",
|
|
386
773
|
className
|
|
387
774
|
),
|
|
388
|
-
children: /* @__PURE__ */
|
|
775
|
+
children: /* @__PURE__ */ jsx4(X, { className: "clcosdk:h-5 clcosdk:w-5" })
|
|
389
776
|
}
|
|
390
777
|
);
|
|
391
778
|
}
|
|
392
779
|
|
|
393
780
|
// src/client/components/design-system/logos/CoinListWordmark.tsx
|
|
394
|
-
import { jsx as
|
|
781
|
+
import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
395
782
|
function CoinListWordmark(props) {
|
|
396
|
-
return /* @__PURE__ */
|
|
783
|
+
return /* @__PURE__ */ jsxs3(
|
|
397
784
|
"svg",
|
|
398
785
|
{
|
|
399
786
|
width: "638",
|
|
@@ -404,35 +791,35 @@ function CoinListWordmark(props) {
|
|
|
404
791
|
"aria-hidden": "true",
|
|
405
792
|
...props,
|
|
406
793
|
children: [
|
|
407
|
-
/* @__PURE__ */
|
|
794
|
+
/* @__PURE__ */ jsx5(
|
|
408
795
|
"path",
|
|
409
796
|
{
|
|
410
797
|
d: "M68.7724 123.966C74.8226 124.172 80.7696 123.519 86.5104 121.799C97.4076 118.531 106.551 112.58 113.942 103.947C113.942 103.947 113.942 103.947 113.908 103.912C111.879 102.193 109.851 100.507 107.857 98.8218L105.829 97.1363C105.451 96.8268 105.107 96.5172 104.729 96.2076C103.939 95.5197 103.148 94.8662 102.323 94.2126C95.3107 98.8562 87.6104 101.539 79.1196 101.883C74.8569 102.055 70.6287 101.642 66.5036 100.507C59.5252 98.6154 53.2688 95.1757 48.2499 89.7755C39.1059 79.938 35.8745 68.1743 38.2465 55.0348C39.7246 46.9172 43.4373 40.0723 49.1093 34.5C47.9061 34.7408 46.703 35.016 45.5342 35.3943C36.5277 38.2148 29.6181 43.6839 24.6336 51.6639C20.6803 58.0273 18.5834 64.9411 18.3428 72.4739C18.2053 76.7047 18.4803 80.7979 19.4428 84.7879C22.5023 97.2395 29.3087 107.043 39.6903 114.335H39.7934V114.403C40.1372 114.644 40.4809 114.919 40.8247 115.16C49.2812 120.801 58.5971 123.691 68.7724 124.035V123.966Z",
|
|
411
798
|
fill: "currentColor"
|
|
412
799
|
}
|
|
413
800
|
),
|
|
414
|
-
/* @__PURE__ */
|
|
801
|
+
/* @__PURE__ */ jsx5(
|
|
415
802
|
"path",
|
|
416
803
|
{
|
|
417
804
|
d: "M72.2101 89.052C68.1881 90.8406 64.0286 91.8725 59.6973 92.2165C64.9912 95.209 70.8007 96.688 77.1259 96.8256C79.1885 96.86 81.251 96.6536 83.4167 96.3097C88.745 95.4841 93.6951 93.5579 98.3015 90.7374C93.9358 87.057 89.6044 83.4109 85.2386 79.7305C81.526 83.6861 77.1946 86.8506 72.2101 89.052Z",
|
|
418
805
|
fill: "currentColor"
|
|
419
806
|
}
|
|
420
807
|
),
|
|
421
|
-
/* @__PURE__ */
|
|
808
|
+
/* @__PURE__ */ jsx5(
|
|
422
809
|
"path",
|
|
423
810
|
{
|
|
424
811
|
d: "M66.9848 0.241609C66.4348 0.276006 65.8848 0.344799 65.3691 0.413592C70.663 1.4111 75.7851 3.13093 80.6321 5.71068C90.0511 10.7326 97.3732 17.9215 102.289 27.4494L104.936 25.1448C107.652 22.7714 110.368 20.3981 113.084 18.0247C106.655 11.1797 99.092 6.15784 90.223 3.06214C84.3103 0.998336 78.2601 -0.0335643 72.0381 0.000832319C70.388 0.000832319 68.7036 0.138419 66.9848 0.241609Z",
|
|
425
812
|
fill: "currentColor"
|
|
426
813
|
}
|
|
427
814
|
),
|
|
428
|
-
/* @__PURE__ */
|
|
815
|
+
/* @__PURE__ */ jsx5(
|
|
429
816
|
"path",
|
|
430
817
|
{
|
|
431
818
|
d: "M25.4242 107.871C17.4833 97.9988 13.1519 86.7167 13.2207 73.818C13.2207 67.317 14.5614 61.0568 17.1396 55.1062C20.9553 46.2662 26.9711 39.1805 35.4276 34.2962C43.3685 29.687 51.9968 27.8984 61.1752 29.2743C70.5943 30.7189 78.3976 35.2249 84.6541 42.2762C84.6541 42.2762 84.8603 42.5514 84.9634 42.6546C85.8916 41.8291 86.8541 41.0035 87.7823 40.178L88.9167 39.1805C89.8792 38.355 90.8417 37.4951 91.8043 36.6696C94.0043 34.7434 96.17 32.8515 98.3357 30.9253C94.1075 22.223 87.7479 15.55 79.3258 10.8377C69.3911 5.26541 58.7002 3.54557 47.3904 5.02463C41.7528 5.78136 36.3557 7.50119 31.1993 10.0465C13.702 18.7145 1.08597 36.532 0.0546833 58.4771C-0.117196 62.0887 0.123436 65.7348 0.673452 69.3464C2.04849 78.3239 5.34859 86.4759 10.6425 93.8368C14.7676 99.5123 19.6834 104.19 25.3898 107.871H25.4242Z",
|
|
432
819
|
fill: "currentColor"
|
|
433
820
|
}
|
|
434
821
|
),
|
|
435
|
-
/* @__PURE__ */
|
|
822
|
+
/* @__PURE__ */ jsx5(
|
|
436
823
|
"path",
|
|
437
824
|
{
|
|
438
825
|
fillRule: "evenodd",
|
|
@@ -447,18 +834,18 @@ function CoinListWordmark(props) {
|
|
|
447
834
|
}
|
|
448
835
|
|
|
449
836
|
// src/client/components/design-system/PoweredByCoinList.tsx
|
|
450
|
-
import { jsx as
|
|
837
|
+
import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
451
838
|
function PoweredByCoinList({ className }) {
|
|
452
|
-
return /* @__PURE__ */
|
|
839
|
+
return /* @__PURE__ */ jsxs4(
|
|
453
840
|
"div",
|
|
454
841
|
{
|
|
455
842
|
className: cn(
|
|
456
|
-
"flex items-center justify-center gap-[5px] text-text-secondary",
|
|
843
|
+
"clcosdk:flex clcosdk:items-center clcosdk:justify-center clcosdk:gap-[5px] clcosdk:text-text-secondary",
|
|
457
844
|
className
|
|
458
845
|
),
|
|
459
846
|
children: [
|
|
460
|
-
/* @__PURE__ */
|
|
461
|
-
/* @__PURE__ */
|
|
847
|
+
/* @__PURE__ */ jsx6("span", { className: cn(typeClasses.caption, "clcosdk:tracking-[0.12px]"), children: "Powered by" }),
|
|
848
|
+
/* @__PURE__ */ jsx6(CoinListWordmark, { className: "clcosdk:h-3 clcosdk:w-auto" })
|
|
462
849
|
]
|
|
463
850
|
}
|
|
464
851
|
);
|
|
@@ -467,48 +854,48 @@ function PoweredByCoinList({ className }) {
|
|
|
467
854
|
// src/client/components/design-system/ClButton.tsx
|
|
468
855
|
import { cva } from "class-variance-authority";
|
|
469
856
|
import { forwardRef } from "react";
|
|
470
|
-
import { jsx as
|
|
857
|
+
import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
471
858
|
var buttonVariants = cva(
|
|
472
|
-
"inline-flex items-center justify-center gap-3 whitespace-nowrap transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-40 cursor-pointer",
|
|
859
|
+
"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",
|
|
473
860
|
{
|
|
474
861
|
variants: {
|
|
475
862
|
variant: {
|
|
476
863
|
// Primary — tokens auto-switch: dark bg (#171717) → light bg (#f4f4f5) in dark mode
|
|
477
|
-
primary: "bg-brand-primary text-text-inverse font-semibold hover:bg-brand-primary-hover active:bg-brand-primary-active focus-visible:ring-gray-500",
|
|
864
|
+
primary: "clcosdk:bg-brand-primary clcosdk:text-text-inverse clcosdk:font-semibold clcosdk:hover:bg-brand-primary-hover clcosdk:active:bg-brand-primary-active clcosdk:focus-visible:ring-gray-500",
|
|
478
865
|
// Secondary — bg-section, border-border, text-text-primary all auto-switch
|
|
479
866
|
// hover maps to border token value; active has no token so uses dark: override
|
|
480
|
-
secondary: "bg-section border border-border text-text-primary font-medium hover:bg-border active:bg-[#d9d9d9] dark:active:bg-divider focus-visible:ring-gray-400",
|
|
867
|
+
secondary: "clcosdk:bg-section clcosdk:border clcosdk:border-border clcosdk:text-text-primary clcosdk:font-medium clcosdk:hover:bg-border clcosdk:active:bg-[#d9d9d9] clcosdk:dark:active:bg-divider clcosdk:focus-visible:ring-gray-400",
|
|
481
868
|
// Destructive — error tokens auto-switch to translucent dark equivalents
|
|
482
869
|
// hover/active have no tokens so use dark: overrides
|
|
483
|
-
destructive: "bg-error-subtle border border-error-border text-error font-semibold hover:bg-[#fcdcd8] active:bg-[#f9c9c4] dark:hover:bg-[rgba(248,113,113,0.20)] dark:active:bg-[rgba(248,113,113,0.30)] focus-visible:ring-red-400",
|
|
870
|
+
destructive: "clcosdk:bg-error-subtle clcosdk:border clcosdk:border-error-border clcosdk:text-error clcosdk:font-semibold clcosdk:hover:bg-[#fcdcd8] clcosdk:active:bg-[#f9c9c4] clcosdk:dark:hover:bg-[rgba(248,113,113,0.20)] clcosdk:dark:active:bg-[rgba(248,113,113,0.30)] clcosdk:focus-visible:ring-red-400",
|
|
484
871
|
// Ghost — transparent base; hover/active use section/border tokens (auto-switch)
|
|
485
|
-
ghost: "bg-transparent text-text-primary font-medium hover:bg-section active:bg-border focus-visible:ring-gray-400",
|
|
872
|
+
ghost: "clcosdk:bg-transparent clcosdk:text-text-primary clcosdk:font-medium clcosdk:hover:bg-section clcosdk:active:bg-border clcosdk:focus-visible:ring-gray-400",
|
|
486
873
|
// Link — text-text-primary auto-switches light/dark
|
|
487
|
-
link: "h-auto p-0 text-text-primary font-medium underline-offset-4 hover:underline focus-visible:ring-gray-500",
|
|
874
|
+
link: "clcosdk:h-auto clcosdk:p-0 clcosdk:text-text-primary clcosdk:font-medium clcosdk:underline-offset-4 clcosdk:hover:underline clcosdk:focus-visible:ring-gray-500",
|
|
488
875
|
// Destructive link — text-error auto-switches (#b42318 → #f87171 in dark)
|
|
489
|
-
destructiveLink: "h-auto p-0 text-error font-medium hover:text-[#8b1a13] active:text-[#6d1510] dark:hover:text-[#fca5a5] dark:active:text-[#f87171] focus-visible:ring-red-500"
|
|
876
|
+
destructiveLink: "clcosdk:h-auto clcosdk:p-0 clcosdk:text-error clcosdk:font-medium clcosdk:hover:text-[#8b1a13] clcosdk:active:text-[#6d1510] clcosdk:dark:hover:text-[#fca5a5] clcosdk:dark:active:text-[#f87171] clcosdk:focus-visible:ring-red-500"
|
|
490
877
|
},
|
|
491
878
|
size: {
|
|
492
|
-
sm: "h-9 px-4 text-sm tracking-[0.28px]",
|
|
493
|
-
default: "h-11 px-5 text-sm tracking-[0.28px]",
|
|
494
|
-
lg: "h-14 px-6 text-base",
|
|
495
|
-
icon: "h-12 w-12"
|
|
879
|
+
sm: "clcosdk:h-9 clcosdk:px-4 clcosdk:text-sm clcosdk:tracking-[0.28px]",
|
|
880
|
+
default: "clcosdk:h-11 clcosdk:px-5 clcosdk:text-sm clcosdk:tracking-[0.28px]",
|
|
881
|
+
lg: "clcosdk:h-14 clcosdk:px-6 clcosdk:text-base",
|
|
882
|
+
icon: "clcosdk:h-12 clcosdk:w-12"
|
|
496
883
|
},
|
|
497
884
|
radius: {
|
|
498
|
-
pill: "rounded-full",
|
|
885
|
+
pill: "clcosdk:rounded-full",
|
|
499
886
|
// compound variants below handle size-specific radii
|
|
500
887
|
rounded: ""
|
|
501
888
|
},
|
|
502
889
|
fullWidth: {
|
|
503
|
-
true: "w-full",
|
|
890
|
+
true: "clcosdk:w-full",
|
|
504
891
|
false: ""
|
|
505
892
|
}
|
|
506
893
|
},
|
|
507
894
|
compoundVariants: [
|
|
508
|
-
{ size: "sm", radius: "rounded", className: "rounded-lg" },
|
|
509
|
-
{ size: "default", radius: "rounded", className: "rounded-2xl" },
|
|
510
|
-
{ size: "lg", radius: "rounded", className: "rounded-2xl" },
|
|
511
|
-
{ size: "icon", radius: "rounded", className: "rounded-md" }
|
|
895
|
+
{ size: "sm", radius: "rounded", className: "clcosdk:rounded-lg" },
|
|
896
|
+
{ size: "default", radius: "rounded", className: "clcosdk:rounded-2xl" },
|
|
897
|
+
{ size: "lg", radius: "rounded", className: "clcosdk:rounded-2xl" },
|
|
898
|
+
{ size: "icon", radius: "rounded", className: "clcosdk:rounded-md" }
|
|
512
899
|
],
|
|
513
900
|
defaultVariants: {
|
|
514
901
|
variant: "primary",
|
|
@@ -534,7 +921,7 @@ var ClButton = forwardRef(
|
|
|
534
921
|
...props
|
|
535
922
|
}, ref) => {
|
|
536
923
|
const isDisabled = disabled || isLoading;
|
|
537
|
-
return /* @__PURE__ */
|
|
924
|
+
return /* @__PURE__ */ jsxs5(
|
|
538
925
|
"button",
|
|
539
926
|
{
|
|
540
927
|
className: cn(
|
|
@@ -545,16 +932,16 @@ var ClButton = forwardRef(
|
|
|
545
932
|
disabled: isDisabled,
|
|
546
933
|
...props,
|
|
547
934
|
children: [
|
|
548
|
-
isLoading && /* @__PURE__ */
|
|
935
|
+
isLoading && /* @__PURE__ */ jsx7(
|
|
549
936
|
"span",
|
|
550
937
|
{
|
|
551
|
-
className: "h-4 w-4 shrink-0 animate-spin rounded-full border-2 border-current border-t-transparent opacity-60",
|
|
938
|
+
className: "clcosdk:h-4 clcosdk:w-4 clcosdk:shrink-0 clcosdk:animate-spin clcosdk:rounded-full clcosdk:border-2 clcosdk:border-current clcosdk:border-t-transparent clcosdk:opacity-60",
|
|
552
939
|
"aria-hidden": "true"
|
|
553
940
|
}
|
|
554
941
|
),
|
|
555
|
-
startIcon && !isLoading && /* @__PURE__ */
|
|
556
|
-
/* @__PURE__ */
|
|
557
|
-
endIcon && !isLoading && /* @__PURE__ */
|
|
942
|
+
startIcon && !isLoading && /* @__PURE__ */ jsx7("span", { className: "clcosdk:shrink-0", children: startIcon }),
|
|
943
|
+
/* @__PURE__ */ jsx7("span", { className: cn(isLoading && "clcosdk:opacity-60"), children: isLoading && loadingText ? loadingText : children }),
|
|
944
|
+
endIcon && !isLoading && /* @__PURE__ */ jsx7("span", { className: "clcosdk:shrink-0", children: endIcon })
|
|
558
945
|
]
|
|
559
946
|
}
|
|
560
947
|
);
|
|
@@ -563,9 +950,9 @@ var ClButton = forwardRef(
|
|
|
563
950
|
ClButton.displayName = "ClButton";
|
|
564
951
|
|
|
565
952
|
// src/client/components/design-system/logos/CoinListLogomark.tsx
|
|
566
|
-
import { jsx as
|
|
953
|
+
import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
567
954
|
function CoinListLogomark(props) {
|
|
568
|
-
return /* @__PURE__ */
|
|
955
|
+
return /* @__PURE__ */ jsxs6(
|
|
569
956
|
"svg",
|
|
570
957
|
{
|
|
571
958
|
width: "115",
|
|
@@ -576,28 +963,28 @@ function CoinListLogomark(props) {
|
|
|
576
963
|
"aria-hidden": "true",
|
|
577
964
|
...props,
|
|
578
965
|
children: [
|
|
579
|
-
/* @__PURE__ */
|
|
966
|
+
/* @__PURE__ */ jsx8(
|
|
580
967
|
"path",
|
|
581
968
|
{
|
|
582
969
|
d: "M69.7519 123.966C75.8021 124.172 81.7491 123.519 87.4899 121.799C98.3871 118.531 107.531 112.58 114.922 103.947C114.922 103.947 114.922 103.947 114.888 103.912C112.859 102.193 110.831 100.507 108.837 98.8218L106.809 97.1363C106.431 96.8268 106.087 96.5172 105.709 96.2076C104.919 95.5197 104.128 94.8662 103.303 94.2126C96.2902 98.8562 88.5899 101.539 80.0991 101.883C75.8364 102.055 71.6082 101.642 67.4831 100.507C60.5047 98.6154 54.2483 95.1757 49.2294 89.7755C40.0854 79.938 36.854 68.1743 39.226 55.0348C40.7041 46.9172 44.4168 40.0723 50.0888 34.5C48.8856 34.7408 47.6825 35.016 46.5137 35.3943C37.5072 38.2148 30.5976 43.6839 25.6131 51.6639C21.6598 58.0273 19.5629 64.9411 19.3223 72.4739C19.1848 76.7047 19.4598 80.7979 20.4223 84.7879C23.4818 97.2395 30.2882 107.043 40.6698 114.335H40.7729V114.403C41.1167 114.644 41.4604 114.919 41.8042 115.16C50.2607 120.801 59.5766 123.691 69.7519 124.035V123.966Z",
|
|
583
970
|
fill: "currentColor"
|
|
584
971
|
}
|
|
585
972
|
),
|
|
586
|
-
/* @__PURE__ */
|
|
973
|
+
/* @__PURE__ */ jsx8(
|
|
587
974
|
"path",
|
|
588
975
|
{
|
|
589
976
|
d: "M73.1896 89.052C69.1676 90.8406 65.0081 91.8725 60.6768 92.2165C65.9707 95.209 71.7802 96.688 78.1054 96.8256C80.168 96.86 82.2305 96.6536 84.3962 96.3097C89.7245 95.4841 94.6746 93.5579 99.281 90.7374C94.9153 87.057 90.5839 83.4109 86.2181 79.7305C82.5055 83.6861 78.1741 86.8506 73.1896 89.052Z",
|
|
590
977
|
fill: "currentColor"
|
|
591
978
|
}
|
|
592
979
|
),
|
|
593
|
-
/* @__PURE__ */
|
|
980
|
+
/* @__PURE__ */ jsx8(
|
|
594
981
|
"path",
|
|
595
982
|
{
|
|
596
983
|
d: "M67.9643 0.241609C67.4143 0.276006 66.8643 0.344799 66.3486 0.413592C71.6425 1.4111 76.7646 3.13093 81.6116 5.71068C91.0306 10.7326 98.3527 17.9215 103.268 27.4494L105.915 25.1448C108.631 22.7714 111.347 20.3981 114.063 18.0247C107.634 11.1797 100.072 6.15784 91.2025 3.06214C85.2898 0.998336 79.2396 -0.0335643 73.0176 0.000832322C71.3675 0.000832322 69.6831 0.138419 67.9643 0.241609Z",
|
|
597
984
|
fill: "currentColor"
|
|
598
985
|
}
|
|
599
986
|
),
|
|
600
|
-
/* @__PURE__ */
|
|
987
|
+
/* @__PURE__ */ jsx8(
|
|
601
988
|
"path",
|
|
602
989
|
{
|
|
603
990
|
d: "M26.4037 107.871C18.4628 97.9988 14.1314 86.7167 14.2002 73.818C14.2002 67.317 15.5409 61.0568 18.1191 55.1062C21.9348 46.2662 27.9506 39.1805 36.4071 34.2962C44.348 29.687 52.9763 27.8984 62.1547 29.2743C71.5738 30.7189 79.3771 35.2249 85.6336 42.2762C85.6336 42.2762 85.8398 42.5514 85.9429 42.6546C86.8711 41.8291 87.8336 41.0035 88.7618 40.178L89.8962 39.1805C90.8587 38.355 91.8212 37.4951 92.7838 36.6696C94.9838 34.7434 97.1495 32.8515 99.3152 30.9253C95.087 22.223 88.7274 15.55 80.3053 10.8377C70.3706 5.26541 59.6797 3.54557 48.37 5.02463C42.7323 5.78136 37.3352 7.50119 32.1788 10.0465C14.6815 18.7145 2.06546 36.532 1.03418 58.4771C0.862296 62.0887 1.10293 65.7348 1.65294 69.3464C3.02798 78.3239 6.32808 86.4759 11.622 93.8368C15.7471 99.5123 20.6629 104.19 26.3693 107.871H26.4037Z",
|
|
@@ -610,7 +997,7 @@ function CoinListLogomark(props) {
|
|
|
610
997
|
}
|
|
611
998
|
|
|
612
999
|
// src/client/components/oauth/CoinListSignInButton.tsx
|
|
613
|
-
import { jsx as
|
|
1000
|
+
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
614
1001
|
function CoinListSignInButton({
|
|
615
1002
|
onClick,
|
|
616
1003
|
disabled = false,
|
|
@@ -618,7 +1005,7 @@ function CoinListSignInButton({
|
|
|
618
1005
|
isLoading = false,
|
|
619
1006
|
className
|
|
620
1007
|
}) {
|
|
621
|
-
return /* @__PURE__ */
|
|
1008
|
+
return /* @__PURE__ */ jsx9(
|
|
622
1009
|
ClButton,
|
|
623
1010
|
{
|
|
624
1011
|
variant: "primary",
|
|
@@ -628,7 +1015,7 @@ function CoinListSignInButton({
|
|
|
628
1015
|
disabled,
|
|
629
1016
|
isLoading,
|
|
630
1017
|
loadingText: "Signing in...",
|
|
631
|
-
startIcon: /* @__PURE__ */
|
|
1018
|
+
startIcon: /* @__PURE__ */ jsx9(CoinListLogomark, { className: "clcosdk:h-[18px] clcosdk:w-[16px] clcosdk:shrink-0" }),
|
|
632
1019
|
className,
|
|
633
1020
|
children: "Continue with CoinList"
|
|
634
1021
|
}
|
|
@@ -636,9 +1023,9 @@ function CoinListSignInButton({
|
|
|
636
1023
|
}
|
|
637
1024
|
|
|
638
1025
|
// src/client/hooks/useCoinList.ts
|
|
639
|
-
import { useContext } from "react";
|
|
1026
|
+
import { useContext as useContext2 } from "react";
|
|
640
1027
|
function useCoinList() {
|
|
641
|
-
const context =
|
|
1028
|
+
const context = useContext2(CoinListContext);
|
|
642
1029
|
if (context === null) {
|
|
643
1030
|
throw new CoinListClientInitializationError();
|
|
644
1031
|
}
|
|
@@ -655,7 +1042,7 @@ var CoinListClientInitializationError = class extends Error {
|
|
|
655
1042
|
};
|
|
656
1043
|
|
|
657
1044
|
// src/client/components/oauth/CoinListSignInCard.tsx
|
|
658
|
-
import { jsx as
|
|
1045
|
+
import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
659
1046
|
function CoinListSignInCard({
|
|
660
1047
|
state = "idle",
|
|
661
1048
|
onSignIn,
|
|
@@ -666,37 +1053,50 @@ function CoinListSignInCard({
|
|
|
666
1053
|
const handleSignIn = onSignIn ?? (() => {
|
|
667
1054
|
void coinlist.startOAuth();
|
|
668
1055
|
});
|
|
669
|
-
return /* @__PURE__ */
|
|
1056
|
+
return /* @__PURE__ */ jsx10(CoinListStyleScope, { children: /* @__PURE__ */ jsxs7(
|
|
670
1057
|
"div",
|
|
671
1058
|
{
|
|
672
1059
|
className: cn(
|
|
673
|
-
"relative flex w-full max-w-md flex-col rounded-card border border-border bg-background p-6 shadow-card",
|
|
1060
|
+
"clcosdk:relative clcosdk:flex clcosdk:w-full clcosdk:max-w-md clcosdk:flex-col clcosdk:rounded-card clcosdk:border clcosdk:border-border clcosdk:bg-background clcosdk:p-6 clcosdk:shadow-card",
|
|
674
1061
|
className
|
|
675
1062
|
),
|
|
676
1063
|
children: [
|
|
677
|
-
onClose && /* @__PURE__ */
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
1064
|
+
onClose && /* @__PURE__ */ jsx10(
|
|
1065
|
+
CloseButton,
|
|
1066
|
+
{
|
|
1067
|
+
onClick: onClose,
|
|
1068
|
+
className: "clcosdk:absolute clcosdk:right-4 clcosdk:top-4"
|
|
1069
|
+
}
|
|
1070
|
+
),
|
|
1071
|
+
/* @__PURE__ */ jsxs7("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-2", children: [
|
|
1072
|
+
/* @__PURE__ */ jsx10("h3", { className: cn(typeClasses.h3, "clcosdk:text-text-primary"), children: "Sign in to participate" }),
|
|
1073
|
+
/* @__PURE__ */ jsx10("p", { className: cn(typeClasses.body, "clcosdk:text-text-secondary"), children: "A CoinList account is required to participate in this sale." })
|
|
681
1074
|
] }),
|
|
682
|
-
/* @__PURE__ */
|
|
683
|
-
|
|
1075
|
+
/* @__PURE__ */ jsx10(
|
|
1076
|
+
CoinListSignInButton,
|
|
1077
|
+
{
|
|
1078
|
+
onClick: handleSignIn,
|
|
1079
|
+
fullWidth: true,
|
|
1080
|
+
className: "clcosdk:mt-4"
|
|
1081
|
+
}
|
|
1082
|
+
),
|
|
1083
|
+
state === "error" && /* @__PURE__ */ jsx10(
|
|
684
1084
|
AlertBanner,
|
|
685
1085
|
{
|
|
686
1086
|
variant: "error",
|
|
687
1087
|
icon: true,
|
|
688
1088
|
content: "Error signing in. Please try again.",
|
|
689
|
-
className: "mt-4"
|
|
1089
|
+
className: "clcosdk:mt-4"
|
|
690
1090
|
}
|
|
691
1091
|
),
|
|
692
|
-
/* @__PURE__ */
|
|
1092
|
+
/* @__PURE__ */ jsx10(PoweredByCoinList, { className: "clcosdk:mt-4" })
|
|
693
1093
|
]
|
|
694
1094
|
}
|
|
695
|
-
);
|
|
1095
|
+
) });
|
|
696
1096
|
}
|
|
697
1097
|
|
|
698
1098
|
// src/client/components/offers/OfferCard.tsx
|
|
699
|
-
import { Fragment, jsx as
|
|
1099
|
+
import { Fragment as Fragment2, jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
700
1100
|
var monthYearFormatter = new Intl.DateTimeFormat("en-US", {
|
|
701
1101
|
month: "short",
|
|
702
1102
|
year: "numeric"
|
|
@@ -717,46 +1117,67 @@ function OfferCard({
|
|
|
717
1117
|
containerClassName
|
|
718
1118
|
}) {
|
|
719
1119
|
const cardLabel = "Open offer details";
|
|
720
|
-
const cardContent = /* @__PURE__ */
|
|
721
|
-
/* @__PURE__ */
|
|
722
|
-
offer.bannerUrl ? /* @__PURE__ */
|
|
1120
|
+
const cardContent = /* @__PURE__ */ jsxs8(Fragment2, { children: [
|
|
1121
|
+
/* @__PURE__ */ jsxs8("div", { className: "clcosdk:relative clcosdk:mb-6 clcosdk:h-52 clcosdk:w-full clcosdk:overflow-hidden clcosdk:rounded-2xl clcosdk:border clcosdk:border-border/60 clcosdk:bg-section", children: [
|
|
1122
|
+
offer.bannerUrl ? /* @__PURE__ */ jsx11(
|
|
723
1123
|
"img",
|
|
724
1124
|
{
|
|
725
1125
|
src: offer.bannerUrl,
|
|
726
1126
|
alt: "Offer banner",
|
|
727
|
-
className: "h-full w-full object-cover"
|
|
1127
|
+
className: "clcosdk:h-full clcosdk:w-full clcosdk:object-cover"
|
|
728
1128
|
}
|
|
729
|
-
) : /* @__PURE__ */
|
|
730
|
-
/* @__PURE__ */
|
|
731
|
-
/* @__PURE__ */
|
|
1129
|
+
) : /* @__PURE__ */ jsx11("div", { className: "clcosdk:h-full clcosdk:w-full clcosdk:bg-gradient-to-br clcosdk:from-surface clcosdk:via-section clcosdk:to-background" }),
|
|
1130
|
+
/* @__PURE__ */ jsx11("div", { className: "clcosdk:absolute clcosdk:inset-0 clcosdk:bg-gradient-to-b clcosdk:from-transparent clcosdk:via-transparent clcosdk:to-overlay/35" }),
|
|
1131
|
+
/* @__PURE__ */ jsx11("div", { className: "clcosdk:absolute clcosdk:inset-0 clcosdk:flex clcosdk:items-center clcosdk:justify-center clcosdk:p-6", children: offer.logoUrl ? /* @__PURE__ */ jsx11(
|
|
732
1132
|
"img",
|
|
733
1133
|
{
|
|
734
1134
|
src: offer.logoUrl,
|
|
735
1135
|
alt: "Offer logo",
|
|
736
|
-
className: "h-28 w-28 rounded-full border border-border bg-surface object-cover shadow-[0_10px_24px_rgba(0,0,0,0.25)]"
|
|
1136
|
+
className: "clcosdk:h-28 clcosdk:w-28 clcosdk:rounded-full clcosdk:border clcosdk:border-border clcosdk:bg-surface clcosdk:object-cover clcosdk:shadow-[0_10px_24px_rgba(0,0,0,0.25)]"
|
|
737
1137
|
}
|
|
738
|
-
) : /* @__PURE__ */
|
|
1138
|
+
) : /* @__PURE__ */ jsx11("div", { className: "clcosdk:h-28 clcosdk:w-28 clcosdk:rounded-full clcosdk:border clcosdk:border-border clcosdk:bg-surface clcosdk:shadow-[0_10px_24px_rgba(0,0,0,0.18)]" }) })
|
|
739
1139
|
] }),
|
|
740
|
-
offer.tagline && /* @__PURE__ */
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
1140
|
+
offer.tagline && /* @__PURE__ */ jsx11(
|
|
1141
|
+
"p",
|
|
1142
|
+
{
|
|
1143
|
+
className: cn(
|
|
1144
|
+
typeClasses.h3,
|
|
1145
|
+
"clcosdk:min-h-[2.4rem] clcosdk:text-text-primary"
|
|
1146
|
+
),
|
|
1147
|
+
children: offer.tagline
|
|
1148
|
+
}
|
|
1149
|
+
),
|
|
1150
|
+
/* @__PURE__ */ jsxs8("div", { className: "clcosdk:mt-4 clcosdk:grid clcosdk:grid-cols-2 clcosdk:gap-5 clcosdk:border-t clcosdk:border-divider clcosdk:pt-4", children: [
|
|
1151
|
+
/* @__PURE__ */ jsxs8("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-1", children: [
|
|
1152
|
+
/* @__PURE__ */ jsx11(
|
|
1153
|
+
"span",
|
|
1154
|
+
{
|
|
1155
|
+
className: cn(typeClasses.subhead, "clcosdk:text-text-secondary"),
|
|
1156
|
+
children: "Starts"
|
|
1157
|
+
}
|
|
1158
|
+
),
|
|
1159
|
+
/* @__PURE__ */ jsx11("span", { className: cn(typeClasses.label, "clcosdk:text-text-primary"), children: offer.formattedStartsAt })
|
|
745
1160
|
] }),
|
|
746
|
-
/* @__PURE__ */
|
|
747
|
-
/* @__PURE__ */
|
|
748
|
-
|
|
1161
|
+
/* @__PURE__ */ jsxs8("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-1", children: [
|
|
1162
|
+
/* @__PURE__ */ jsx11(
|
|
1163
|
+
"span",
|
|
1164
|
+
{
|
|
1165
|
+
className: cn(typeClasses.subhead, "clcosdk:text-text-secondary"),
|
|
1166
|
+
children: "Ends"
|
|
1167
|
+
}
|
|
1168
|
+
),
|
|
1169
|
+
/* @__PURE__ */ jsx11("span", { className: cn(typeClasses.label, "clcosdk:text-text-primary"), children: offer.formattedEndsAt })
|
|
749
1170
|
] })
|
|
750
1171
|
] })
|
|
751
1172
|
] });
|
|
752
1173
|
const baseClasses = cn(
|
|
753
|
-
"relative flex w-full max-w-[28rem] flex-col rounded-card border border-border bg-background p-6 text-left shadow-card transition-all duration-200",
|
|
1174
|
+
"clcosdk:relative clcosdk:flex clcosdk:w-full clcosdk:max-w-[28rem] clcosdk:flex-col clcosdk:rounded-card clcosdk:border clcosdk:border-border clcosdk:bg-background clcosdk:p-6 clcosdk:text-left clcosdk:shadow-card clcosdk:transition-all clcosdk:duration-200",
|
|
754
1175
|
className,
|
|
755
|
-
onClick && "cursor-pointer hover:-translate-y-0.5 hover:border-divider hover:shadow-[0px_14px_32px_-10px_rgba(0,0,0,0.35)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent-focus focus-visible:ring-offset-2"
|
|
1176
|
+
onClick && "clcosdk:cursor-pointer clcosdk:hover:-translate-y-0.5 clcosdk:hover:border-divider clcosdk:hover:shadow-[0px_14px_32px_-10px_rgba(0,0,0,0.35)] clcosdk:focus-visible:outline-none clcosdk:focus-visible:ring-2 clcosdk:focus-visible:ring-accent-focus clcosdk:focus-visible:ring-offset-2"
|
|
756
1177
|
);
|
|
757
1178
|
let cardNode;
|
|
758
1179
|
if (onClick) {
|
|
759
|
-
cardNode = /* @__PURE__ */
|
|
1180
|
+
cardNode = /* @__PURE__ */ jsx11(
|
|
760
1181
|
"button",
|
|
761
1182
|
{
|
|
762
1183
|
type: "button",
|
|
@@ -767,12 +1188,10 @@ function OfferCard({
|
|
|
767
1188
|
}
|
|
768
1189
|
);
|
|
769
1190
|
} else {
|
|
770
|
-
cardNode = /* @__PURE__ */
|
|
771
|
-
}
|
|
772
|
-
if (!containerClassName) {
|
|
773
|
-
return cardNode;
|
|
1191
|
+
cardNode = /* @__PURE__ */ jsx11("div", { className: baseClasses, children: cardContent });
|
|
774
1192
|
}
|
|
775
|
-
|
|
1193
|
+
const card = containerClassName ? /* @__PURE__ */ jsx11("div", { className: containerClassName, children: cardNode }) : cardNode;
|
|
1194
|
+
return /* @__PURE__ */ jsx11(CoinListStyleScope, { children: card });
|
|
776
1195
|
}
|
|
777
1196
|
|
|
778
1197
|
// src/client/hooks/useOffers.ts
|
|
@@ -818,9 +1237,9 @@ function useOffers(options = {}) {
|
|
|
818
1237
|
}
|
|
819
1238
|
|
|
820
1239
|
// src/client/components/offers/OffersGrid.tsx
|
|
821
|
-
import { jsx as
|
|
1240
|
+
import { jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
822
1241
|
var DEFAULT_MAX_COLUMNS = 3;
|
|
823
|
-
function
|
|
1242
|
+
function OffersGridBody({
|
|
824
1243
|
data,
|
|
825
1244
|
maxColumns,
|
|
826
1245
|
className,
|
|
@@ -836,12 +1255,12 @@ function OffersGrid({
|
|
|
836
1255
|
if (loading) {
|
|
837
1256
|
return loading;
|
|
838
1257
|
}
|
|
839
|
-
return /* @__PURE__ */
|
|
1258
|
+
return /* @__PURE__ */ jsx12(
|
|
840
1259
|
"output",
|
|
841
1260
|
{
|
|
842
1261
|
"aria-live": "polite",
|
|
843
|
-
className: "flex min-h-40 items-center justify-center rounded-2xl border border-border bg-background p-6",
|
|
844
|
-
children: /* @__PURE__ */
|
|
1262
|
+
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",
|
|
1263
|
+
children: /* @__PURE__ */ jsx12("p", { className: cn(typeClasses.body, "clcosdk:text-text-secondary"), children: "Loading offers..." })
|
|
845
1264
|
}
|
|
846
1265
|
);
|
|
847
1266
|
}
|
|
@@ -850,13 +1269,13 @@ function OffersGrid({
|
|
|
850
1269
|
return error;
|
|
851
1270
|
}
|
|
852
1271
|
const errorMessage = offersState.reason === "not-authenticated" ? "Sign in to view available offers." : "Unable to load offers right now. Please try again.";
|
|
853
|
-
return /* @__PURE__ */
|
|
1272
|
+
return /* @__PURE__ */ jsx12(
|
|
854
1273
|
AlertBanner,
|
|
855
1274
|
{
|
|
856
1275
|
variant: "error",
|
|
857
1276
|
icon: true,
|
|
858
1277
|
content: errorMessage,
|
|
859
|
-
className: "w-full max-w-[28rem]"
|
|
1278
|
+
className: "clcosdk:w-full clcosdk:max-w-[28rem]"
|
|
860
1279
|
}
|
|
861
1280
|
);
|
|
862
1281
|
}
|
|
@@ -864,103 +1283,671 @@ function OffersGrid({
|
|
|
864
1283
|
if (emptyState) {
|
|
865
1284
|
return emptyState;
|
|
866
1285
|
}
|
|
867
|
-
return /* @__PURE__ */
|
|
1286
|
+
return /* @__PURE__ */ jsxs9(
|
|
868
1287
|
"output",
|
|
869
1288
|
{
|
|
870
1289
|
"aria-live": "polite",
|
|
871
|
-
className: "flex min-h-40 flex-col items-center justify-center rounded-2xl border border-border bg-background p-6 text-center",
|
|
1290
|
+
className: "clcosdk:flex clcosdk:min-h-40 clcosdk:flex-col clcosdk:items-center clcosdk:justify-center clcosdk:rounded-2xl clcosdk:border clcosdk:border-border clcosdk:bg-background clcosdk:p-6 clcosdk:text-center",
|
|
872
1291
|
children: [
|
|
873
|
-
/* @__PURE__ */
|
|
874
|
-
|
|
1292
|
+
/* @__PURE__ */ jsx12(
|
|
1293
|
+
"p",
|
|
1294
|
+
{
|
|
1295
|
+
className: cn(
|
|
1296
|
+
typeClasses.body,
|
|
1297
|
+
"clcosdk:font-medium clcosdk:text-text-primary"
|
|
1298
|
+
),
|
|
1299
|
+
children: "No offers available"
|
|
1300
|
+
}
|
|
1301
|
+
),
|
|
1302
|
+
/* @__PURE__ */ jsx12("p", { className: cn(typeClasses.subhead, "clcosdk:text-text-secondary"), children: "Check back soon for upcoming opportunities." })
|
|
875
1303
|
]
|
|
876
1304
|
}
|
|
877
1305
|
);
|
|
878
1306
|
}
|
|
879
1307
|
const maxGridWidth = `calc(${cols} * 28rem + ${Math.max(cols - 1, 0)} * 1.5rem)`;
|
|
880
|
-
return /* @__PURE__ */
|
|
1308
|
+
return /* @__PURE__ */ jsx12(
|
|
881
1309
|
"div",
|
|
882
1310
|
{
|
|
883
|
-
className: cn(
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
OfferCard,
|
|
1311
|
+
className: cn(
|
|
1312
|
+
"clcosdk:flex clcosdk:w-full clcosdk:justify-center",
|
|
1313
|
+
containerClassName
|
|
1314
|
+
),
|
|
1315
|
+
children: /* @__PURE__ */ jsx12(
|
|
1316
|
+
"div",
|
|
890
1317
|
{
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
1318
|
+
className: cn("clcosdk:grid clcosdk:w-full clcosdk:gap-6", className),
|
|
1319
|
+
style: {
|
|
1320
|
+
gridTemplateColumns: "repeat(auto-fit, minmax(min(100%, 20rem), 1fr))",
|
|
1321
|
+
maxWidth: maxGridWidth
|
|
1322
|
+
},
|
|
1323
|
+
children: offersState.offers.map((offer) => /* @__PURE__ */ jsx12(
|
|
1324
|
+
OfferCard,
|
|
1325
|
+
{
|
|
1326
|
+
offer: OfferCardUi.fromDomain(offer),
|
|
1327
|
+
onClick: onOfferClick ? () => onOfferClick(offer) : void 0
|
|
1328
|
+
},
|
|
1329
|
+
offer.id
|
|
1330
|
+
))
|
|
1331
|
+
}
|
|
1332
|
+
)
|
|
896
1333
|
}
|
|
897
|
-
)
|
|
1334
|
+
);
|
|
1335
|
+
}
|
|
1336
|
+
function OffersGrid(props = {}) {
|
|
1337
|
+
return /* @__PURE__ */ jsx12(CoinListStyleScope, { children: /* @__PURE__ */ jsx12(OffersGridBody, { ...props }) });
|
|
898
1338
|
}
|
|
899
1339
|
|
|
900
|
-
// src/client/components/requirements/
|
|
901
|
-
import {
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
1340
|
+
// src/client/components/requirements/ConnectedWalletList.tsx
|
|
1341
|
+
import { useState as useState3 } from "react";
|
|
1342
|
+
import { jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1343
|
+
function ConnectedWalletRow({
|
|
1344
|
+
wallet,
|
|
1345
|
+
onRemove
|
|
1346
|
+
}) {
|
|
1347
|
+
const [state, setState] = useState3("idle");
|
|
1348
|
+
const remove = async () => {
|
|
1349
|
+
if (!onRemove) return;
|
|
1350
|
+
setState("removing");
|
|
1351
|
+
try {
|
|
1352
|
+
await onRemove(wallet.id);
|
|
1353
|
+
setState("idle");
|
|
1354
|
+
} catch {
|
|
1355
|
+
setState("error");
|
|
1356
|
+
}
|
|
1357
|
+
};
|
|
1358
|
+
return /* @__PURE__ */ jsxs10("div", { className: "clcosdk:flex clcosdk:min-h-9 clcosdk:flex-wrap clcosdk:items-center clcosdk:justify-between clcosdk:gap-2", children: [
|
|
1359
|
+
/* @__PURE__ */ jsx13(
|
|
1360
|
+
"span",
|
|
1361
|
+
{
|
|
1362
|
+
title: wallet.address,
|
|
1363
|
+
className: cn(
|
|
1364
|
+
typeClasses.body,
|
|
1365
|
+
"clcosdk:font-mono clcosdk:text-text-primary"
|
|
1366
|
+
),
|
|
1367
|
+
children: wallet.shortAddress
|
|
1368
|
+
}
|
|
1369
|
+
),
|
|
1370
|
+
onRemove != null && (state === "confirming" ? /* @__PURE__ */ jsxs10("div", { className: "clcosdk:flex clcosdk:items-center clcosdk:gap-2", children: [
|
|
1371
|
+
/* @__PURE__ */ jsx13(
|
|
1372
|
+
"span",
|
|
1373
|
+
{
|
|
1374
|
+
className: cn(typeClasses.subhead, "clcosdk:text-text-secondary"),
|
|
1375
|
+
children: "Remove?"
|
|
1376
|
+
}
|
|
1377
|
+
),
|
|
1378
|
+
/* @__PURE__ */ jsx13(ClButton, { size: "sm", variant: "destructive", onClick: remove, children: "Remove" }),
|
|
1379
|
+
/* @__PURE__ */ jsx13(
|
|
1380
|
+
ClButton,
|
|
1381
|
+
{
|
|
1382
|
+
size: "sm",
|
|
1383
|
+
variant: "ghost",
|
|
1384
|
+
onClick: () => setState("idle"),
|
|
1385
|
+
children: "Cancel"
|
|
1386
|
+
}
|
|
1387
|
+
)
|
|
1388
|
+
] }) : state === "error" ? /* @__PURE__ */ jsxs10("div", { className: "clcosdk:flex clcosdk:items-center clcosdk:gap-2", children: [
|
|
1389
|
+
/* @__PURE__ */ jsx13("span", { className: cn(typeClasses.subhead, "clcosdk:text-error"), children: "Couldn't remove." }),
|
|
1390
|
+
/* @__PURE__ */ jsx13(
|
|
1391
|
+
ClButton,
|
|
1392
|
+
{
|
|
1393
|
+
size: "sm",
|
|
1394
|
+
variant: "destructiveLink",
|
|
1395
|
+
onClick: () => setState("confirming"),
|
|
1396
|
+
children: "Try again"
|
|
1397
|
+
}
|
|
1398
|
+
)
|
|
1399
|
+
] }) : /* @__PURE__ */ jsx13(
|
|
1400
|
+
ClButton,
|
|
1401
|
+
{
|
|
1402
|
+
size: "sm",
|
|
1403
|
+
variant: "destructiveLink",
|
|
1404
|
+
disabled: state === "removing",
|
|
1405
|
+
onClick: () => setState("confirming"),
|
|
1406
|
+
children: state === "removing" ? "Removing\u2026" : "Remove"
|
|
1407
|
+
}
|
|
1408
|
+
))
|
|
1409
|
+
] });
|
|
1410
|
+
}
|
|
1411
|
+
function ConnectedWalletList({
|
|
1412
|
+
wallets,
|
|
1413
|
+
onRemove,
|
|
1414
|
+
onAdd,
|
|
1415
|
+
addLabel = "Add wallet",
|
|
1416
|
+
status = "ready",
|
|
1417
|
+
className
|
|
1418
|
+
}) {
|
|
1419
|
+
return /* @__PURE__ */ jsxs10(
|
|
1420
|
+
"div",
|
|
932
1421
|
{
|
|
933
|
-
className: cn("
|
|
934
|
-
|
|
1422
|
+
className: cn("clcosdk:flex clcosdk:flex-col clcosdk:gap-2", className),
|
|
1423
|
+
children: [
|
|
1424
|
+
status === "loading" ? /* @__PURE__ */ jsx13(AlertBanner, { variant: "info", content: "Loading your connected wallets\u2026" }) : status === "error" ? /* @__PURE__ */ jsx13(
|
|
1425
|
+
AlertBanner,
|
|
1426
|
+
{
|
|
1427
|
+
variant: "error",
|
|
1428
|
+
content: "Couldn't load your connected wallets."
|
|
1429
|
+
}
|
|
1430
|
+
) : wallets.length === 0 ? /* @__PURE__ */ jsx13(AlertBanner, { variant: "info", content: "No wallets connected yet." }) : /* @__PURE__ */ jsx13("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:divide-y clcosdk:divide-divider", children: wallets.map((wallet) => /* @__PURE__ */ jsx13(
|
|
1431
|
+
ConnectedWalletRow,
|
|
1432
|
+
{
|
|
1433
|
+
wallet,
|
|
1434
|
+
onRemove
|
|
1435
|
+
},
|
|
1436
|
+
wallet.id
|
|
1437
|
+
)) }),
|
|
1438
|
+
onAdd != null && status !== "loading" && /* @__PURE__ */ jsx13(
|
|
1439
|
+
ClButton,
|
|
1440
|
+
{
|
|
1441
|
+
size: "sm",
|
|
1442
|
+
variant: "secondary",
|
|
1443
|
+
onClick: onAdd,
|
|
1444
|
+
className: "clcosdk:self-start",
|
|
1445
|
+
children: addLabel
|
|
1446
|
+
}
|
|
1447
|
+
)
|
|
1448
|
+
]
|
|
935
1449
|
}
|
|
936
1450
|
);
|
|
937
1451
|
}
|
|
938
1452
|
|
|
939
|
-
// src/client/components/requirements/
|
|
940
|
-
import {
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
1453
|
+
// src/client/components/requirements/ConnectWalletModal.tsx
|
|
1454
|
+
import { useEffect as useEffect4, useId } from "react";
|
|
1455
|
+
|
|
1456
|
+
// src/client/hooks/useConnectWallet.ts
|
|
1457
|
+
import { useCallback, useEffect as useEffect3, useRef, useState as useState4 } from "react";
|
|
1458
|
+
|
|
1459
|
+
// src/client/core/connect-external-wallet.ts
|
|
1460
|
+
var DEFAULT_STATEMENT = "Sign this message to prove you own this wallet. This does not cost gas or move funds.";
|
|
1461
|
+
var TERMINAL_CODES = /* @__PURE__ */ new Set([
|
|
1462
|
+
"not_authenticated",
|
|
1463
|
+
"wallet_not_whitelisted",
|
|
1464
|
+
"max_wallets_reached"
|
|
1465
|
+
]);
|
|
1466
|
+
var API_ERROR_CODES = /* @__PURE__ */ new Set([
|
|
1467
|
+
"wallet_not_whitelisted",
|
|
1468
|
+
"max_wallets_reached"
|
|
1469
|
+
]);
|
|
1470
|
+
function flowError(code) {
|
|
1471
|
+
return { code, retryable: !TERMINAL_CODES.has(code) };
|
|
1472
|
+
}
|
|
1473
|
+
function siweContext() {
|
|
1474
|
+
if (typeof window === "undefined") return { domain: "", uri: "" };
|
|
1475
|
+
return { domain: window.location.host, uri: window.location.origin };
|
|
1476
|
+
}
|
|
1477
|
+
function apiErrorCode(error) {
|
|
1478
|
+
if (typeof error !== "object" || error === null) return void 0;
|
|
1479
|
+
const body = error.response?.body;
|
|
1480
|
+
return typeof body?.code === "string" ? body.code : void 0;
|
|
1481
|
+
}
|
|
1482
|
+
function classifyApiError(error) {
|
|
1483
|
+
if (error instanceof NotAuthenticatedError) {
|
|
1484
|
+
return flowError("not_authenticated");
|
|
1485
|
+
}
|
|
1486
|
+
const code = apiErrorCode(error);
|
|
1487
|
+
if (code !== void 0 && API_ERROR_CODES.has(code)) {
|
|
1488
|
+
return flowError(code);
|
|
1489
|
+
}
|
|
1490
|
+
return flowError("unknown");
|
|
1491
|
+
}
|
|
1492
|
+
function challengeParams(wallet, challengeType, statement) {
|
|
1493
|
+
switch (challengeType) {
|
|
1494
|
+
case "siwe":
|
|
1495
|
+
return {
|
|
1496
|
+
walletAddress: wallet.address,
|
|
1497
|
+
chain: wallet.chain,
|
|
1498
|
+
challengeType: "siwe",
|
|
1499
|
+
...siweContext(),
|
|
1500
|
+
statement: statement ?? DEFAULT_STATEMENT
|
|
1501
|
+
};
|
|
1502
|
+
case "plain":
|
|
1503
|
+
return {
|
|
1504
|
+
walletAddress: wallet.address,
|
|
1505
|
+
chain: wallet.chain,
|
|
1506
|
+
challengeType: "plain"
|
|
1507
|
+
};
|
|
1508
|
+
default: {
|
|
1509
|
+
const _exhaustive = challengeType;
|
|
1510
|
+
return _exhaustive;
|
|
949
1511
|
}
|
|
950
1512
|
}
|
|
951
|
-
}
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
1513
|
+
}
|
|
1514
|
+
async function connectExternalWalletFlow(params) {
|
|
1515
|
+
const {
|
|
1516
|
+
coinlist,
|
|
1517
|
+
wallet,
|
|
1518
|
+
offerId,
|
|
1519
|
+
offerOptionId,
|
|
1520
|
+
challengeType,
|
|
1521
|
+
statement,
|
|
1522
|
+
isCancelled,
|
|
1523
|
+
onProgress
|
|
1524
|
+
} = params;
|
|
1525
|
+
const emit = (phase) => onProgress?.(phase);
|
|
1526
|
+
const cancelled = () => isCancelled?.() ?? false;
|
|
1527
|
+
emit("requesting-challenge");
|
|
1528
|
+
let challenge;
|
|
1529
|
+
try {
|
|
1530
|
+
challenge = await coinlist.createWalletOwnershipChallenge(
|
|
1531
|
+
challengeParams(wallet, challengeType ?? "siwe", statement)
|
|
1532
|
+
);
|
|
1533
|
+
} catch (error) {
|
|
1534
|
+
return { type: "error", error: classifyApiError(error) };
|
|
1535
|
+
}
|
|
1536
|
+
if (cancelled()) return { type: "cancelled" };
|
|
1537
|
+
emit("signing-message");
|
|
1538
|
+
let signature;
|
|
1539
|
+
try {
|
|
1540
|
+
signature = await wallet.signMessage(challenge.message);
|
|
1541
|
+
} catch (error) {
|
|
1542
|
+
if (classifyWalletError(error).type === "user_rejected") {
|
|
1543
|
+
return { type: "error", error: flowError("user_rejected") };
|
|
1544
|
+
}
|
|
1545
|
+
return { type: "error", error: flowError("unknown") };
|
|
1546
|
+
}
|
|
1547
|
+
if (cancelled()) return { type: "cancelled" };
|
|
1548
|
+
emit("submitting-signature");
|
|
1549
|
+
try {
|
|
1550
|
+
const binding = await coinlist.connectExternalWallet(offerId, {
|
|
1551
|
+
offerOptionId,
|
|
1552
|
+
walletAddress: wallet.address,
|
|
1553
|
+
chain: wallet.chain,
|
|
1554
|
+
signature
|
|
1555
|
+
});
|
|
1556
|
+
return { type: "success", binding };
|
|
1557
|
+
} catch (error) {
|
|
1558
|
+
return { type: "error", error: classifyApiError(error) };
|
|
1559
|
+
}
|
|
1560
|
+
}
|
|
1561
|
+
|
|
1562
|
+
// src/client/hooks/useConnectWallet.ts
|
|
1563
|
+
var IDLE_SIGN = { type: "idle", error: null };
|
|
1564
|
+
var ERROR_COPY = {
|
|
1565
|
+
not_authenticated: "Sign in to connect your wallet.",
|
|
1566
|
+
user_rejected: "Signature request declined. Approve it in your wallet to continue.",
|
|
1567
|
+
wallet_not_whitelisted: "This wallet is not approved for this offer.",
|
|
1568
|
+
max_wallets_reached: "You've reached the maximum number of wallets for this option.",
|
|
1569
|
+
unknown: "Unable to connect your wallet. Please try again."
|
|
1570
|
+
};
|
|
1571
|
+
function displayError(error) {
|
|
1572
|
+
return {
|
|
1573
|
+
code: error.code,
|
|
1574
|
+
message: ERROR_COPY[error.code],
|
|
1575
|
+
retryable: error.retryable
|
|
1576
|
+
};
|
|
1577
|
+
}
|
|
1578
|
+
function useConnectWallet({
|
|
1579
|
+
isOpen,
|
|
1580
|
+
offerId,
|
|
1581
|
+
offerOptionId,
|
|
1582
|
+
wallet,
|
|
1583
|
+
challengeType,
|
|
1584
|
+
statement
|
|
1585
|
+
}) {
|
|
1586
|
+
const { coinlist } = useCoinList();
|
|
1587
|
+
const [state, setState] = useState4(
|
|
1588
|
+
() => wallet ? { type: "READY", address: wallet.address, sign: IDLE_SIGN } : { type: "NEEDS_WALLET" }
|
|
1589
|
+
);
|
|
1590
|
+
const attempt = useRef(0);
|
|
1591
|
+
useEffect3(() => {
|
|
1592
|
+
attempt.current += 1;
|
|
1593
|
+
if (!isOpen) return;
|
|
1594
|
+
setState(
|
|
1595
|
+
wallet ? { type: "READY", address: wallet.address, sign: IDLE_SIGN } : { type: "NEEDS_WALLET" }
|
|
1596
|
+
);
|
|
1597
|
+
}, [isOpen, wallet?.address]);
|
|
1598
|
+
useEffect3(
|
|
1599
|
+
() => () => {
|
|
1600
|
+
attempt.current += 1;
|
|
1601
|
+
},
|
|
1602
|
+
[]
|
|
1603
|
+
);
|
|
1604
|
+
const onSign = useCallback(() => {
|
|
1605
|
+
if (!wallet || state.type !== "READY") return;
|
|
1606
|
+
attempt.current += 1;
|
|
1607
|
+
const gen = attempt.current;
|
|
1608
|
+
setState({
|
|
1609
|
+
type: "READY",
|
|
1610
|
+
address: wallet.address,
|
|
1611
|
+
sign: { type: "signing" }
|
|
1612
|
+
});
|
|
1613
|
+
connectExternalWalletFlow({
|
|
1614
|
+
coinlist,
|
|
1615
|
+
wallet,
|
|
1616
|
+
offerId,
|
|
1617
|
+
offerOptionId,
|
|
1618
|
+
challengeType,
|
|
1619
|
+
statement,
|
|
1620
|
+
// Cancels the flow before signing / binding if this attempt is superseded.
|
|
1621
|
+
isCancelled: () => attempt.current !== gen
|
|
1622
|
+
}).then((result) => {
|
|
1623
|
+
if (attempt.current !== gen) return;
|
|
1624
|
+
if (result.type === "success") {
|
|
1625
|
+
setState({ type: "CONNECTED", binding: result.binding });
|
|
1626
|
+
} else if (result.type === "error") {
|
|
1627
|
+
setState({
|
|
1628
|
+
type: "READY",
|
|
1629
|
+
address: wallet.address,
|
|
1630
|
+
sign: { type: "idle", error: displayError(result.error) }
|
|
1631
|
+
});
|
|
1632
|
+
}
|
|
1633
|
+
});
|
|
1634
|
+
}, [
|
|
1635
|
+
wallet,
|
|
1636
|
+
state,
|
|
1637
|
+
coinlist,
|
|
1638
|
+
offerId,
|
|
1639
|
+
offerOptionId,
|
|
1640
|
+
challengeType,
|
|
1641
|
+
statement
|
|
1642
|
+
]);
|
|
1643
|
+
return { state, onSign };
|
|
1644
|
+
}
|
|
1645
|
+
|
|
1646
|
+
// src/client/components/requirements/ConnectWalletModal.tsx
|
|
1647
|
+
import { jsx as jsx14, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1648
|
+
function ConnectWalletModal({
|
|
1649
|
+
isOpen,
|
|
1650
|
+
onClose,
|
|
1651
|
+
offerId,
|
|
1652
|
+
optionId,
|
|
1653
|
+
wallet,
|
|
1654
|
+
onConnected,
|
|
1655
|
+
onRequestConnect,
|
|
1656
|
+
challengeType,
|
|
1657
|
+
statement,
|
|
1658
|
+
className
|
|
1659
|
+
}) {
|
|
1660
|
+
const { state, onSign } = useConnectWallet({
|
|
1661
|
+
isOpen,
|
|
1662
|
+
offerId,
|
|
1663
|
+
offerOptionId: optionId,
|
|
1664
|
+
wallet,
|
|
1665
|
+
challengeType,
|
|
1666
|
+
statement
|
|
1667
|
+
});
|
|
1668
|
+
const titleId = useId();
|
|
1669
|
+
useEffect4(() => {
|
|
1670
|
+
if (state.type === "CONNECTED") {
|
|
1671
|
+
onConnected?.(state.binding);
|
|
1672
|
+
onClose();
|
|
1673
|
+
}
|
|
1674
|
+
}, [state]);
|
|
1675
|
+
if (!isOpen || state.type === "CONNECTED") return null;
|
|
1676
|
+
return /* @__PURE__ */ jsx14("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__ */ jsxs11(
|
|
1677
|
+
"div",
|
|
1678
|
+
{
|
|
1679
|
+
role: "dialog",
|
|
1680
|
+
"aria-modal": "true",
|
|
1681
|
+
"aria-labelledby": titleId,
|
|
1682
|
+
className: cn(
|
|
1683
|
+
"clcosdk:flex clcosdk:w-full clcosdk:max-w-md clcosdk:flex-col clcosdk:gap-6 clcosdk:rounded-2xl clcosdk:bg-background clcosdk:p-6",
|
|
1684
|
+
className
|
|
1685
|
+
),
|
|
1686
|
+
children: [
|
|
1687
|
+
/* @__PURE__ */ jsxs11("div", { className: "clcosdk:flex clcosdk:items-start clcosdk:justify-between clcosdk:gap-4", children: [
|
|
1688
|
+
/* @__PURE__ */ jsx14(
|
|
1689
|
+
"h3",
|
|
1690
|
+
{
|
|
1691
|
+
id: titleId,
|
|
1692
|
+
className: cn(typeClasses.h3, "clcosdk:text-text-primary"),
|
|
1693
|
+
children: "Connect your wallet"
|
|
1694
|
+
}
|
|
1695
|
+
),
|
|
1696
|
+
/* @__PURE__ */ jsx14(CloseButton, { onClick: onClose })
|
|
1697
|
+
] }),
|
|
1698
|
+
state.type === "NEEDS_WALLET" && /* @__PURE__ */ jsx14(NeedsWalletScreen, { onRequestConnect }),
|
|
1699
|
+
state.type === "READY" && /* @__PURE__ */ jsx14(
|
|
1700
|
+
ReadyScreen,
|
|
1701
|
+
{
|
|
1702
|
+
address: state.address,
|
|
1703
|
+
sign: state.sign,
|
|
1704
|
+
onSign,
|
|
1705
|
+
onRequestConnect
|
|
1706
|
+
}
|
|
1707
|
+
)
|
|
1708
|
+
]
|
|
1709
|
+
}
|
|
1710
|
+
) });
|
|
1711
|
+
}
|
|
1712
|
+
function NeedsWalletScreen({
|
|
1713
|
+
onRequestConnect
|
|
1714
|
+
}) {
|
|
1715
|
+
return /* @__PURE__ */ jsxs11("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-6", children: [
|
|
1716
|
+
/* @__PURE__ */ jsx14("p", { className: cn(typeClasses.body, "clcosdk:text-text-secondary"), children: "Connect an external wallet to prove ownership and bind it to this offer." }),
|
|
1717
|
+
onRequestConnect && /* @__PURE__ */ jsx14(ClButton, { fullWidth: true, onClick: onRequestConnect, children: "Connect wallet" })
|
|
1718
|
+
] });
|
|
1719
|
+
}
|
|
1720
|
+
function ReadyScreen({
|
|
1721
|
+
address,
|
|
1722
|
+
sign,
|
|
1723
|
+
onSign,
|
|
1724
|
+
onRequestConnect
|
|
1725
|
+
}) {
|
|
1726
|
+
const hasTerminalError = sign.type === "idle" && sign.error !== null && !sign.error.retryable;
|
|
1727
|
+
return /* @__PURE__ */ jsxs11("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-6", children: [
|
|
1728
|
+
/* @__PURE__ */ jsx14("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." }),
|
|
1729
|
+
/* @__PURE__ */ jsxs11("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-1 clcosdk:border-t clcosdk:border-divider clcosdk:pt-4", children: [
|
|
1730
|
+
/* @__PURE__ */ jsx14("span", { className: cn(typeClasses.label, "clcosdk:text-text-secondary"), children: "Wallet address" }),
|
|
1731
|
+
/* @__PURE__ */ jsx14("span", { className: cn(typeClasses.body, "clcosdk:text-text-primary"), children: shortenAddress(address) })
|
|
1732
|
+
] }),
|
|
1733
|
+
sign.type === "idle" && sign.error && // Live region: the error is inserted async after a failed attempt, so
|
|
1734
|
+
// screen readers need it announced rather than silently rendered.
|
|
1735
|
+
/* @__PURE__ */ jsx14("div", { role: "alert", children: /* @__PURE__ */ jsx14(AlertBanner, { variant: "error", icon: true, content: sign.error.message }) }),
|
|
1736
|
+
/* @__PURE__ */ jsx14(
|
|
1737
|
+
ClButton,
|
|
1738
|
+
{
|
|
1739
|
+
fullWidth: true,
|
|
1740
|
+
onClick: onSign,
|
|
1741
|
+
isLoading: sign.type === "signing",
|
|
1742
|
+
loadingText: "Waiting for signature...",
|
|
1743
|
+
disabled: hasTerminalError,
|
|
1744
|
+
children: "Sign & connect"
|
|
1745
|
+
}
|
|
1746
|
+
),
|
|
1747
|
+
onRequestConnect && /* @__PURE__ */ jsx14(
|
|
1748
|
+
ClButton,
|
|
1749
|
+
{
|
|
1750
|
+
fullWidth: true,
|
|
1751
|
+
variant: "secondary",
|
|
1752
|
+
onClick: onRequestConnect,
|
|
1753
|
+
disabled: sign.type === "signing",
|
|
1754
|
+
children: "Use a different wallet"
|
|
1755
|
+
}
|
|
1756
|
+
)
|
|
1757
|
+
] });
|
|
1758
|
+
}
|
|
1759
|
+
|
|
1760
|
+
// src/client/components/requirements/IdentityVerification.tsx
|
|
1761
|
+
import SumsubWebSdk from "@sumsub/websdk-react";
|
|
1762
|
+
import { useEffect as useEffect6, useRef as useRef3 } from "react";
|
|
1763
|
+
|
|
1764
|
+
// src/client/hooks/useKycToken.ts
|
|
1765
|
+
import { useCallback as useCallback2, useEffect as useEffect5, useRef as useRef2, useState as useState5 } from "react";
|
|
1766
|
+
var IDLE_STATE = { type: "IDLE" };
|
|
1767
|
+
var LOADING_STATE2 = { type: "LOADING" };
|
|
1768
|
+
function useKycToken(levelName, reset) {
|
|
1769
|
+
const { coinlist } = useCoinList();
|
|
1770
|
+
const [kycTokenState, setKycTokenState] = useState5(IDLE_STATE);
|
|
1771
|
+
const resetPendingRef = useRef2(reset === true);
|
|
1772
|
+
const tokenIssuedRef = useRef2(false);
|
|
1773
|
+
useEffect5(() => {
|
|
1774
|
+
if (!tokenIssuedRef.current) {
|
|
1775
|
+
resetPendingRef.current = reset === true;
|
|
1776
|
+
}
|
|
1777
|
+
}, [reset]);
|
|
1778
|
+
const fetchToken = useCallback2(async () => {
|
|
1779
|
+
setKycTokenState(LOADING_STATE2);
|
|
1780
|
+
try {
|
|
1781
|
+
const kycToken = await coinlist.createKycToken(
|
|
1782
|
+
levelName,
|
|
1783
|
+
resetPendingRef.current
|
|
1784
|
+
);
|
|
1785
|
+
resetPendingRef.current = false;
|
|
1786
|
+
tokenIssuedRef.current = true;
|
|
1787
|
+
setKycTokenState({ type: "CONTENT", token: kycToken.token });
|
|
1788
|
+
return kycToken.token;
|
|
1789
|
+
} catch (error) {
|
|
1790
|
+
const reason = error instanceof NotAuthenticatedError ? "not-authenticated" : "generic-error";
|
|
1791
|
+
setKycTokenState({ type: "ERROR", reason });
|
|
1792
|
+
throw error;
|
|
1793
|
+
}
|
|
1794
|
+
}, [coinlist, levelName]);
|
|
1795
|
+
return { kycTokenState, fetchToken };
|
|
1796
|
+
}
|
|
1797
|
+
|
|
1798
|
+
// src/client/components/requirements/IdentityVerification.tsx
|
|
1799
|
+
import { jsx as jsx15, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1800
|
+
function IdentityVerification({
|
|
1801
|
+
levelName,
|
|
1802
|
+
reset,
|
|
1803
|
+
locale,
|
|
1804
|
+
onSubmitted,
|
|
1805
|
+
onError,
|
|
1806
|
+
className
|
|
1807
|
+
}) {
|
|
1808
|
+
const { kycTokenState, fetchToken } = useKycToken(levelName, reset);
|
|
1809
|
+
const fetchedRef = useRef3(false);
|
|
1810
|
+
useEffect6(() => {
|
|
1811
|
+
if (fetchedRef.current) return;
|
|
1812
|
+
fetchedRef.current = true;
|
|
1813
|
+
fetchToken().catch(() => {
|
|
1814
|
+
});
|
|
1815
|
+
}, [fetchToken]);
|
|
1816
|
+
const handleMessage = (type, payload) => {
|
|
1817
|
+
switch (type) {
|
|
1818
|
+
case "idCheck.onApplicantSubmitted":
|
|
1819
|
+
onSubmitted?.();
|
|
1820
|
+
break;
|
|
1821
|
+
case "idCheck.onError": {
|
|
1822
|
+
const message = payload?.message ?? "Verification error";
|
|
1823
|
+
onError?.(new Error(message));
|
|
1824
|
+
break;
|
|
1825
|
+
}
|
|
1826
|
+
default:
|
|
1827
|
+
break;
|
|
1828
|
+
}
|
|
1829
|
+
};
|
|
1830
|
+
const handleError = (error) => {
|
|
1831
|
+
onError?.(error instanceof Error ? error : new Error("Verification error"));
|
|
1832
|
+
};
|
|
1833
|
+
if (kycTokenState.type === "IDLE" || kycTokenState.type === "LOADING") {
|
|
1834
|
+
return /* @__PURE__ */ jsx15(
|
|
1835
|
+
"output",
|
|
1836
|
+
{
|
|
1837
|
+
"aria-live": "polite",
|
|
1838
|
+
className: cn(
|
|
1839
|
+
"clcosdk:flex clcosdk:min-h-40 clcosdk:items-center clcosdk:justify-center",
|
|
1840
|
+
className
|
|
1841
|
+
),
|
|
1842
|
+
children: /* @__PURE__ */ jsx15("p", { className: cn(typeClasses.body, "clcosdk:text-text-secondary"), children: "Loading identity verification..." })
|
|
1843
|
+
}
|
|
1844
|
+
);
|
|
1845
|
+
}
|
|
1846
|
+
if (kycTokenState.type === "ERROR") {
|
|
1847
|
+
const errorMessage = kycTokenState.reason === "not-authenticated" ? "Sign in to verify your identity." : "Unable to start identity verification right now. Please try again.";
|
|
1848
|
+
return /* @__PURE__ */ jsxs12(
|
|
1849
|
+
"div",
|
|
1850
|
+
{
|
|
1851
|
+
className: cn("clcosdk:flex clcosdk:flex-col clcosdk:gap-4", className),
|
|
1852
|
+
children: [
|
|
1853
|
+
/* @__PURE__ */ jsx15(AlertBanner, { variant: "error", icon: true, content: errorMessage }),
|
|
1854
|
+
kycTokenState.reason !== "not-authenticated" && /* @__PURE__ */ jsx15(
|
|
1855
|
+
ClButton,
|
|
1856
|
+
{
|
|
1857
|
+
size: "sm",
|
|
1858
|
+
onClick: () => {
|
|
1859
|
+
fetchToken().catch(() => {
|
|
1860
|
+
});
|
|
1861
|
+
},
|
|
1862
|
+
children: "Try again"
|
|
1863
|
+
}
|
|
1864
|
+
)
|
|
1865
|
+
]
|
|
1866
|
+
}
|
|
1867
|
+
);
|
|
1868
|
+
}
|
|
1869
|
+
return /* @__PURE__ */ jsx15("div", { className: cn("clcosdk:w-full", className), children: /* @__PURE__ */ jsx15(
|
|
1870
|
+
SumsubWebSdk,
|
|
1871
|
+
{
|
|
1872
|
+
accessToken: kycTokenState.token,
|
|
1873
|
+
expirationHandler: fetchToken,
|
|
1874
|
+
config: locale === void 0 ? {} : { lang: locale },
|
|
1875
|
+
options: { addViewportTag: false, adaptIframeHeight: true },
|
|
1876
|
+
onMessage: handleMessage,
|
|
1877
|
+
onError: handleError
|
|
1878
|
+
}
|
|
1879
|
+
) });
|
|
1880
|
+
}
|
|
1881
|
+
|
|
1882
|
+
// src/client/components/requirements/RequirementItem.tsx
|
|
1883
|
+
import { ChevronRight } from "lucide-react";
|
|
1884
|
+
|
|
1885
|
+
// src/client/components/design-system/StepStatusIcon.tsx
|
|
1886
|
+
import { CircleCheck as CircleCheck2, CircleX, Info as Info2 } from "lucide-react";
|
|
1887
|
+
import { jsx as jsx16 } from "react/jsx-runtime";
|
|
1888
|
+
var statusConfig = {
|
|
1889
|
+
required: {
|
|
1890
|
+
Icon: Info2,
|
|
1891
|
+
colorClass: "clcosdk:text-warning",
|
|
1892
|
+
fillClass: "clcosdk:[&_circle]:fill-warning-subtle"
|
|
1893
|
+
},
|
|
1894
|
+
pending: {
|
|
1895
|
+
Icon: Info2,
|
|
1896
|
+
colorClass: "clcosdk:text-warning",
|
|
1897
|
+
fillClass: "clcosdk:[&_circle]:fill-warning-subtle"
|
|
1898
|
+
},
|
|
1899
|
+
completed: {
|
|
1900
|
+
Icon: CircleCheck2,
|
|
1901
|
+
colorClass: "clcosdk:text-success",
|
|
1902
|
+
fillClass: "clcosdk:[&_circle]:fill-success-subtle"
|
|
1903
|
+
},
|
|
1904
|
+
rejected: {
|
|
1905
|
+
Icon: CircleX,
|
|
1906
|
+
colorClass: "clcosdk:text-error",
|
|
1907
|
+
fillClass: "clcosdk:[&_circle]:fill-error-subtle"
|
|
1908
|
+
}
|
|
1909
|
+
};
|
|
1910
|
+
function StepStatusIcon({ status, className }) {
|
|
1911
|
+
const { Icon, colorClass, fillClass } = statusConfig[status];
|
|
1912
|
+
return /* @__PURE__ */ jsx16(
|
|
1913
|
+
Icon,
|
|
1914
|
+
{
|
|
1915
|
+
className: cn(
|
|
1916
|
+
"clcosdk:h-6 clcosdk:w-6 clcosdk:shrink-0",
|
|
1917
|
+
colorClass,
|
|
1918
|
+
fillClass,
|
|
1919
|
+
className
|
|
1920
|
+
),
|
|
1921
|
+
"aria-hidden": "true"
|
|
1922
|
+
}
|
|
1923
|
+
);
|
|
1924
|
+
}
|
|
1925
|
+
|
|
1926
|
+
// src/client/components/requirements/RequirementItem.tsx
|
|
1927
|
+
import { Fragment as Fragment3, jsx as jsx17, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1928
|
+
var RequirementVariant = {
|
|
1929
|
+
fromType(type) {
|
|
1930
|
+
switch (type) {
|
|
1931
|
+
case "external_wallet":
|
|
1932
|
+
case "whitelisted_wallet":
|
|
1933
|
+
return "wallet";
|
|
1934
|
+
default:
|
|
1935
|
+
return "verification";
|
|
1936
|
+
}
|
|
1937
|
+
}
|
|
1938
|
+
};
|
|
1939
|
+
var RequirementStatus = {
|
|
1940
|
+
fromStatusValue(status) {
|
|
1941
|
+
switch (status) {
|
|
1942
|
+
case "not_started":
|
|
1943
|
+
case "action_needed":
|
|
1944
|
+
return "required";
|
|
1945
|
+
case "in_progress":
|
|
1946
|
+
return "pending";
|
|
1947
|
+
case "completed":
|
|
1948
|
+
return "completed";
|
|
1949
|
+
case "rejected":
|
|
1950
|
+
return "rejected";
|
|
964
1951
|
}
|
|
965
1952
|
}
|
|
966
1953
|
};
|
|
@@ -972,13 +1959,18 @@ var ChecklistStatus = {
|
|
|
972
1959
|
}
|
|
973
1960
|
};
|
|
974
1961
|
var RequirementItemUi = {
|
|
975
|
-
fromDomain(req, statusInfo, label, description,
|
|
1962
|
+
fromDomain(req, statusInfo, label, description, addresses = []) {
|
|
976
1963
|
return {
|
|
977
1964
|
variant: RequirementVariant.fromType(req.type),
|
|
978
1965
|
status: statusInfo ? RequirementStatus.fromStatusValue(statusInfo.status) : "required",
|
|
979
1966
|
label,
|
|
980
1967
|
description,
|
|
981
|
-
|
|
1968
|
+
multiWallet: req.type === "whitelisted_wallet",
|
|
1969
|
+
connectedWallets: addresses.map((address) => ({
|
|
1970
|
+
id: address.id,
|
|
1971
|
+
address: address.address,
|
|
1972
|
+
shortAddress: shortenAddress(address.address)
|
|
1973
|
+
}))
|
|
982
1974
|
};
|
|
983
1975
|
}
|
|
984
1976
|
};
|
|
@@ -990,9 +1982,9 @@ function VerificationActionZone({
|
|
|
990
1982
|
switch (status) {
|
|
991
1983
|
case "required":
|
|
992
1984
|
if (onAction === null) return null;
|
|
993
|
-
return /* @__PURE__ */
|
|
1985
|
+
return /* @__PURE__ */ jsx17(ClButton, { size: "sm", onClick: onAction, children: "Continue" });
|
|
994
1986
|
case "pending":
|
|
995
|
-
return /* @__PURE__ */
|
|
1987
|
+
return /* @__PURE__ */ jsx17(
|
|
996
1988
|
AlertBanner,
|
|
997
1989
|
{
|
|
998
1990
|
variant: "warning",
|
|
@@ -1000,21 +1992,21 @@ function VerificationActionZone({
|
|
|
1000
1992
|
}
|
|
1001
1993
|
);
|
|
1002
1994
|
case "completed":
|
|
1003
|
-
return /* @__PURE__ */
|
|
1995
|
+
return /* @__PURE__ */ jsx17(AlertBanner, { variant: "success", content: "Identity verified." });
|
|
1004
1996
|
case "rejected":
|
|
1005
|
-
return /* @__PURE__ */
|
|
1997
|
+
return /* @__PURE__ */ jsx17(
|
|
1006
1998
|
AlertBanner,
|
|
1007
1999
|
{
|
|
1008
2000
|
variant: "error",
|
|
1009
|
-
content: onContactSupport === null ? "Verification rejected." : /* @__PURE__ */
|
|
2001
|
+
content: onContactSupport === null ? "Verification rejected." : /* @__PURE__ */ jsxs13(Fragment3, { children: [
|
|
1010
2002
|
"Verification rejected.",
|
|
1011
2003
|
" ",
|
|
1012
|
-
/* @__PURE__ */
|
|
2004
|
+
/* @__PURE__ */ jsx17(
|
|
1013
2005
|
"button",
|
|
1014
2006
|
{
|
|
1015
2007
|
type: "button",
|
|
1016
2008
|
onClick: onContactSupport,
|
|
1017
|
-
className: "underline",
|
|
2009
|
+
className: "clcosdk:underline",
|
|
1018
2010
|
children: "Contact support"
|
|
1019
2011
|
}
|
|
1020
2012
|
),
|
|
@@ -1026,25 +2018,61 @@ function VerificationActionZone({
|
|
|
1026
2018
|
}
|
|
1027
2019
|
function WalletActionZone({
|
|
1028
2020
|
status,
|
|
1029
|
-
|
|
1030
|
-
|
|
2021
|
+
multiWallet,
|
|
2022
|
+
connectedWallets,
|
|
2023
|
+
walletsStatus,
|
|
2024
|
+
onAction,
|
|
2025
|
+
onRemoveWallet
|
|
1031
2026
|
}) {
|
|
2027
|
+
if (multiWallet) {
|
|
2028
|
+
return /* @__PURE__ */ jsxs13(Fragment3, { children: [
|
|
2029
|
+
/* @__PURE__ */ jsx17(
|
|
2030
|
+
ConnectedWalletList,
|
|
2031
|
+
{
|
|
2032
|
+
wallets: connectedWallets,
|
|
2033
|
+
onRemove: onRemoveWallet,
|
|
2034
|
+
onAdd: onAction ?? void 0,
|
|
2035
|
+
status: walletsStatus
|
|
2036
|
+
}
|
|
2037
|
+
),
|
|
2038
|
+
status === "rejected" && /* @__PURE__ */ jsx17(
|
|
2039
|
+
AlertBanner,
|
|
2040
|
+
{
|
|
2041
|
+
variant: "error",
|
|
2042
|
+
content: "One of these wallets is not eligible for this sale."
|
|
2043
|
+
}
|
|
2044
|
+
)
|
|
2045
|
+
] });
|
|
2046
|
+
}
|
|
1032
2047
|
if (status === "completed") {
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
/* @__PURE__ */
|
|
2048
|
+
const connected = connectedWallets[0];
|
|
2049
|
+
return /* @__PURE__ */ jsxs13(Fragment3, { children: [
|
|
2050
|
+
onAction !== null && /* @__PURE__ */ jsx17(ClButton, { size: "sm", variant: "secondary", onClick: onAction, children: "Change wallet" }),
|
|
2051
|
+
walletsStatus === "loading" ? /* @__PURE__ */ jsx17(
|
|
2052
|
+
AlertBanner,
|
|
2053
|
+
{
|
|
2054
|
+
variant: "info",
|
|
2055
|
+
content: "Loading your connected wallet\u2026"
|
|
2056
|
+
}
|
|
2057
|
+
) : walletsStatus === "error" ? /* @__PURE__ */ jsx17(
|
|
2058
|
+
AlertBanner,
|
|
2059
|
+
{
|
|
2060
|
+
variant: "error",
|
|
2061
|
+
content: "Couldn't load your connected wallet."
|
|
2062
|
+
}
|
|
2063
|
+
) : /* @__PURE__ */ jsx17(
|
|
1036
2064
|
AlertBanner,
|
|
1037
2065
|
{
|
|
1038
2066
|
variant: "success",
|
|
1039
|
-
content:
|
|
2067
|
+
content: connected ? connected.shortAddress : "Wallet connected."
|
|
1040
2068
|
}
|
|
1041
2069
|
)
|
|
1042
2070
|
] });
|
|
1043
2071
|
}
|
|
1044
2072
|
if (status === "rejected") {
|
|
1045
|
-
return /* @__PURE__ */
|
|
1046
|
-
onAction !== null && /* @__PURE__ */
|
|
1047
|
-
/* @__PURE__ */
|
|
2073
|
+
return /* @__PURE__ */ jsxs13(Fragment3, { children: [
|
|
2074
|
+
onAction !== null && /* @__PURE__ */ jsx17(ClButton, { size: "sm", onClick: onAction, children: "Connect wallet" }),
|
|
2075
|
+
/* @__PURE__ */ jsx17(
|
|
1048
2076
|
AlertBanner,
|
|
1049
2077
|
{
|
|
1050
2078
|
variant: "error",
|
|
@@ -1054,7 +2082,7 @@ function WalletActionZone({
|
|
|
1054
2082
|
] });
|
|
1055
2083
|
}
|
|
1056
2084
|
if (onAction === null) return null;
|
|
1057
|
-
return /* @__PURE__ */
|
|
2085
|
+
return /* @__PURE__ */ jsx17(ClButton, { size: "sm", onClick: onAction, children: "Connect wallet" });
|
|
1058
2086
|
}
|
|
1059
2087
|
function RequirementItem({
|
|
1060
2088
|
ui,
|
|
@@ -1062,92 +2090,588 @@ function RequirementItem({
|
|
|
1062
2090
|
onToggle,
|
|
1063
2091
|
className,
|
|
1064
2092
|
onAction,
|
|
2093
|
+
onRemoveWallet,
|
|
2094
|
+
walletsStatus,
|
|
1065
2095
|
onContactSupport
|
|
1066
2096
|
}) {
|
|
1067
|
-
return /* @__PURE__ */
|
|
1068
|
-
|
|
1069
|
-
|
|
2097
|
+
return /* @__PURE__ */ jsx17(CoinListStyleScope, { children: /* @__PURE__ */ jsxs13(
|
|
2098
|
+
"div",
|
|
2099
|
+
{
|
|
2100
|
+
className: cn(
|
|
2101
|
+
"clcosdk:flex clcosdk:w-full clcosdk:flex-col",
|
|
2102
|
+
className
|
|
2103
|
+
),
|
|
2104
|
+
children: [
|
|
2105
|
+
/* @__PURE__ */ jsxs13(
|
|
2106
|
+
"button",
|
|
2107
|
+
{
|
|
2108
|
+
type: "button",
|
|
2109
|
+
onClick: onToggle,
|
|
2110
|
+
"aria-expanded": expanded,
|
|
2111
|
+
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",
|
|
2112
|
+
children: [
|
|
2113
|
+
/* @__PURE__ */ jsxs13("div", { className: "clcosdk:flex clcosdk:items-center clcosdk:gap-3", children: [
|
|
2114
|
+
/* @__PURE__ */ jsx17(StepStatusIcon, { status: ui.status }),
|
|
2115
|
+
/* @__PURE__ */ jsx17(
|
|
2116
|
+
"span",
|
|
2117
|
+
{
|
|
2118
|
+
className: cn(
|
|
2119
|
+
typeClasses.body,
|
|
2120
|
+
"clcosdk:whitespace-nowrap clcosdk:font-medium clcosdk:text-text-primary"
|
|
2121
|
+
),
|
|
2122
|
+
children: ui.label
|
|
2123
|
+
}
|
|
2124
|
+
)
|
|
2125
|
+
] }),
|
|
2126
|
+
/* @__PURE__ */ jsx17(
|
|
2127
|
+
ChevronRight,
|
|
2128
|
+
{
|
|
2129
|
+
className: cn(
|
|
2130
|
+
"clcosdk:h-6 clcosdk:w-6 clcosdk:shrink-0 clcosdk:text-text-secondary clcosdk:transition-transform clcosdk:duration-300",
|
|
2131
|
+
expanded && "clcosdk:rotate-90"
|
|
2132
|
+
),
|
|
2133
|
+
"aria-hidden": "true"
|
|
2134
|
+
}
|
|
2135
|
+
)
|
|
2136
|
+
]
|
|
2137
|
+
}
|
|
2138
|
+
),
|
|
2139
|
+
/* @__PURE__ */ jsx17(
|
|
2140
|
+
"div",
|
|
2141
|
+
{
|
|
2142
|
+
className: cn(
|
|
2143
|
+
"clcosdk:grid clcosdk:transition-[grid-template-rows] clcosdk:duration-300 clcosdk:ease-in-out",
|
|
2144
|
+
expanded ? "clcosdk:grid-rows-[1fr]" : "clcosdk:grid-rows-[0fr]"
|
|
2145
|
+
),
|
|
2146
|
+
children: /* @__PURE__ */ jsx17("div", { className: "clcosdk:min-h-0 clcosdk:overflow-hidden", children: /* @__PURE__ */ jsxs13("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-4 clcosdk:px-2 clcosdk:pb-4", children: [
|
|
2147
|
+
/* @__PURE__ */ jsx17(
|
|
2148
|
+
"p",
|
|
2149
|
+
{
|
|
2150
|
+
className: cn(
|
|
2151
|
+
typeClasses.subhead,
|
|
2152
|
+
"clcosdk:text-text-secondary"
|
|
2153
|
+
),
|
|
2154
|
+
children: ui.description
|
|
2155
|
+
}
|
|
2156
|
+
),
|
|
2157
|
+
ui.variant === "verification" ? /* @__PURE__ */ jsx17(
|
|
2158
|
+
VerificationActionZone,
|
|
2159
|
+
{
|
|
2160
|
+
status: ui.status,
|
|
2161
|
+
onAction,
|
|
2162
|
+
onContactSupport
|
|
2163
|
+
}
|
|
2164
|
+
) : /* @__PURE__ */ jsx17(
|
|
2165
|
+
WalletActionZone,
|
|
2166
|
+
{
|
|
2167
|
+
status: ui.status,
|
|
2168
|
+
multiWallet: ui.multiWallet,
|
|
2169
|
+
connectedWallets: ui.connectedWallets,
|
|
2170
|
+
walletsStatus,
|
|
2171
|
+
onAction,
|
|
2172
|
+
onRemoveWallet
|
|
2173
|
+
}
|
|
2174
|
+
)
|
|
2175
|
+
] }) })
|
|
2176
|
+
}
|
|
2177
|
+
)
|
|
2178
|
+
]
|
|
2179
|
+
}
|
|
2180
|
+
) });
|
|
2181
|
+
}
|
|
2182
|
+
|
|
2183
|
+
// src/client/components/requirements/RequirementsChecklist.tsx
|
|
2184
|
+
import { useEffect as useEffect11, useRef as useRef4, useState as useState9 } from "react";
|
|
2185
|
+
|
|
2186
|
+
// src/client/components/requirements/TaxDocumentModal.tsx
|
|
2187
|
+
import { useEffect as useEffect8 } from "react";
|
|
2188
|
+
|
|
2189
|
+
// src/client/hooks/useTaxDocument.ts
|
|
2190
|
+
import { useCallback as useCallback3, useEffect as useEffect7, useState as useState6 } from "react";
|
|
2191
|
+
var IDLE_SIGN2 = { type: "idle", error: null };
|
|
2192
|
+
var LOADING_STATE3 = { type: "LOADING" };
|
|
2193
|
+
var SIGN_FAILED_MESSAGE = "Unable to sign document. Please try again.";
|
|
2194
|
+
var DOB_INVALID_MESSAGE = "Enter your date of birth as MM/DD/YYYY.";
|
|
2195
|
+
var FIELD_KEYS = {
|
|
2196
|
+
fullLegalName: "Full Name",
|
|
2197
|
+
dob: "DOB",
|
|
2198
|
+
countryOfCitizenship: "Country Of Citizenship",
|
|
2199
|
+
taxId: "Foreign Tax Number",
|
|
2200
|
+
permanentAddress: "Permanent Address"
|
|
2201
|
+
};
|
|
2202
|
+
function formatUsDate(date) {
|
|
2203
|
+
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
2204
|
+
const day = String(date.getDate()).padStart(2, "0");
|
|
2205
|
+
const year = String(date.getFullYear()).padStart(4, "0");
|
|
2206
|
+
return `${month}/${day}/${year}`;
|
|
2207
|
+
}
|
|
2208
|
+
function formatIsoDateOnly(isoDate) {
|
|
2209
|
+
const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(isoDate);
|
|
2210
|
+
if (!match) return "";
|
|
2211
|
+
const [, year, month, day] = match;
|
|
2212
|
+
return `${month}/${day}/${year}`;
|
|
2213
|
+
}
|
|
2214
|
+
function isValidUsDate(value) {
|
|
2215
|
+
const match = /^(\d{2})\/(\d{2})\/(\d{4})$/.exec(value);
|
|
2216
|
+
if (!match) return false;
|
|
2217
|
+
const [, mm, dd, yyyy] = match;
|
|
2218
|
+
const month = Number(mm);
|
|
2219
|
+
const day = Number(dd);
|
|
2220
|
+
const year = Number(yyyy);
|
|
2221
|
+
const date = new Date(year, month - 1, day);
|
|
2222
|
+
return date.getFullYear() === year && date.getMonth() === month - 1 && date.getDate() === day;
|
|
2223
|
+
}
|
|
2224
|
+
function mapPiiToFields(pii) {
|
|
2225
|
+
const { street, city, state, postalCode } = pii.permanentAddress;
|
|
2226
|
+
const cityLine = [postalCode, city].filter(Boolean).join(" ");
|
|
2227
|
+
const permanentAddress = [street, cityLine, state].filter(Boolean).join(", ");
|
|
2228
|
+
return {
|
|
2229
|
+
fullLegalName: pii.fullLegalName ?? "",
|
|
2230
|
+
// Date-only ISO from the backend, shown as MM/DD/YYYY. Blank until the
|
|
2231
|
+
// backend has a date of birth (the field is editable in the meantime).
|
|
2232
|
+
dob: formatIsoDateOnly(pii.dateOfBirth ?? ""),
|
|
2233
|
+
countryOfCitizenship: pii.jurisdiction?.name ?? "",
|
|
2234
|
+
taxId: pii.taxId ?? "",
|
|
2235
|
+
permanentAddress
|
|
2236
|
+
};
|
|
2237
|
+
}
|
|
2238
|
+
function addressPartsFromPii(pii) {
|
|
2239
|
+
return {
|
|
2240
|
+
city: pii.permanentAddress.city ?? "",
|
|
2241
|
+
country: pii.permanentAddress.country ?? ""
|
|
2242
|
+
};
|
|
2243
|
+
}
|
|
2244
|
+
function hasAnyFieldValue(fields) {
|
|
2245
|
+
return Object.values(fields).some((value) => value.trim() !== "");
|
|
2246
|
+
}
|
|
2247
|
+
function toSubmissionFields(fields, addressParts) {
|
|
2248
|
+
return {
|
|
2249
|
+
[FIELD_KEYS.fullLegalName]: fields.fullLegalName,
|
|
2250
|
+
[FIELD_KEYS.dob]: fields.dob,
|
|
2251
|
+
[FIELD_KEYS.countryOfCitizenship]: fields.countryOfCitizenship,
|
|
2252
|
+
[FIELD_KEYS.taxId]: fields.taxId,
|
|
2253
|
+
[FIELD_KEYS.permanentAddress]: fields.permanentAddress,
|
|
2254
|
+
City: addressParts.city,
|
|
2255
|
+
Country: addressParts.country,
|
|
2256
|
+
Signature: fields.fullLegalName,
|
|
2257
|
+
Date: formatUsDate(/* @__PURE__ */ new Date())
|
|
2258
|
+
};
|
|
2259
|
+
}
|
|
2260
|
+
function useTaxDocument({
|
|
2261
|
+
isOpen
|
|
2262
|
+
}) {
|
|
2263
|
+
const { coinlist, isReady } = useCoinList();
|
|
2264
|
+
const [state, setState] = useState6(LOADING_STATE3);
|
|
2265
|
+
useEffect7(() => {
|
|
2266
|
+
let isCancelled = false;
|
|
2267
|
+
if (!isOpen) {
|
|
2268
|
+
return () => {
|
|
2269
|
+
isCancelled = true;
|
|
2270
|
+
};
|
|
2271
|
+
}
|
|
2272
|
+
if (!isReady) {
|
|
2273
|
+
setState(LOADING_STATE3);
|
|
2274
|
+
return () => {
|
|
2275
|
+
isCancelled = true;
|
|
2276
|
+
};
|
|
2277
|
+
}
|
|
2278
|
+
setState(LOADING_STATE3);
|
|
2279
|
+
coinlist.fetchPii().then((pii) => {
|
|
2280
|
+
if (isCancelled) return;
|
|
2281
|
+
if (pii.kind === "company") {
|
|
2282
|
+
setState({ type: "SIGN_ONLY", sign: IDLE_SIGN2 });
|
|
2283
|
+
return;
|
|
2284
|
+
}
|
|
2285
|
+
const fields = mapPiiToFields(pii);
|
|
2286
|
+
setState({
|
|
2287
|
+
type: "REVIEW",
|
|
2288
|
+
fields,
|
|
2289
|
+
addressParts: addressPartsFromPii(pii),
|
|
2290
|
+
piiUnavailable: !hasAnyFieldValue(fields),
|
|
2291
|
+
sign: IDLE_SIGN2
|
|
2292
|
+
});
|
|
2293
|
+
}).catch((error) => {
|
|
2294
|
+
if (isCancelled) return;
|
|
2295
|
+
setState({
|
|
2296
|
+
type: "ERROR",
|
|
2297
|
+
reason: error instanceof NotAuthenticatedError ? "not-authenticated" : "generic-error"
|
|
2298
|
+
});
|
|
2299
|
+
});
|
|
2300
|
+
return () => {
|
|
2301
|
+
isCancelled = true;
|
|
2302
|
+
};
|
|
2303
|
+
}, [coinlist, isReady, isOpen]);
|
|
2304
|
+
const onEditField = useCallback3(
|
|
2305
|
+
(field, value) => {
|
|
2306
|
+
setState(
|
|
2307
|
+
(prev) => prev.type === "EDITING" ? { ...prev, fields: { ...prev.fields, [field]: value } } : prev
|
|
2308
|
+
);
|
|
2309
|
+
},
|
|
2310
|
+
[]
|
|
2311
|
+
);
|
|
2312
|
+
const onStartEdit = useCallback3(() => {
|
|
2313
|
+
setState(
|
|
2314
|
+
(prev) => prev.type === "REVIEW" ? {
|
|
2315
|
+
type: "EDITING",
|
|
2316
|
+
fields: prev.fields,
|
|
2317
|
+
original: prev.fields,
|
|
2318
|
+
addressParts: prev.addressParts,
|
|
2319
|
+
piiUnavailable: prev.piiUnavailable
|
|
2320
|
+
} : prev
|
|
2321
|
+
);
|
|
2322
|
+
}, []);
|
|
2323
|
+
const onSaveEdit = useCallback3(() => {
|
|
2324
|
+
setState(
|
|
2325
|
+
(prev) => prev.type === "EDITING" ? {
|
|
2326
|
+
type: "REVIEW",
|
|
2327
|
+
fields: prev.fields,
|
|
2328
|
+
addressParts: prev.addressParts,
|
|
2329
|
+
piiUnavailable: prev.piiUnavailable,
|
|
2330
|
+
sign: IDLE_SIGN2
|
|
2331
|
+
} : prev
|
|
2332
|
+
);
|
|
2333
|
+
}, []);
|
|
2334
|
+
const onCancelEdit = useCallback3(() => {
|
|
2335
|
+
setState(
|
|
2336
|
+
(prev) => prev.type === "EDITING" ? {
|
|
2337
|
+
type: "REVIEW",
|
|
2338
|
+
fields: prev.original,
|
|
2339
|
+
addressParts: prev.addressParts,
|
|
2340
|
+
piiUnavailable: prev.piiUnavailable,
|
|
2341
|
+
sign: IDLE_SIGN2
|
|
2342
|
+
} : prev
|
|
2343
|
+
);
|
|
2344
|
+
}, []);
|
|
2345
|
+
const onSign = useCallback3(() => {
|
|
2346
|
+
if (state.type !== "REVIEW" && state.type !== "SIGN_ONLY") return;
|
|
2347
|
+
if (state.type === "REVIEW" && state.fields.dob.trim() !== "" && !isValidUsDate(state.fields.dob)) {
|
|
2348
|
+
setState({
|
|
2349
|
+
...state,
|
|
2350
|
+
sign: { type: "idle", error: DOB_INVALID_MESSAGE }
|
|
2351
|
+
});
|
|
2352
|
+
return;
|
|
2353
|
+
}
|
|
2354
|
+
setState({ ...state, sign: { type: "signing" } });
|
|
2355
|
+
coinlist.submitDocument(
|
|
2356
|
+
"tax_certification",
|
|
2357
|
+
state.type === "REVIEW" ? toSubmissionFields(state.fields, state.addressParts) : {}
|
|
2358
|
+
).then((submission) => {
|
|
2359
|
+
setState({ type: "SUBMITTED", submission });
|
|
2360
|
+
}).catch(() => {
|
|
2361
|
+
setState(
|
|
2362
|
+
(prev) => prev.type === "REVIEW" || prev.type === "SIGN_ONLY" ? { ...prev, sign: { type: "idle", error: SIGN_FAILED_MESSAGE } } : prev
|
|
2363
|
+
);
|
|
2364
|
+
});
|
|
2365
|
+
}, [state, coinlist]);
|
|
2366
|
+
return { state, onEditField, onStartEdit, onSaveEdit, onCancelEdit, onSign };
|
|
2367
|
+
}
|
|
2368
|
+
|
|
2369
|
+
// src/client/components/requirements/TaxDocumentModal.tsx
|
|
2370
|
+
import { jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
2371
|
+
var FIELD_ROWS = [
|
|
2372
|
+
{ field: "fullLegalName", label: "Full legal name" },
|
|
2373
|
+
{ field: "dob", label: "Date of birth", placeholder: "MM/DD/YYYY" },
|
|
2374
|
+
{ field: "countryOfCitizenship", label: "Country of citizenship" },
|
|
2375
|
+
{ field: "taxId", label: "Tax ID" },
|
|
2376
|
+
{ field: "permanentAddress", label: "Permanent address" }
|
|
2377
|
+
];
|
|
2378
|
+
function TaxDocumentModal({
|
|
2379
|
+
isOpen,
|
|
2380
|
+
onClose,
|
|
2381
|
+
onSubmitted,
|
|
2382
|
+
className
|
|
2383
|
+
}) {
|
|
2384
|
+
const { state, onEditField, onStartEdit, onSaveEdit, onCancelEdit, onSign } = useTaxDocument({ isOpen });
|
|
2385
|
+
useEffect8(() => {
|
|
2386
|
+
if (state.type === "SUBMITTED") {
|
|
2387
|
+
onSubmitted?.(state.submission);
|
|
2388
|
+
onClose();
|
|
2389
|
+
}
|
|
2390
|
+
}, [state]);
|
|
2391
|
+
if (!isOpen || state.type === "SUBMITTED") return null;
|
|
2392
|
+
return /* @__PURE__ */ jsx18("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__ */ jsxs14(
|
|
2393
|
+
"div",
|
|
2394
|
+
{
|
|
2395
|
+
className: cn(
|
|
2396
|
+
"clcosdk:flex clcosdk:w-full clcosdk:max-w-md clcosdk:flex-col clcosdk:gap-6 clcosdk:rounded-2xl clcosdk:bg-background clcosdk:p-6",
|
|
2397
|
+
className
|
|
2398
|
+
),
|
|
2399
|
+
children: [
|
|
2400
|
+
/* @__PURE__ */ jsxs14("div", { className: "clcosdk:flex clcosdk:items-start clcosdk:justify-between clcosdk:gap-4", children: [
|
|
2401
|
+
/* @__PURE__ */ jsx18(TaxDocumentModalHeading, { state }),
|
|
2402
|
+
/* @__PURE__ */ jsx18(CloseButton, { onClick: onClose })
|
|
2403
|
+
] }),
|
|
2404
|
+
state.type === "LOADING" && /* @__PURE__ */ jsx18(LoadingScreen, {}),
|
|
2405
|
+
state.type === "ERROR" && /* @__PURE__ */ jsx18(ErrorScreen, { reason: state.reason }),
|
|
2406
|
+
state.type === "REVIEW" && /* @__PURE__ */ jsx18(
|
|
2407
|
+
ReviewScreen,
|
|
2408
|
+
{
|
|
2409
|
+
fields: state.fields,
|
|
2410
|
+
piiUnavailable: state.piiUnavailable,
|
|
2411
|
+
sign: state.sign,
|
|
2412
|
+
onStartEdit,
|
|
2413
|
+
onSign
|
|
2414
|
+
}
|
|
2415
|
+
),
|
|
2416
|
+
state.type === "EDITING" && /* @__PURE__ */ jsx18(
|
|
2417
|
+
EditScreen,
|
|
2418
|
+
{
|
|
2419
|
+
fields: state.fields,
|
|
2420
|
+
onEditField,
|
|
2421
|
+
onSaveEdit,
|
|
2422
|
+
onCancelEdit
|
|
2423
|
+
}
|
|
2424
|
+
),
|
|
2425
|
+
state.type === "SIGN_ONLY" && /* @__PURE__ */ jsx18(SignOnlyScreen, { sign: state.sign, onSign })
|
|
2426
|
+
]
|
|
2427
|
+
}
|
|
2428
|
+
) });
|
|
2429
|
+
}
|
|
2430
|
+
function TaxDocumentModalHeading({
|
|
2431
|
+
state
|
|
2432
|
+
}) {
|
|
2433
|
+
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";
|
|
2434
|
+
return /* @__PURE__ */ jsx18("h3", { className: cn(typeClasses.h3, "clcosdk:text-text-primary"), children: title });
|
|
2435
|
+
}
|
|
2436
|
+
function LoadingScreen() {
|
|
2437
|
+
return /* @__PURE__ */ jsx18(
|
|
2438
|
+
"output",
|
|
2439
|
+
{
|
|
2440
|
+
"aria-live": "polite",
|
|
2441
|
+
className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-4",
|
|
2442
|
+
children: FIELD_ROWS.map(({ field }) => /* @__PURE__ */ jsxs14(
|
|
2443
|
+
"div",
|
|
2444
|
+
{
|
|
2445
|
+
className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-1",
|
|
2446
|
+
children: [
|
|
2447
|
+
/* @__PURE__ */ jsx18("div", { className: "clcosdk:h-3 clcosdk:w-28 clcosdk:animate-pulse clcosdk:rounded clcosdk:bg-surface" }),
|
|
2448
|
+
/* @__PURE__ */ jsx18("div", { className: "clcosdk:h-5 clcosdk:w-48 clcosdk:animate-pulse clcosdk:rounded clcosdk:bg-surface" })
|
|
2449
|
+
]
|
|
2450
|
+
},
|
|
2451
|
+
field
|
|
2452
|
+
))
|
|
2453
|
+
}
|
|
2454
|
+
);
|
|
2455
|
+
}
|
|
2456
|
+
function ErrorScreen({
|
|
2457
|
+
reason
|
|
2458
|
+
}) {
|
|
2459
|
+
return /* @__PURE__ */ jsx18(
|
|
2460
|
+
AlertBanner,
|
|
2461
|
+
{
|
|
2462
|
+
variant: "error",
|
|
2463
|
+
icon: true,
|
|
2464
|
+
content: reason === "not-authenticated" ? "Sign in to complete your tax document." : "Unable to load your tax information right now. Please try again."
|
|
2465
|
+
}
|
|
2466
|
+
);
|
|
2467
|
+
}
|
|
2468
|
+
function ReviewScreen({
|
|
2469
|
+
fields,
|
|
2470
|
+
piiUnavailable,
|
|
2471
|
+
sign,
|
|
2472
|
+
onStartEdit,
|
|
2473
|
+
onSign
|
|
2474
|
+
}) {
|
|
2475
|
+
return /* @__PURE__ */ jsxs14("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-6", children: [
|
|
2476
|
+
/* @__PURE__ */ jsx18("p", { className: cn(typeClasses.body, "clcosdk:text-text-secondary"), children: "Review your information below. If anything looks incorrect, edit before signing." }),
|
|
2477
|
+
piiUnavailable && /* @__PURE__ */ jsx18(
|
|
2478
|
+
AlertBanner,
|
|
1070
2479
|
{
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
"
|
|
1074
|
-
|
|
2480
|
+
variant: "info",
|
|
2481
|
+
icon: true,
|
|
2482
|
+
content: "We don't have this information on file yet \u2014 please fill it in below."
|
|
2483
|
+
}
|
|
2484
|
+
),
|
|
2485
|
+
/* @__PURE__ */ jsx18("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__ */ jsxs14(
|
|
2486
|
+
"div",
|
|
2487
|
+
{
|
|
2488
|
+
className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-1",
|
|
1075
2489
|
children: [
|
|
1076
|
-
/* @__PURE__ */
|
|
1077
|
-
|
|
1078
|
-
/* @__PURE__ */ jsx13(
|
|
1079
|
-
"span",
|
|
1080
|
-
{
|
|
1081
|
-
className: cn(
|
|
1082
|
-
typeClasses.body,
|
|
1083
|
-
"whitespace-nowrap font-medium text-text-primary"
|
|
1084
|
-
),
|
|
1085
|
-
children: ui.label
|
|
1086
|
-
}
|
|
1087
|
-
)
|
|
1088
|
-
] }),
|
|
1089
|
-
/* @__PURE__ */ jsx13(
|
|
1090
|
-
ChevronRight,
|
|
2490
|
+
/* @__PURE__ */ jsx18(
|
|
2491
|
+
"span",
|
|
1091
2492
|
{
|
|
1092
|
-
className: cn(
|
|
1093
|
-
|
|
1094
|
-
expanded && "rotate-90"
|
|
1095
|
-
),
|
|
1096
|
-
"aria-hidden": "true"
|
|
2493
|
+
className: cn(typeClasses.label, "clcosdk:text-text-secondary"),
|
|
2494
|
+
children: label
|
|
1097
2495
|
}
|
|
1098
|
-
)
|
|
2496
|
+
),
|
|
2497
|
+
/* @__PURE__ */ jsx18("span", { className: cn(typeClasses.body, "clcosdk:text-text-primary"), children: fields[field] || "\u2014" })
|
|
1099
2498
|
]
|
|
1100
|
-
}
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
2499
|
+
},
|
|
2500
|
+
field
|
|
2501
|
+
)) }),
|
|
2502
|
+
/* @__PURE__ */ jsx18("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." }),
|
|
2503
|
+
sign.type === "idle" && sign.error && /* @__PURE__ */ jsx18(AlertBanner, { variant: "error", icon: true, content: sign.error }),
|
|
2504
|
+
/* @__PURE__ */ jsxs14("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-2", children: [
|
|
2505
|
+
/* @__PURE__ */ jsx18(
|
|
2506
|
+
ClButton,
|
|
2507
|
+
{
|
|
2508
|
+
fullWidth: true,
|
|
2509
|
+
onClick: onSign,
|
|
2510
|
+
isLoading: sign.type === "signing",
|
|
2511
|
+
loadingText: "Signing...",
|
|
2512
|
+
children: "Sign W-8BEN"
|
|
2513
|
+
}
|
|
2514
|
+
),
|
|
2515
|
+
/* @__PURE__ */ jsx18(
|
|
2516
|
+
ClButton,
|
|
2517
|
+
{
|
|
2518
|
+
fullWidth: true,
|
|
2519
|
+
variant: "secondary",
|
|
2520
|
+
onClick: onStartEdit,
|
|
2521
|
+
disabled: sign.type === "signing",
|
|
2522
|
+
children: "Edit information"
|
|
2523
|
+
}
|
|
2524
|
+
)
|
|
2525
|
+
] })
|
|
2526
|
+
] });
|
|
2527
|
+
}
|
|
2528
|
+
function EditScreen({
|
|
2529
|
+
fields,
|
|
2530
|
+
onEditField,
|
|
2531
|
+
onSaveEdit,
|
|
2532
|
+
onCancelEdit
|
|
2533
|
+
}) {
|
|
2534
|
+
return /* @__PURE__ */ jsxs14("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-6", children: [
|
|
2535
|
+
/* @__PURE__ */ jsx18("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__ */ jsxs14(
|
|
2536
|
+
"label",
|
|
1104
2537
|
{
|
|
1105
|
-
className:
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
children: /* @__PURE__ */ jsx13("div", { className: "min-h-0 overflow-hidden", children: /* @__PURE__ */ jsxs9("div", { className: "flex flex-col gap-4 px-2 pb-4", children: [
|
|
1110
|
-
/* @__PURE__ */ jsx13("p", { className: cn(typeClasses.subhead, "text-text-secondary"), children: ui.description }),
|
|
1111
|
-
ui.variant === "verification" ? /* @__PURE__ */ jsx13(
|
|
1112
|
-
VerificationActionZone,
|
|
2538
|
+
className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-1",
|
|
2539
|
+
children: [
|
|
2540
|
+
/* @__PURE__ */ jsx18(
|
|
2541
|
+
"span",
|
|
1113
2542
|
{
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
onContactSupport
|
|
2543
|
+
className: cn(typeClasses.label, "clcosdk:text-text-secondary"),
|
|
2544
|
+
children: label
|
|
1117
2545
|
}
|
|
1118
|
-
)
|
|
1119
|
-
|
|
2546
|
+
),
|
|
2547
|
+
/* @__PURE__ */ jsx18(
|
|
2548
|
+
"input",
|
|
1120
2549
|
{
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
2550
|
+
type: "text",
|
|
2551
|
+
value: fields[field],
|
|
2552
|
+
placeholder,
|
|
2553
|
+
onChange: (e) => onEditField(field, e.target.value),
|
|
2554
|
+
className: cn(
|
|
2555
|
+
typeClasses.body,
|
|
2556
|
+
"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"
|
|
2557
|
+
)
|
|
1124
2558
|
}
|
|
1125
2559
|
)
|
|
1126
|
-
]
|
|
2560
|
+
]
|
|
2561
|
+
},
|
|
2562
|
+
field
|
|
2563
|
+
)) }),
|
|
2564
|
+
/* @__PURE__ */ jsxs14("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-2", children: [
|
|
2565
|
+
/* @__PURE__ */ jsx18(ClButton, { fullWidth: true, onClick: onSaveEdit, children: "Save & review" }),
|
|
2566
|
+
/* @__PURE__ */ jsx18(ClButton, { fullWidth: true, variant: "secondary", onClick: onCancelEdit, children: "Cancel" })
|
|
2567
|
+
] })
|
|
2568
|
+
] });
|
|
2569
|
+
}
|
|
2570
|
+
function SignOnlyScreen({
|
|
2571
|
+
sign,
|
|
2572
|
+
onSign
|
|
2573
|
+
}) {
|
|
2574
|
+
return /* @__PURE__ */ jsxs14("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-6", children: [
|
|
2575
|
+
/* @__PURE__ */ jsx18("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." }),
|
|
2576
|
+
sign.type === "idle" && sign.error && /* @__PURE__ */ jsx18(AlertBanner, { variant: "error", icon: true, content: sign.error }),
|
|
2577
|
+
/* @__PURE__ */ jsx18(
|
|
2578
|
+
ClButton,
|
|
2579
|
+
{
|
|
2580
|
+
fullWidth: true,
|
|
2581
|
+
onClick: onSign,
|
|
2582
|
+
isLoading: sign.type === "signing",
|
|
2583
|
+
loadingText: "Signing...",
|
|
2584
|
+
children: "Sign W-8BEN-E"
|
|
1127
2585
|
}
|
|
1128
2586
|
)
|
|
1129
2587
|
] });
|
|
1130
2588
|
}
|
|
1131
2589
|
|
|
1132
|
-
// src/client/
|
|
1133
|
-
import { useState as
|
|
2590
|
+
// src/client/hooks/useOptionAddresses.ts
|
|
2591
|
+
import { useCallback as useCallback4, useEffect as useEffect9, useState as useState7 } from "react";
|
|
2592
|
+
var LOADING_STATE4 = { type: "LOADING" };
|
|
2593
|
+
var EMPTY_STATE = {
|
|
2594
|
+
type: "CONTENT",
|
|
2595
|
+
addresses: []
|
|
2596
|
+
};
|
|
2597
|
+
function useOptionAddresses(offerId, offerOptionId, options = {}) {
|
|
2598
|
+
const { coinlist, isReady } = useCoinList();
|
|
2599
|
+
const { data, enabled = true } = options;
|
|
2600
|
+
const [addressesState, setAddressesState] = useState7(
|
|
2601
|
+
data !== void 0 ? { type: "CONTENT", addresses: data } : LOADING_STATE4
|
|
2602
|
+
);
|
|
2603
|
+
const [fetchKey, setFetchKey] = useState7(0);
|
|
2604
|
+
const refetch = useCallback4(() => setFetchKey((k) => k + 1), []);
|
|
2605
|
+
const disconnect = useCallback4(
|
|
2606
|
+
async (addressId) => {
|
|
2607
|
+
await coinlist.removeOptionAddress(offerId, addressId);
|
|
2608
|
+
refetch();
|
|
2609
|
+
},
|
|
2610
|
+
[coinlist, offerId, refetch]
|
|
2611
|
+
);
|
|
2612
|
+
useEffect9(() => {
|
|
2613
|
+
let isCancelled = false;
|
|
2614
|
+
if (!enabled) {
|
|
2615
|
+
setAddressesState(
|
|
2616
|
+
data !== void 0 ? { type: "CONTENT", addresses: data } : EMPTY_STATE
|
|
2617
|
+
);
|
|
2618
|
+
return () => {
|
|
2619
|
+
isCancelled = true;
|
|
2620
|
+
};
|
|
2621
|
+
}
|
|
2622
|
+
if (!isReady) {
|
|
2623
|
+
if (data === void 0) {
|
|
2624
|
+
setAddressesState(LOADING_STATE4);
|
|
2625
|
+
}
|
|
2626
|
+
return () => {
|
|
2627
|
+
isCancelled = true;
|
|
2628
|
+
};
|
|
2629
|
+
}
|
|
2630
|
+
if (data !== void 0 && fetchKey === 0) {
|
|
2631
|
+
return () => {
|
|
2632
|
+
isCancelled = true;
|
|
2633
|
+
};
|
|
2634
|
+
}
|
|
2635
|
+
if (coinlist.getAuthState() === "logged-out") {
|
|
2636
|
+
setAddressesState({ type: "ERROR", reason: "not-authenticated" });
|
|
2637
|
+
return () => {
|
|
2638
|
+
isCancelled = true;
|
|
2639
|
+
};
|
|
2640
|
+
}
|
|
2641
|
+
setAddressesState(LOADING_STATE4);
|
|
2642
|
+
coinlist.listOptionAddresses(offerId, offerOptionId).then((addresses) => {
|
|
2643
|
+
if (!isCancelled) {
|
|
2644
|
+
setAddressesState({ type: "CONTENT", addresses });
|
|
2645
|
+
}
|
|
2646
|
+
}).catch((error) => {
|
|
2647
|
+
if (!isCancelled) {
|
|
2648
|
+
const reason = error instanceof NotAuthenticatedError ? "not-authenticated" : "generic-error";
|
|
2649
|
+
setAddressesState({ type: "ERROR", reason });
|
|
2650
|
+
}
|
|
2651
|
+
});
|
|
2652
|
+
return () => {
|
|
2653
|
+
isCancelled = true;
|
|
2654
|
+
};
|
|
2655
|
+
}, [coinlist, isReady, enabled, offerId, offerOptionId, fetchKey]);
|
|
2656
|
+
return { addressesState, refetch, disconnect };
|
|
2657
|
+
}
|
|
1134
2658
|
|
|
1135
2659
|
// src/client/hooks/useRequirements.ts
|
|
1136
|
-
import { useCallback, useEffect as
|
|
1137
|
-
var
|
|
2660
|
+
import { useCallback as useCallback5, useEffect as useEffect10, useState as useState8 } from "react";
|
|
2661
|
+
var LOADING_STATE5 = { type: "LOADING" };
|
|
1138
2662
|
function useRequirements(offerId, options = {}) {
|
|
1139
2663
|
const { coinlist, isReady } = useCoinList();
|
|
1140
2664
|
const { data } = options;
|
|
1141
|
-
const [requirementsState, setRequirementsState] =
|
|
1142
|
-
data !== void 0 ? { type: "CONTENT", ...data } :
|
|
2665
|
+
const [requirementsState, setRequirementsState] = useState8(
|
|
2666
|
+
data !== void 0 ? { type: "CONTENT", ...data } : LOADING_STATE5
|
|
1143
2667
|
);
|
|
1144
|
-
const [fetchKey, setFetchKey] =
|
|
1145
|
-
const refetch =
|
|
1146
|
-
|
|
2668
|
+
const [fetchKey, setFetchKey] = useState8(0);
|
|
2669
|
+
const refetch = useCallback5(() => setFetchKey((k) => k + 1), []);
|
|
2670
|
+
useEffect10(() => {
|
|
1147
2671
|
let isCancelled = false;
|
|
1148
2672
|
if (!isReady) {
|
|
1149
2673
|
if (data === void 0) {
|
|
1150
|
-
setRequirementsState(
|
|
2674
|
+
setRequirementsState(LOADING_STATE5);
|
|
1151
2675
|
}
|
|
1152
2676
|
return () => {
|
|
1153
2677
|
isCancelled = true;
|
|
@@ -1158,7 +2682,13 @@ function useRequirements(offerId, options = {}) {
|
|
|
1158
2682
|
isCancelled = true;
|
|
1159
2683
|
};
|
|
1160
2684
|
}
|
|
1161
|
-
|
|
2685
|
+
if (coinlist.getAuthState() === "logged-out") {
|
|
2686
|
+
setRequirementsState({ type: "ERROR", reason: "not-authenticated" });
|
|
2687
|
+
return () => {
|
|
2688
|
+
isCancelled = true;
|
|
2689
|
+
};
|
|
2690
|
+
}
|
|
2691
|
+
setRequirementsState(LOADING_STATE5);
|
|
1162
2692
|
Promise.all([
|
|
1163
2693
|
coinlist.fetchOfferRequirements(offerId),
|
|
1164
2694
|
coinlist.fetchRequirementStatuses(offerId)
|
|
@@ -1184,7 +2714,8 @@ function useRequirements(offerId, options = {}) {
|
|
|
1184
2714
|
}
|
|
1185
2715
|
|
|
1186
2716
|
// src/client/components/requirements/RequirementsChecklist.tsx
|
|
1187
|
-
import { jsx as
|
|
2717
|
+
import { jsx as jsx19, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
2718
|
+
var isWalletRequirement = (requirement) => RequirementVariant.fromType(requirement.type) === "wallet";
|
|
1188
2719
|
var DEFAULT_LABELS = {
|
|
1189
2720
|
kyc_approved: "KYC Verification",
|
|
1190
2721
|
identity_verified: "Identity Verification",
|
|
@@ -1193,7 +2724,8 @@ var DEFAULT_LABELS = {
|
|
|
1193
2724
|
external_wallet: "External Wallet",
|
|
1194
2725
|
whitelisted_wallet: "Whitelisted Wallet",
|
|
1195
2726
|
jurisdiction: "Jurisdiction Check",
|
|
1196
|
-
accreditation: "Accreditation"
|
|
2727
|
+
accreditation: "Accreditation",
|
|
2728
|
+
document: "Document"
|
|
1197
2729
|
};
|
|
1198
2730
|
var DEFAULT_DESCRIPTIONS = {
|
|
1199
2731
|
kyc_approved: "Complete Know Your Customer verification.",
|
|
@@ -1203,9 +2735,39 @@ var DEFAULT_DESCRIPTIONS = {
|
|
|
1203
2735
|
external_wallet: "Connect an external wallet.",
|
|
1204
2736
|
whitelisted_wallet: "Connect a whitelisted wallet.",
|
|
1205
2737
|
jurisdiction: "Confirm your jurisdiction eligibility.",
|
|
1206
|
-
accreditation: "Verify your accreditation status."
|
|
2738
|
+
accreditation: "Verify your accreditation status.",
|
|
2739
|
+
document: "Confirm your Tax Documents."
|
|
1207
2740
|
};
|
|
1208
|
-
|
|
2741
|
+
var VERIFICATION_POLL_INTERVAL_MS = 5e3;
|
|
2742
|
+
var VERIFICATION_POLL_TIMEOUT_MS = 12e4;
|
|
2743
|
+
function sleep(ms) {
|
|
2744
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
2745
|
+
}
|
|
2746
|
+
function VerificationOverlay({
|
|
2747
|
+
onClose,
|
|
2748
|
+
children
|
|
2749
|
+
}) {
|
|
2750
|
+
return /* @__PURE__ */ jsx19(
|
|
2751
|
+
"div",
|
|
2752
|
+
{
|
|
2753
|
+
role: "dialog",
|
|
2754
|
+
"aria-modal": "true",
|
|
2755
|
+
"aria-label": "Identity verification",
|
|
2756
|
+
className: "clcosdk:fixed clcosdk:inset-0 clcosdk:z-50 clcosdk:flex clcosdk:items-center clcosdk:justify-center clcosdk:bg-overlay clcosdk:p-4",
|
|
2757
|
+
children: /* @__PURE__ */ jsxs15("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: [
|
|
2758
|
+
/* @__PURE__ */ jsx19(
|
|
2759
|
+
CloseButton,
|
|
2760
|
+
{
|
|
2761
|
+
onClick: onClose,
|
|
2762
|
+
className: "clcosdk:absolute clcosdk:top-4 clcosdk:right-4"
|
|
2763
|
+
}
|
|
2764
|
+
),
|
|
2765
|
+
children
|
|
2766
|
+
] })
|
|
2767
|
+
}
|
|
2768
|
+
);
|
|
2769
|
+
}
|
|
2770
|
+
function RequirementsChecklistBody({
|
|
1209
2771
|
offerId,
|
|
1210
2772
|
optionId,
|
|
1211
2773
|
title,
|
|
@@ -1213,39 +2775,107 @@ function RequirementsChecklist({
|
|
|
1213
2775
|
onContinue,
|
|
1214
2776
|
onRequirementActionOverride,
|
|
1215
2777
|
onContactSupportOverride,
|
|
2778
|
+
wallet,
|
|
2779
|
+
onRequestConnect,
|
|
1216
2780
|
getLabel,
|
|
1217
2781
|
getDescription,
|
|
1218
2782
|
loading,
|
|
2783
|
+
unauthenticatedState,
|
|
1219
2784
|
error,
|
|
1220
2785
|
className,
|
|
1221
|
-
data
|
|
2786
|
+
data,
|
|
2787
|
+
identityVerificationOptions
|
|
1222
2788
|
}) {
|
|
1223
2789
|
const { coinlist } = useCoinList();
|
|
1224
|
-
const { requirementsState } = useRequirements(offerId, { data });
|
|
1225
|
-
const [expandedIndex, setExpandedIndex] =
|
|
1226
|
-
const
|
|
2790
|
+
const { requirementsState, refetch } = useRequirements(offerId, { data });
|
|
2791
|
+
const [expandedIndex, setExpandedIndex] = useState9(null);
|
|
2792
|
+
const [taxDocumentOpen, setTaxDocumentOpen] = useState9(false);
|
|
2793
|
+
const [walletConnectOpen, setConnectWalletOpen] = useState9(false);
|
|
2794
|
+
const [verifyingRequirementId, setVerifyingRequirementId] = useState9(null);
|
|
2795
|
+
const isMountedRef = useRef4(true);
|
|
2796
|
+
useEffect11(() => {
|
|
2797
|
+
isMountedRef.current = true;
|
|
2798
|
+
return () => {
|
|
2799
|
+
isMountedRef.current = false;
|
|
2800
|
+
};
|
|
2801
|
+
}, []);
|
|
2802
|
+
const [hasWalletRequirement, setHasWalletRequirement] = useState9(false);
|
|
2803
|
+
useEffect11(() => {
|
|
2804
|
+
if (requirementsState.type === "CONTENT") {
|
|
2805
|
+
setHasWalletRequirement(
|
|
2806
|
+
(requirementsState.requirements[optionId] ?? []).some(
|
|
2807
|
+
isWalletRequirement
|
|
2808
|
+
)
|
|
2809
|
+
);
|
|
2810
|
+
}
|
|
2811
|
+
}, [requirementsState, optionId]);
|
|
2812
|
+
const {
|
|
2813
|
+
addressesState,
|
|
2814
|
+
refetch: refetchAddresses,
|
|
2815
|
+
disconnect
|
|
2816
|
+
} = useOptionAddresses(offerId, optionId, {
|
|
2817
|
+
enabled: hasWalletRequirement
|
|
2818
|
+
});
|
|
2819
|
+
const optionAddresses = addressesState.type === "CONTENT" ? addressesState.addresses : [];
|
|
2820
|
+
const walletsStatus = addressesState.type === "ERROR" ? "error" : addressesState.type === "LOADING" ? "loading" : "ready";
|
|
2821
|
+
const onRemoveWallet = async (id) => {
|
|
2822
|
+
await disconnect(OfferOptionAddressId(id));
|
|
2823
|
+
refetch();
|
|
2824
|
+
};
|
|
2825
|
+
const onRequirementAction = onRequirementActionOverride !== void 0 ? onRequirementActionOverride : (requirement) => {
|
|
2826
|
+
if (requirement.type === "document") {
|
|
2827
|
+
setTaxDocumentOpen(true);
|
|
2828
|
+
return;
|
|
2829
|
+
}
|
|
2830
|
+
if ((requirement.type === "external_wallet" || requirement.type === "whitelisted_wallet") && wallet !== void 0 && (wallet !== null || onRequestConnect !== void 0)) {
|
|
2831
|
+
setConnectWalletOpen(true);
|
|
2832
|
+
return;
|
|
2833
|
+
}
|
|
2834
|
+
coinlist.handleRequirement(requirement);
|
|
2835
|
+
};
|
|
1227
2836
|
const onContactSupport = onContactSupportOverride !== void 0 ? onContactSupportOverride : () => coinlist.contactSupport();
|
|
2837
|
+
const awaitVerificationResult = (requirementId, statusBeforeSubmit) => {
|
|
2838
|
+
void (async () => {
|
|
2839
|
+
const deadline = Date.now() + VERIFICATION_POLL_TIMEOUT_MS;
|
|
2840
|
+
while (Date.now() < deadline) {
|
|
2841
|
+
await sleep(VERIFICATION_POLL_INTERVAL_MS);
|
|
2842
|
+
if (!isMountedRef.current) return;
|
|
2843
|
+
try {
|
|
2844
|
+
const statuses2 = await coinlist.fetchRequirementStatuses(offerId);
|
|
2845
|
+
const current = statuses2.find((s) => s.id === requirementId)?.status;
|
|
2846
|
+
if (current !== void 0 && current !== statusBeforeSubmit) break;
|
|
2847
|
+
} catch (_) {
|
|
2848
|
+
}
|
|
2849
|
+
}
|
|
2850
|
+
if (isMountedRef.current) {
|
|
2851
|
+
setVerifyingRequirementId(null);
|
|
2852
|
+
refetch();
|
|
2853
|
+
}
|
|
2854
|
+
})();
|
|
2855
|
+
};
|
|
1228
2856
|
if (requirementsState.type === "LOADING") {
|
|
1229
2857
|
if (loading) return loading;
|
|
1230
|
-
return /* @__PURE__ */
|
|
2858
|
+
return /* @__PURE__ */ jsx19(
|
|
1231
2859
|
"output",
|
|
1232
2860
|
{
|
|
1233
2861
|
"aria-live": "polite",
|
|
1234
|
-
className: "flex min-h-40 items-center justify-center rounded-2xl border border-border bg-background p-6",
|
|
1235
|
-
children: /* @__PURE__ */
|
|
2862
|
+
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",
|
|
2863
|
+
children: /* @__PURE__ */ jsx19("p", { className: cn(typeClasses.body, "clcosdk:text-text-secondary"), children: "Loading requirements..." })
|
|
1236
2864
|
}
|
|
1237
2865
|
);
|
|
1238
2866
|
}
|
|
1239
2867
|
if (requirementsState.type === "ERROR") {
|
|
2868
|
+
if (requirementsState.reason === "not-authenticated") {
|
|
2869
|
+
return unauthenticatedState !== void 0 ? unauthenticatedState : /* @__PURE__ */ jsx19(CoinListSignInCard, {});
|
|
2870
|
+
}
|
|
1240
2871
|
if (error) return error;
|
|
1241
|
-
|
|
1242
|
-
return /* @__PURE__ */ jsx14(
|
|
2872
|
+
return /* @__PURE__ */ jsx19(
|
|
1243
2873
|
AlertBanner,
|
|
1244
2874
|
{
|
|
1245
2875
|
variant: "error",
|
|
1246
2876
|
icon: true,
|
|
1247
|
-
content:
|
|
1248
|
-
className: "w-full max-w-[28rem]"
|
|
2877
|
+
content: "Unable to load requirements right now. Please try again.",
|
|
2878
|
+
className: "clcosdk:w-full clcosdk:max-w-[28rem]"
|
|
1249
2879
|
}
|
|
1250
2880
|
);
|
|
1251
2881
|
}
|
|
@@ -1255,76 +2885,310 @@ function RequirementsChecklist({
|
|
|
1255
2885
|
const optionStatuses = statuses.filter((s) => requirementIds.has(s.id));
|
|
1256
2886
|
const statusByRequirementId = new Map(optionStatuses.map((s) => [s.id, s]));
|
|
1257
2887
|
const checklistStatus = ChecklistStatus.derive(optionStatuses);
|
|
1258
|
-
return /* @__PURE__ */
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
2888
|
+
return /* @__PURE__ */ jsxs15(
|
|
2889
|
+
"div",
|
|
2890
|
+
{
|
|
2891
|
+
className: cn(
|
|
2892
|
+
"clcosdk:flex clcosdk:w-full clcosdk:flex-col clcosdk:gap-4",
|
|
2893
|
+
className
|
|
2894
|
+
),
|
|
2895
|
+
children: [
|
|
2896
|
+
/* @__PURE__ */ jsxs15("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-2", children: [
|
|
2897
|
+
/* @__PURE__ */ jsx19("h3", { className: cn(typeClasses.h3, "clcosdk:text-text-primary"), children: title }),
|
|
2898
|
+
/* @__PURE__ */ jsx19("p", { className: cn(typeClasses.body, "clcosdk:text-text-secondary"), children: description })
|
|
2899
|
+
] }),
|
|
2900
|
+
/* @__PURE__ */ jsx19("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:divide-y clcosdk:divide-divider", children: requirements.map((req, index) => {
|
|
2901
|
+
const statusInfo = statusByRequirementId.get(req.id);
|
|
2902
|
+
const label = getLabel ? getLabel(req) : DEFAULT_LABELS[req.type];
|
|
2903
|
+
const itemDescription = (getDescription ? getDescription(req) : null) ?? DEFAULT_DESCRIPTIONS[req.type];
|
|
2904
|
+
const inlineVerification = statusInfo?.kycLevel !== void 0 && onRequirementActionOverride === void 0;
|
|
2905
|
+
let onActionBound;
|
|
2906
|
+
if (onRequirementAction === null) {
|
|
2907
|
+
onActionBound = null;
|
|
2908
|
+
} else if (inlineVerification) {
|
|
2909
|
+
onActionBound = () => setVerifyingRequirementId(req.id);
|
|
2910
|
+
} else if (onRequirementAction) {
|
|
2911
|
+
onActionBound = () => onRequirementAction(req);
|
|
2912
|
+
}
|
|
2913
|
+
let onContactSupportBound;
|
|
2914
|
+
if (onContactSupport === null) {
|
|
2915
|
+
onContactSupportBound = null;
|
|
2916
|
+
} else if (onContactSupport) {
|
|
2917
|
+
onContactSupportBound = () => onContactSupport(req);
|
|
2918
|
+
}
|
|
2919
|
+
const walletRequirement = isWalletRequirement(req);
|
|
2920
|
+
return /* @__PURE__ */ jsx19(
|
|
2921
|
+
RequirementItem,
|
|
2922
|
+
{
|
|
2923
|
+
ui: RequirementItemUi.fromDomain(
|
|
2924
|
+
req,
|
|
2925
|
+
statusInfo,
|
|
2926
|
+
label,
|
|
2927
|
+
itemDescription,
|
|
2928
|
+
walletRequirement ? optionAddresses : []
|
|
2929
|
+
),
|
|
2930
|
+
expanded: expandedIndex === index,
|
|
2931
|
+
onToggle: () => setExpandedIndex((prev) => prev === index ? null : index),
|
|
2932
|
+
onAction: onActionBound,
|
|
2933
|
+
onRemoveWallet: walletRequirement ? onRemoveWallet : void 0,
|
|
2934
|
+
walletsStatus: walletRequirement ? walletsStatus : void 0,
|
|
2935
|
+
onContactSupport: onContactSupportBound
|
|
2936
|
+
},
|
|
2937
|
+
req.id
|
|
2938
|
+
);
|
|
2939
|
+
}) }),
|
|
2940
|
+
checklistStatus === "ineligible" && /* @__PURE__ */ jsx19(
|
|
2941
|
+
AlertBanner,
|
|
2942
|
+
{
|
|
2943
|
+
variant: "error",
|
|
2944
|
+
icon: true,
|
|
2945
|
+
content: "You are not eligible to participate."
|
|
2946
|
+
}
|
|
2947
|
+
),
|
|
2948
|
+
onContinue && /* @__PURE__ */ jsx19(
|
|
2949
|
+
ClButton,
|
|
2950
|
+
{
|
|
2951
|
+
fullWidth: true,
|
|
2952
|
+
disabled: checklistStatus !== "eligible",
|
|
2953
|
+
onClick: onContinue,
|
|
2954
|
+
children: "Continue"
|
|
2955
|
+
}
|
|
2956
|
+
),
|
|
2957
|
+
/* @__PURE__ */ jsx19(
|
|
2958
|
+
TaxDocumentModal,
|
|
2959
|
+
{
|
|
2960
|
+
isOpen: taxDocumentOpen,
|
|
2961
|
+
onClose: () => setTaxDocumentOpen(false),
|
|
2962
|
+
onSubmitted: () => refetch()
|
|
2963
|
+
}
|
|
2964
|
+
),
|
|
2965
|
+
verifyingRequirementId !== null && /* @__PURE__ */ jsx19(VerificationOverlay, { onClose: () => setVerifyingRequirementId(null), children: /* @__PURE__ */ jsx19(
|
|
2966
|
+
IdentityVerification,
|
|
2967
|
+
{
|
|
2968
|
+
levelName: identityVerificationOptions?.levelName ?? statusByRequirementId.get(verifyingRequirementId)?.kycLevel,
|
|
2969
|
+
reset: statusByRequirementId.get(verifyingRequirementId)?.kycReset ?? false,
|
|
2970
|
+
locale: identityVerificationOptions?.locale,
|
|
2971
|
+
onSubmitted: () => awaitVerificationResult(
|
|
2972
|
+
verifyingRequirementId,
|
|
2973
|
+
statusByRequirementId.get(verifyingRequirementId)?.status ?? "not_started"
|
|
2974
|
+
)
|
|
2975
|
+
}
|
|
2976
|
+
) }),
|
|
2977
|
+
/* @__PURE__ */ jsx19(
|
|
2978
|
+
ConnectWalletModal,
|
|
2979
|
+
{
|
|
2980
|
+
isOpen: walletConnectOpen,
|
|
2981
|
+
onClose: () => setConnectWalletOpen(false),
|
|
2982
|
+
offerId,
|
|
2983
|
+
optionId,
|
|
2984
|
+
wallet: wallet ?? null,
|
|
2985
|
+
onRequestConnect,
|
|
2986
|
+
onConnected: () => {
|
|
2987
|
+
refetch();
|
|
2988
|
+
refetchAddresses();
|
|
2989
|
+
}
|
|
2990
|
+
}
|
|
2991
|
+
)
|
|
2992
|
+
]
|
|
2993
|
+
}
|
|
2994
|
+
);
|
|
2995
|
+
}
|
|
2996
|
+
function RequirementsChecklist(props) {
|
|
2997
|
+
return /* @__PURE__ */ jsx19(CoinListStyleScope, { children: /* @__PURE__ */ jsx19(RequirementsChecklistBody, { ...props }) });
|
|
2998
|
+
}
|
|
2999
|
+
|
|
3000
|
+
// src/client/hooks/swap/useSwapOutputToken.ts
|
|
3001
|
+
import { useEffect as useEffect12, useRef as useRef5, useState as useState10 } from "react";
|
|
3002
|
+
var LOADING_STATE6 = { type: "LOADING" };
|
|
3003
|
+
function useSwapOutputToken(options) {
|
|
3004
|
+
const { contractAddress, chain, enabled } = options;
|
|
3005
|
+
const { coinlist, isReady } = useCoinList();
|
|
3006
|
+
const [outputTokenState, setOutputTokenState] = useState10(LOADING_STATE6);
|
|
3007
|
+
const fetchIdRef = useRef5(0);
|
|
3008
|
+
useEffect12(() => {
|
|
3009
|
+
if (!enabled || !isReady) return;
|
|
3010
|
+
const currentFetchId = ++fetchIdRef.current;
|
|
3011
|
+
const load = async () => {
|
|
3012
|
+
try {
|
|
3013
|
+
const outputToken = await coinlist.swap.getOutputToken({
|
|
3014
|
+
contractAddress,
|
|
3015
|
+
chain
|
|
3016
|
+
});
|
|
3017
|
+
if (currentFetchId !== fetchIdRef.current) return;
|
|
3018
|
+
setOutputTokenState({ type: "CONTENT", outputToken });
|
|
3019
|
+
} catch {
|
|
3020
|
+
if (currentFetchId !== fetchIdRef.current) return;
|
|
3021
|
+
setOutputTokenState({ type: "ERROR" });
|
|
1272
3022
|
}
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
3023
|
+
};
|
|
3024
|
+
load();
|
|
3025
|
+
return () => {
|
|
3026
|
+
++fetchIdRef.current;
|
|
3027
|
+
};
|
|
3028
|
+
}, [coinlist, isReady, contractAddress, chain, enabled]);
|
|
3029
|
+
return { outputTokenState };
|
|
3030
|
+
}
|
|
3031
|
+
|
|
3032
|
+
// src/client/hooks/swap/useSwapQuote.ts
|
|
3033
|
+
import { useEffect as useEffect13, useRef as useRef6, useState as useState11 } from "react";
|
|
3034
|
+
function useSwapQuote(options) {
|
|
3035
|
+
const {
|
|
3036
|
+
contractAddress,
|
|
3037
|
+
chain,
|
|
3038
|
+
inputAmount,
|
|
3039
|
+
inputTokenAddress,
|
|
3040
|
+
outputTokenDecimals,
|
|
3041
|
+
pollIntervalMs = SWAP_POLL_INTERVAL_MS,
|
|
3042
|
+
enabled
|
|
3043
|
+
} = options;
|
|
3044
|
+
const { coinlist, isReady } = useCoinList();
|
|
3045
|
+
const [quote, setQuote] = useState11(null);
|
|
3046
|
+
const [isLoading, setIsLoading] = useState11(true);
|
|
3047
|
+
const [isRefreshing, setIsRefreshing] = useState11(false);
|
|
3048
|
+
const isFetchingRef = useRef6(false);
|
|
3049
|
+
const hasQuoteRef = useRef6(false);
|
|
3050
|
+
const fetchIdRef = useRef6(0);
|
|
3051
|
+
useEffect13(() => {
|
|
3052
|
+
if (!isReady) return;
|
|
3053
|
+
if (!enabled) {
|
|
3054
|
+
setIsLoading(false);
|
|
3055
|
+
return;
|
|
3056
|
+
}
|
|
3057
|
+
const currentFetchId = ++fetchIdRef.current;
|
|
3058
|
+
isFetchingRef.current = false;
|
|
3059
|
+
const loadQuote = async () => {
|
|
3060
|
+
if (outputTokenDecimals === null) return;
|
|
3061
|
+
if (isFetchingRef.current) return;
|
|
3062
|
+
isFetchingRef.current = true;
|
|
3063
|
+
if (hasQuoteRef.current) {
|
|
3064
|
+
setIsRefreshing(true);
|
|
1278
3065
|
}
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
{
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
3066
|
+
try {
|
|
3067
|
+
const preview = await coinlist.swap.getPreview({
|
|
3068
|
+
contractAddress,
|
|
3069
|
+
chain,
|
|
3070
|
+
inputToken: inputTokenAddress,
|
|
3071
|
+
amount: inputAmount.raw
|
|
3072
|
+
});
|
|
3073
|
+
if (currentFetchId !== fetchIdRef.current) return;
|
|
3074
|
+
setQuote(
|
|
3075
|
+
SwapQuote.fromPreview(
|
|
3076
|
+
preview,
|
|
3077
|
+
inputAmount.decimals,
|
|
3078
|
+
outputTokenDecimals
|
|
3079
|
+
)
|
|
3080
|
+
);
|
|
3081
|
+
if (!hasQuoteRef.current) {
|
|
3082
|
+
hasQuoteRef.current = true;
|
|
3083
|
+
setIsLoading(false);
|
|
3084
|
+
}
|
|
3085
|
+
} catch {
|
|
3086
|
+
} finally {
|
|
3087
|
+
if (currentFetchId === fetchIdRef.current) {
|
|
3088
|
+
isFetchingRef.current = false;
|
|
3089
|
+
setIsRefreshing(false);
|
|
3090
|
+
}
|
|
1302
3091
|
}
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
3092
|
+
};
|
|
3093
|
+
loadQuote();
|
|
3094
|
+
const interval = setInterval(loadQuote, pollIntervalMs);
|
|
3095
|
+
return () => {
|
|
3096
|
+
clearInterval(interval);
|
|
3097
|
+
++fetchIdRef.current;
|
|
3098
|
+
setIsRefreshing(false);
|
|
3099
|
+
};
|
|
3100
|
+
}, [
|
|
3101
|
+
coinlist,
|
|
3102
|
+
isReady,
|
|
3103
|
+
contractAddress,
|
|
3104
|
+
chain,
|
|
3105
|
+
inputAmount.raw,
|
|
3106
|
+
inputAmount.decimals,
|
|
3107
|
+
inputTokenAddress,
|
|
3108
|
+
outputTokenDecimals,
|
|
3109
|
+
pollIntervalMs,
|
|
3110
|
+
enabled
|
|
3111
|
+
]);
|
|
3112
|
+
return { quote, isLoading, isRefreshing };
|
|
3113
|
+
}
|
|
3114
|
+
|
|
3115
|
+
// src/client/hooks/swap/useSwapTokenBalances.ts
|
|
3116
|
+
import { useEffect as useEffect14, useRef as useRef7, useState as useState12 } from "react";
|
|
3117
|
+
function useSwapTokenBalances(options) {
|
|
3118
|
+
const {
|
|
3119
|
+
address,
|
|
3120
|
+
chain,
|
|
3121
|
+
assets,
|
|
3122
|
+
pollIntervalMs = SWAP_POLL_INTERVAL_MS,
|
|
3123
|
+
enabled
|
|
3124
|
+
} = options;
|
|
3125
|
+
const { coinlist, isReady } = useCoinList();
|
|
3126
|
+
const [balances, setBalances] = useState12(/* @__PURE__ */ new Map());
|
|
3127
|
+
const [isLoading, setIsLoading] = useState12(true);
|
|
3128
|
+
const fetchIdRef = useRef7(0);
|
|
3129
|
+
const isFetchingRef = useRef7(false);
|
|
3130
|
+
const assetsKey = assets.join(",");
|
|
3131
|
+
useEffect14(() => {
|
|
3132
|
+
if (!isReady) return;
|
|
3133
|
+
if (!enabled) {
|
|
3134
|
+
setIsLoading(false);
|
|
3135
|
+
return;
|
|
3136
|
+
}
|
|
3137
|
+
const symbols = assetsKey.split(",");
|
|
3138
|
+
const currentFetchId = ++fetchIdRef.current;
|
|
3139
|
+
isFetchingRef.current = false;
|
|
3140
|
+
let isFirstFetch = true;
|
|
3141
|
+
async function fetchBalances() {
|
|
3142
|
+
if (isFetchingRef.current) return;
|
|
3143
|
+
isFetchingRef.current = true;
|
|
3144
|
+
if (isFirstFetch) {
|
|
3145
|
+
setIsLoading(true);
|
|
1311
3146
|
}
|
|
1312
|
-
|
|
1313
|
-
|
|
3147
|
+
const results = await Promise.allSettled(
|
|
3148
|
+
symbols.map(
|
|
3149
|
+
(symbol) => coinlist.swap.getTokenBalance({
|
|
3150
|
+
tokenAddress: TOKEN_REGISTRY.contractAddress(symbol, chain),
|
|
3151
|
+
owner: address,
|
|
3152
|
+
chain
|
|
3153
|
+
})
|
|
3154
|
+
)
|
|
3155
|
+
);
|
|
3156
|
+
if (currentFetchId !== fetchIdRef.current) return;
|
|
3157
|
+
isFetchingRef.current = false;
|
|
3158
|
+
const next = /* @__PURE__ */ new Map();
|
|
3159
|
+
symbols.forEach((symbol, i) => {
|
|
3160
|
+
const result = results[i];
|
|
3161
|
+
next.set(
|
|
3162
|
+
symbol,
|
|
3163
|
+
result.status === "fulfilled" ? result.value.balance : null
|
|
3164
|
+
);
|
|
3165
|
+
});
|
|
3166
|
+
setBalances(next);
|
|
3167
|
+
setIsLoading(false);
|
|
3168
|
+
isFirstFetch = false;
|
|
3169
|
+
}
|
|
3170
|
+
fetchBalances();
|
|
3171
|
+
const interval = setInterval(fetchBalances, pollIntervalMs);
|
|
3172
|
+
return () => {
|
|
3173
|
+
clearInterval(interval);
|
|
3174
|
+
++fetchIdRef.current;
|
|
3175
|
+
};
|
|
3176
|
+
}, [coinlist, isReady, address, chain, assetsKey, pollIntervalMs, enabled]);
|
|
3177
|
+
return { balances, isLoading };
|
|
1314
3178
|
}
|
|
1315
3179
|
|
|
1316
3180
|
// src/client/hooks/useCompleteOAuth.ts
|
|
1317
|
-
import { useEffect as
|
|
3181
|
+
import { useEffect as useEffect15, useRef as useRef8 } from "react";
|
|
1318
3182
|
function useCompleteOAuth(options) {
|
|
1319
3183
|
const { coinlist } = useCoinList();
|
|
1320
|
-
const postOAuthCompleteRef =
|
|
1321
|
-
const onFailureRef =
|
|
1322
|
-
const onSuccessRef =
|
|
3184
|
+
const postOAuthCompleteRef = useRef8(options.postOAuthComplete);
|
|
3185
|
+
const onFailureRef = useRef8(options.onFailure);
|
|
3186
|
+
const onSuccessRef = useRef8(options.onSuccess);
|
|
1323
3187
|
postOAuthCompleteRef.current = options.postOAuthComplete;
|
|
1324
3188
|
onFailureRef.current = options.onFailure;
|
|
1325
3189
|
onSuccessRef.current = options.onSuccess;
|
|
1326
|
-
const hasStartedExchangeRef =
|
|
1327
|
-
|
|
3190
|
+
const hasStartedExchangeRef = useRef8(false);
|
|
3191
|
+
useEffect15(() => {
|
|
1328
3192
|
if (typeof window === "undefined") return;
|
|
1329
3193
|
const params = new URLSearchParams(window.location.search);
|
|
1330
3194
|
if (!params.has("code") && !params.has("error")) return;
|
|
@@ -1368,19 +3232,19 @@ function useCompleteOAuth(options) {
|
|
|
1368
3232
|
}
|
|
1369
3233
|
|
|
1370
3234
|
// src/client/hooks/useOfferDetails.ts
|
|
1371
|
-
import { useEffect as
|
|
1372
|
-
var
|
|
3235
|
+
import { useEffect as useEffect16, useState as useState13 } from "react";
|
|
3236
|
+
var LOADING_STATE7 = { type: "LOADING" };
|
|
1373
3237
|
function useOfferDetails(offerId, options = {}) {
|
|
1374
3238
|
const { coinlist, isReady } = useCoinList();
|
|
1375
3239
|
const { data } = options;
|
|
1376
|
-
const [offerDetailsState, setOfferDetailsState] =
|
|
1377
|
-
data !== void 0 ? { type: "CONTENT", offerDetail: data } :
|
|
3240
|
+
const [offerDetailsState, setOfferDetailsState] = useState13(
|
|
3241
|
+
data !== void 0 ? { type: "CONTENT", offerDetail: data } : LOADING_STATE7
|
|
1378
3242
|
);
|
|
1379
|
-
|
|
3243
|
+
useEffect16(() => {
|
|
1380
3244
|
let isCancelled = false;
|
|
1381
3245
|
if (!isReady) {
|
|
1382
3246
|
if (data === void 0) {
|
|
1383
|
-
setOfferDetailsState(
|
|
3247
|
+
setOfferDetailsState(LOADING_STATE7);
|
|
1384
3248
|
}
|
|
1385
3249
|
return () => {
|
|
1386
3250
|
isCancelled = true;
|
|
@@ -1391,7 +3255,7 @@ function useOfferDetails(offerId, options = {}) {
|
|
|
1391
3255
|
isCancelled = true;
|
|
1392
3256
|
};
|
|
1393
3257
|
}
|
|
1394
|
-
setOfferDetailsState(
|
|
3258
|
+
setOfferDetailsState(LOADING_STATE7);
|
|
1395
3259
|
coinlist.fetchOfferDetails(offerId).then((offerDetail) => {
|
|
1396
3260
|
if (!isCancelled) {
|
|
1397
3261
|
setOfferDetailsState({ type: "CONTENT", offerDetail });
|
|
@@ -1410,19 +3274,19 @@ function useOfferDetails(offerId, options = {}) {
|
|
|
1410
3274
|
}
|
|
1411
3275
|
|
|
1412
3276
|
// src/client/hooks/useParticipations.ts
|
|
1413
|
-
import { useEffect as
|
|
1414
|
-
var
|
|
3277
|
+
import { useEffect as useEffect17, useState as useState14 } from "react";
|
|
3278
|
+
var LOADING_STATE8 = { type: "LOADING" };
|
|
1415
3279
|
function useParticipations(offerId, options = {}) {
|
|
1416
3280
|
const { coinlist, isReady } = useCoinList();
|
|
1417
3281
|
const { data } = options;
|
|
1418
|
-
const [participationsState, setParticipationsState] =
|
|
1419
|
-
data !== void 0 ? { type: "CONTENT", participations: data } :
|
|
3282
|
+
const [participationsState, setParticipationsState] = useState14(
|
|
3283
|
+
data !== void 0 ? { type: "CONTENT", participations: data } : LOADING_STATE8
|
|
1420
3284
|
);
|
|
1421
|
-
|
|
3285
|
+
useEffect17(() => {
|
|
1422
3286
|
let isCancelled = false;
|
|
1423
3287
|
if (!isReady) {
|
|
1424
3288
|
if (data === void 0) {
|
|
1425
|
-
setParticipationsState(
|
|
3289
|
+
setParticipationsState(LOADING_STATE8);
|
|
1426
3290
|
}
|
|
1427
3291
|
return () => {
|
|
1428
3292
|
isCancelled = true;
|
|
@@ -1433,7 +3297,7 @@ function useParticipations(offerId, options = {}) {
|
|
|
1433
3297
|
isCancelled = true;
|
|
1434
3298
|
};
|
|
1435
3299
|
}
|
|
1436
|
-
setParticipationsState(
|
|
3300
|
+
setParticipationsState(LOADING_STATE8);
|
|
1437
3301
|
coinlist.fetchParticipations(offerId).then((participations) => {
|
|
1438
3302
|
if (!isCancelled) {
|
|
1439
3303
|
setParticipationsState({ type: "CONTENT", participations });
|
|
@@ -1452,10 +3316,17 @@ function useParticipations(offerId, options = {}) {
|
|
|
1452
3316
|
}
|
|
1453
3317
|
export {
|
|
1454
3318
|
ChecklistStatus,
|
|
3319
|
+
ClientSwapNamespaceImpl,
|
|
1455
3320
|
CoinListClientInitializationError,
|
|
1456
3321
|
CoinListContext,
|
|
3322
|
+
CoinListContextProvider,
|
|
1457
3323
|
CoinListProvider,
|
|
1458
3324
|
CoinListSignInCard,
|
|
3325
|
+
CoinListStyleScope,
|
|
3326
|
+
ConnectWalletModal,
|
|
3327
|
+
ConnectedWalletList,
|
|
3328
|
+
IdentityVerification,
|
|
3329
|
+
KycToken,
|
|
1459
3330
|
OAUTH_CODE_VERIFIER_KEY,
|
|
1460
3331
|
OAUTH_STATE_KEY,
|
|
1461
3332
|
OfferCard,
|
|
@@ -1466,12 +3337,24 @@ export {
|
|
|
1466
3337
|
RequirementStatus,
|
|
1467
3338
|
RequirementVariant,
|
|
1468
3339
|
RequirementsChecklist,
|
|
3340
|
+
TaxDocumentModal,
|
|
3341
|
+
authorizeWallet,
|
|
3342
|
+
classifyWalletError,
|
|
3343
|
+
connectExternalWalletFlow,
|
|
1469
3344
|
createCoinListClient,
|
|
3345
|
+
executeSwap,
|
|
1470
3346
|
useCoinList,
|
|
1471
3347
|
useCompleteOAuth,
|
|
3348
|
+
useConnectWallet,
|
|
3349
|
+
useKycToken,
|
|
1472
3350
|
useOfferDetails,
|
|
1473
3351
|
useOffers,
|
|
3352
|
+
useOptionAddresses,
|
|
1474
3353
|
useParticipations,
|
|
1475
|
-
useRequirements
|
|
3354
|
+
useRequirements,
|
|
3355
|
+
useSwapOutputToken,
|
|
3356
|
+
useSwapQuote,
|
|
3357
|
+
useSwapTokenBalances,
|
|
3358
|
+
useTaxDocument
|
|
1476
3359
|
};
|
|
1477
3360
|
//# sourceMappingURL=index.js.map
|