@coinlist-co/react 0.12.2-rc.8a0d02a → 0.12.2-rc.99b1bd5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/README.md +10 -0
  2. package/dist/{chunk-IZJ4JSSC.js → chunk-IQAJ3L25.js} +173 -253
  3. package/dist/chunk-IQAJ3L25.js.map +1 -0
  4. package/dist/{chunk-3WW5FLT7.js → chunk-J45AY2FX.js} +10 -10
  5. package/dist/chunk-J45AY2FX.js.map +1 -0
  6. package/dist/{chunk-C6GF7MDF.js → chunk-M2TURNJH.js} +876 -800
  7. package/dist/chunk-M2TURNJH.js.map +1 -0
  8. package/dist/chunk-MJ6YXZWH.js +22 -0
  9. package/dist/chunk-MJ6YXZWH.js.map +1 -0
  10. package/dist/client/index.d.ts +2836 -5619
  11. package/dist/client/index.js +7157 -8250
  12. package/dist/client/index.js.map +1 -1
  13. package/dist/server/index.d.ts +2 -32
  14. package/dist/server/index.js +6 -4
  15. package/dist/server/index.js.map +1 -1
  16. package/dist/{time-CVZpAkGY.d.cts → time-DkU7jivQ.d.ts} +1907 -3185
  17. package/dist/{token-registry-snapshot-BkwA8KmD.d.ts → token-registry-snapshot-D0OWXMe4.d.ts} +22 -58
  18. package/dist/universal/index.d.ts +81 -1067
  19. package/dist/universal/index.js +22 -46
  20. package/package.json +18 -14
  21. package/dist/chunk-3WW5FLT7.js.map +0 -1
  22. package/dist/chunk-C6GF7MDF.js.map +0 -1
  23. package/dist/chunk-IZJ4JSSC.js.map +0 -1
  24. package/dist/client/index.cjs +0 -20460
  25. package/dist/client/index.cjs.map +0 -1
  26. package/dist/client/index.d.cts +0 -8195
  27. package/dist/server/index.cjs +0 -4525
  28. package/dist/server/index.cjs.map +0 -1
  29. package/dist/server/index.d.cts +0 -382
  30. package/dist/time-CVZpAkGY.d.ts +0 -3987
  31. package/dist/token-registry-snapshot-bR14QehS.d.cts +0 -245
  32. package/dist/universal/index.cjs +0 -4562
  33. package/dist/universal/index.cjs.map +0 -1
  34. package/dist/universal/index.d.cts +0 -1362
package/README.md CHANGED
@@ -37,3 +37,13 @@ The flake provides the toolchain, not `node_modules` — install JS dependencies
37
37
  ```bash
38
38
  npm ci
39
39
  ```
40
+
41
+ ## Git hooks
42
+
43
+ The dev shell includes [pre-commit](https://pre-commit.com/). Register the push hook once:
44
+
45
+ ```bash
46
+ pre-commit install --hook-type pre-push
47
+ ```
48
+
49
+ The hook runs typecheck, Biome, and deslop.
@@ -9,19 +9,20 @@ import {
9
9
  MAX_UINT_256,
10
10
  MathError,
11
11
  NA_AMOUNT_ASSET_UI,
12
- SUPERSTATE_SWAP_ABI,
13
12
  StablecoinSymbol,
14
13
  apiErrorCode,
15
14
  arrayBufferToBase64Url,
16
15
  assertUint256,
16
+ contractOn,
17
17
  fetchOfferDetails,
18
18
  fetchOffers,
19
19
  fetchOffersPage,
20
20
  formattedUsdPrice,
21
21
  generateSecureRandomBase64Url,
22
22
  internalLogger,
23
+ pricePerShare,
23
24
  sha256
24
- } from "./chunk-C6GF7MDF.js";
25
+ } from "./chunk-M2TURNJH.js";
25
26
 
26
27
  // src/universal/types/oauth.ts
27
28
  var AuthorizationCode = (value) => value;
@@ -49,42 +50,125 @@ async function generatePKCEParams(config) {
49
50
  };
50
51
  }
51
52
 
52
- // src/universal/core/checkout/centrifuge/constants.ts
53
- var CENTRIFUGE_POLL_INTERVAL_MS = 15e3;
53
+ // src/universal/types/blockchain/wallet-error.ts
54
+ var RedactedWalletError = {
55
+ fromWalletError: (error) => error.type === "unknown" ? { type: "unknown" } : error
56
+ };
54
57
 
55
- // src/universal/core/checkout/centrifuge/vaults.ts
56
- function resolveCentrifugeVaults(offer, lookup) {
57
- return offer.vaultContracts.map((contract) => {
58
- const { chain } = contract;
59
- if (!isEthereumChain(chain)) {
60
- return { type: "unresolved", chain, missing: "evm-chain" };
61
- }
62
- const onChain = (role) => offer.tokens.filter(
63
- (token) => token.role === role && token.chain === chain
64
- );
65
- const share = firstKnown(onChain("vault"), lookup);
66
- if (share === null) {
67
- return { type: "unresolved", chain, missing: "share-token" };
68
- }
69
- const funding = firstKnown(onChain("funding"), lookup);
70
- if (funding === null) {
71
- return { type: "unresolved", chain, missing: "funding-token" };
58
+ // src/universal/core/offers/swap-contracts.ts
59
+ function swapSpender(swapContracts, chain) {
60
+ return contractOn(swapContracts, chain);
61
+ }
62
+
63
+ // src/universal/core/shared/blockchain/bps.ts
64
+ var BPS_DENOM = Bps(10000n);
65
+ function applyBps(amount, bps) {
66
+ return assertUint256(amount * bps / BPS_DENOM);
67
+ }
68
+
69
+ // src/universal/core/providers/checkout/superstate/blockchain/math.ts
70
+ function computePrice({
71
+ inputTokenAmount,
72
+ outputTokenAmount
73
+ }) {
74
+ if (outputTokenAmount.raw === 0n) return null;
75
+ return pricePerShare({ usd: inputTokenAmount, shares: outputTokenAmount });
76
+ }
77
+ function computeSlip(amount, slippage) {
78
+ const retained = Bps(assertUint256(BPS_DENOM - slippage));
79
+ const slipRaw = applyBps(amount.raw, retained);
80
+ return BlockchainAmount({ raw: slipRaw, decimals: amount.decimals });
81
+ }
82
+
83
+ // src/universal/core/providers/checkout/superstate/blockchain/status.ts
84
+ var SWAP_LEVEL = 2;
85
+ function isSwapAvailable(status) {
86
+ switch (status.state) {
87
+ case "active":
88
+ return true;
89
+ case "stopped":
90
+ return false;
91
+ case "paused":
92
+ return (status.pausedLevels & SWAP_LEVEL) === 0;
93
+ default: {
94
+ const _exhaustive = status;
95
+ return _exhaustive;
72
96
  }
73
- return {
74
- type: "resolved",
75
- vault: { chain, proxy: contract.address, share, funding }
76
- };
77
- });
97
+ }
78
98
  }
79
- function firstKnown(tokens, lookup) {
80
- for (const token of tokens) {
81
- const metadata = lookup(token);
82
- if (metadata !== null) return metadata;
99
+
100
+ // src/universal/core/offers/offers-namespace.ts
101
+ var OffersNamespaceImpl = class {
102
+ constructor(ctx) {
103
+ this.ctx = ctx;
104
+ this.log = internalLogger(ctx.logger, "OFFERS");
83
105
  }
84
- return null;
106
+ async list() {
107
+ return this.log.wrap("list", void 0, async () => {
108
+ await this.ctx.ensureUserAuthenticated();
109
+ return fetchOffers(this.ctx.api, void 0);
110
+ });
111
+ }
112
+ async listPage(params) {
113
+ return this.log.wrap("listPage", params, async () => {
114
+ await this.ctx.ensureUserAuthenticated();
115
+ return fetchOffersPage(this.ctx.api, params, void 0);
116
+ });
117
+ }
118
+ async get(id) {
119
+ return this.log.wrap("get", id, async () => {
120
+ await this.ctx.ensureUserAuthenticated();
121
+ return fetchOfferDetails(this.ctx.api, id, void 0);
122
+ });
123
+ }
124
+ };
125
+
126
+ // src/universal/core/tokens/token-registry-snapshot.ts
127
+ var TokenRegistrySnapshot = {
128
+ /** Indexes a `tokens.list()` result. `[]` is a valid, empty snapshot. */
129
+ fromTokens: (tokens) => ({
130
+ tokens,
131
+ byKey: new Map(
132
+ tokens.map((token) => [registryKey(token.identifier), token])
133
+ )
134
+ }),
135
+ /**
136
+ * The registry's entry for one token, or `null` when it lists none. The
137
+ * registry is curated, so `null` is an ordinary answer rather than an
138
+ * error, and callers fall back to their own display defaults.
139
+ */
140
+ get: (snapshot, token) => snapshot.byKey.get(registryKey(token)) ?? null,
141
+ /**
142
+ * The registry's entry for the token an offer is *about*, or `null` when
143
+ * it lists none of them.
144
+ *
145
+ * Resolution follows {@link offerDisplayTokens}: the token a sale
146
+ * distributes or a swap hands over, never the funding token the user pays
147
+ * with. An offer deployed on several chains carries one such token per
148
+ * chain, and the first the registry knows wins - they are the same asset,
149
+ * so any listed one answers for the offer.
150
+ */
151
+ forOffer: (snapshot, offer) => {
152
+ for (const token of offerDisplayTokens(offer)) {
153
+ const metadata = TokenRegistrySnapshot.get(snapshot, token);
154
+ if (metadata !== null) {
155
+ return metadata;
156
+ }
157
+ }
158
+ return null;
159
+ }
160
+ };
161
+ function offerDisplayTokens(offer) {
162
+ const swaps = offer.tokens.filter(
163
+ (token) => token.role === "swap" || token.role === "vault"
164
+ );
165
+ const distributions = offer.tokens.filter(
166
+ (token) => token.role === "distribution"
167
+ );
168
+ return [...swaps, ...distributions];
85
169
  }
86
- function isEthereumChain(chain) {
87
- return chain in ETHEREUM_CHAINS;
170
+ function registryKey(token) {
171
+ return `${token.chain}:${token.address.toLowerCase()}`;
88
172
  }
89
173
 
90
174
  // src/universal/core/shared/blockchain/token-registry.ts
@@ -150,7 +234,13 @@ var TOKEN_REGISTRY = {
150
234
  usdtAddress: (chain) => USDT_ADDRESSES[chain]
151
235
  };
152
236
 
153
- // src/universal/core/checkout/ondo/constants.ts
237
+ // src/universal/core/providers/checkout/ondo/not-tradable.ts
238
+ var ONDO_NOT_TRADABLE_CODE = "not_tradable";
239
+ function isOndoNotTradableError(error) {
240
+ return apiErrorCode(error) === ONDO_NOT_TRADABLE_CODE;
241
+ }
242
+
243
+ // src/universal/core/providers/checkout/ondo/constants.ts
154
244
  var ONDO_POLL_INTERVAL_MS = 15e3;
155
245
  var ONDO_QUOTE_MAX_TTL_MS = 15e3;
156
246
  var DEFAULT_ONDO_AMOUNT_TO_COMPUTE_PRICE = DecimalString("1000");
@@ -160,7 +250,7 @@ var ONDO_SUPPORTED_INPUT_ASSETS = [
160
250
  USDC_SYMBOL
161
251
  ];
162
252
 
163
- // src/universal/core/checkout/ondo/math.ts
253
+ // src/universal/core/providers/checkout/ondo/math.ts
164
254
  function computeOndoBuyPrice(transaction) {
165
255
  const { notionalValue, receiveOutputAmount } = transaction;
166
256
  return pricePerShare({
@@ -185,110 +275,8 @@ function grossProceeds(expected) {
185
275
  }
186
276
  return BlockchainAmount.add(expected.quantity, expected.fee);
187
277
  }
188
- function pricePerShare({
189
- usd,
190
- shares
191
- }) {
192
- const price = BlockchainAmount.div(usd, shares);
193
- return BlockchainAmount({
194
- raw: assertPriceFits(price.raw),
195
- decimals: price.decimals
196
- });
197
- }
198
- function assertPriceFits(raw) {
199
- try {
200
- return assertUint256(raw);
201
- } catch {
202
- throw new MathError(`Ondo price: out of uint256 bounds (${raw})`);
203
- }
204
- }
205
-
206
- // src/universal/core/checkout/ondo/not-tradable.ts
207
- var ONDO_NOT_TRADABLE_CODE = "not_tradable";
208
- function isOndoNotTradableError(error) {
209
- return apiErrorCode(error) === ONDO_NOT_TRADABLE_CODE;
210
- }
211
-
212
- // src/universal/core/shared/blockchain/bps.ts
213
- var BPS_DENOM = Bps(10000n);
214
- function applyBps(amount, bps) {
215
- return assertUint256(amount * bps / BPS_DENOM);
216
- }
217
-
218
- // src/universal/core/checkout/superstate/blockchain/math.ts
219
- function computePrice({
220
- inputTokenAmount,
221
- outputTokenAmount
222
- }) {
223
- if (outputTokenAmount.raw === 0n) return null;
224
- const scale = 10n ** BigInt(outputTokenAmount.decimals);
225
- const raw = assertUint256(
226
- inputTokenAmount.raw * scale / outputTokenAmount.raw
227
- );
228
- return BlockchainAmount({ raw, decimals: inputTokenAmount.decimals });
229
- }
230
- function computeSlip(amount, slippage) {
231
- const retained = Bps(assertUint256(BPS_DENOM - slippage));
232
- const slipRaw = applyBps(amount.raw, retained);
233
- return BlockchainAmount({ raw: slipRaw, decimals: amount.decimals });
234
- }
235
-
236
- // src/universal/core/checkout/superstate/blockchain/quote.ts
237
- var SwapQuote = {
238
- /**
239
- * Assembles a {@link SwapQuote} from a raw contract {@link SwapPreview}. The
240
- * input and fee are denominated in the input token; the output in the output
241
- * token.
242
- */
243
- fromPreview: (preview, inputDecimals, outputDecimals) => ({
244
- inputTokenAmount: BlockchainAmount({
245
- raw: preview.inputAmount,
246
- decimals: inputDecimals
247
- }),
248
- fee: BlockchainAmount({ raw: preview.fee, decimals: inputDecimals }),
249
- outputTokenAmount: BlockchainAmount({
250
- raw: preview.outputAmount,
251
- decimals: outputDecimals
252
- })
253
- })
254
- };
255
-
256
- // src/universal/core/checkout/superstate/blockchain/status.ts
257
- var SWAP_LEVEL = 2;
258
- function isSwapAvailable(status) {
259
- switch (status.state) {
260
- case "active":
261
- return true;
262
- case "stopped":
263
- return false;
264
- case "paused":
265
- return (status.pausedLevels & SWAP_LEVEL) === 0;
266
- default: {
267
- const _exhaustive = status;
268
- return _exhaustive;
269
- }
270
- }
271
- }
272
278
 
273
- // src/universal/core/checkout/superstate/blockchain/swapped-event.ts
274
- import { parseEventLogs } from "viem";
275
- function decodeSwappedOutputAmount(receipt, outputDecimals) {
276
- try {
277
- const [swapped] = parseEventLogs({
278
- abi: SUPERSTATE_SWAP_ABI,
279
- eventName: "Swapped",
280
- logs: receipt.logs
281
- });
282
- if (!swapped) return null;
283
- const raw = swapped.args.outputAmount;
284
- if (raw < 0n || raw > MAX_UINT_256) return null;
285
- return BlockchainAmount({ raw, decimals: outputDecimals });
286
- } catch {
287
- return null;
288
- }
289
- }
290
-
291
- // src/universal/core/checkout/superstate/constants.ts
279
+ // src/universal/core/providers/checkout/superstate/constants.ts
292
280
  var SUPERSTATE_ISSUER_NAME = "Superstate";
293
281
  var SUPERSTATE_SUPPORTED_INPUT_ASSETS = [USDC_SYMBOL];
294
282
  var SWAP_POLL_INTERVAL_MS = 15e3;
@@ -305,96 +293,12 @@ function superstateSwapContractAddress(chain) {
305
293
  return SUPERSTATE_SWAP_CONTRACT_ADDRESSES[chain] ?? null;
306
294
  }
307
295
 
308
- // src/universal/core/checkout/superstate/formatters.ts
296
+ // src/universal/core/providers/checkout/superstate/formatters.ts
309
297
  function formattedPricePerShare(quote, locale) {
310
298
  if (!quote) return NA_AMOUNT_ASSET_UI;
311
299
  return formattedUsdPrice(computePrice(quote), locale);
312
300
  }
313
301
 
314
- // src/universal/core/offers/offers-namespace.ts
315
- var OffersNamespaceImpl = class {
316
- constructor(ctx) {
317
- this.ctx = ctx;
318
- this.log = internalLogger(ctx.logger, "OFFERS");
319
- }
320
- async list() {
321
- return this.log.wrap("list", void 0, async () => {
322
- await this.ctx.ensureUserAuthenticated();
323
- return fetchOffers(this.ctx.api, void 0);
324
- });
325
- }
326
- async listPage(params) {
327
- return this.log.wrap("listPage", params, async () => {
328
- await this.ctx.ensureUserAuthenticated();
329
- return fetchOffersPage(this.ctx.api, params, void 0);
330
- });
331
- }
332
- async get(id) {
333
- return this.log.wrap("get", id, async () => {
334
- await this.ctx.ensureUserAuthenticated();
335
- return fetchOfferDetails(this.ctx.api, id, void 0);
336
- });
337
- }
338
- };
339
-
340
- // src/universal/core/offers/swap-contracts.ts
341
- function swapSpender(swapContracts, chain) {
342
- return swapContracts.find((contract) => contract.chain === chain)?.address ?? null;
343
- }
344
-
345
- // src/universal/core/tokens/token-registry-snapshot.ts
346
- var TokenRegistrySnapshot = {
347
- /** Indexes a `tokens.list()` result. `[]` is a valid, empty snapshot. */
348
- fromTokens: (tokens) => ({
349
- tokens,
350
- byKey: new Map(
351
- tokens.map((token) => [registryKey(token.identifier), token])
352
- )
353
- }),
354
- /**
355
- * The registry's entry for one token, or `null` when it lists none. The
356
- * registry is curated, so `null` is an ordinary answer rather than an
357
- * error, and callers fall back to their own display defaults.
358
- */
359
- get: (snapshot, token) => snapshot.byKey.get(registryKey(token)) ?? null,
360
- /**
361
- * The registry's entry for the token an offer is *about*, or `null` when
362
- * it lists none of them.
363
- *
364
- * Resolution follows {@link offerDisplayTokens}: the token a sale
365
- * distributes or a swap hands over, never the funding token the user pays
366
- * with. An offer deployed on several chains carries one such token per
367
- * chain, and the first the registry knows wins - they are the same asset,
368
- * so any listed one answers for the offer.
369
- */
370
- forOffer: (snapshot, offer) => {
371
- for (const token of offerDisplayTokens(offer)) {
372
- const metadata = TokenRegistrySnapshot.get(snapshot, token);
373
- if (metadata !== null) {
374
- return metadata;
375
- }
376
- }
377
- return null;
378
- }
379
- };
380
- function offerDisplayTokens(offer) {
381
- const swaps = offer.tokens.filter(
382
- (token) => token.role === "swap" || token.role === "vault"
383
- );
384
- const distributions = offer.tokens.filter(
385
- (token) => token.role === "distribution"
386
- );
387
- return [...swaps, ...distributions];
388
- }
389
- function registryKey(token) {
390
- return `${token.chain}:${token.address.toLowerCase()}`;
391
- }
392
-
393
- // src/universal/types/blockchain/wallet-error.ts
394
- var RedactedWalletError = {
395
- fromWalletError: (error) => error.type === "unknown" ? { type: "unknown" } : error
396
- };
397
-
398
302
  // src/universal/types/blockchain/wallet-selection.ts
399
303
  var WalletSelection = {
400
304
  /**
@@ -416,15 +320,40 @@ var WalletSelection = {
416
320
  }
417
321
  };
418
322
 
419
- // src/universal/types/user.ts
420
- var UserId = (value) => value;
421
- var UserEmail = (value) => value;
422
- var User = {
423
- fromDto: (dto) => ({
424
- id: UserId(dto.id),
425
- email: UserEmail(dto.email)
426
- })
427
- };
323
+ // src/universal/core/providers/checkout/centrifuge/vaults.ts
324
+ function resolveCentrifugeVaults(offer, lookup) {
325
+ return offer.vaultContracts.map((contract) => {
326
+ const { chain } = contract;
327
+ if (!isEthereumChain(chain)) {
328
+ return { type: "unresolved", chain, missing: "evm-chain" };
329
+ }
330
+ const onChain = (role) => offer.tokens.filter(
331
+ (token) => token.role === role && token.chain === chain
332
+ );
333
+ const share = firstKnown(onChain("vault"), lookup);
334
+ if (share === null) {
335
+ return { type: "unresolved", chain, missing: "share-token" };
336
+ }
337
+ const funding = firstKnown(onChain("funding"), lookup);
338
+ if (funding === null) {
339
+ return { type: "unresolved", chain, missing: "funding-token" };
340
+ }
341
+ return {
342
+ type: "resolved",
343
+ vault: { chain, proxy: contract.address, share, funding }
344
+ };
345
+ });
346
+ }
347
+ function firstKnown(tokens, lookup) {
348
+ for (const token of tokens) {
349
+ const metadata = lookup(token);
350
+ if (metadata !== null) return metadata;
351
+ }
352
+ return null;
353
+ }
354
+ function isEthereumChain(chain) {
355
+ return chain in ETHEREUM_CHAINS;
356
+ }
428
357
 
429
358
  export {
430
359
  AuthorizationCode,
@@ -436,32 +365,29 @@ export {
436
365
  ClientSecret,
437
366
  generatePKCEParams,
438
367
  RedactedWalletError,
439
- CENTRIFUGE_POLL_INTERVAL_MS,
440
- resolveCentrifugeVaults,
368
+ swapSpender,
369
+ computePrice,
370
+ computeSlip,
371
+ SWAP_LEVEL,
372
+ isSwapAvailable,
373
+ OffersNamespaceImpl,
374
+ TokenRegistrySnapshot,
375
+ offerDisplayTokens,
441
376
  USDC_SYMBOL,
442
377
  USDC,
443
378
  USDT_SYMBOL,
444
379
  USDT,
445
380
  TOKEN_REGISTRY,
446
381
  ONDO_POLL_INTERVAL_MS,
447
- ONDO_QUOTE_MAX_TTL_MS,
448
382
  DEFAULT_ONDO_AMOUNT_TO_COMPUTE_PRICE,
449
383
  ONDO_SETTLEMENT_ASSET,
450
384
  DEFAULT_ONDO_SELL_TOKENS_TO_COMPUTE_PRICE,
451
385
  ONDO_SUPPORTED_INPUT_ASSETS,
386
+ ONDO_NOT_TRADABLE_CODE,
387
+ isOndoNotTradableError,
452
388
  computeOndoBuyPrice,
453
389
  computeOndoSellPrice,
454
390
  ondoQuoteOfferDeadline,
455
- ONDO_NOT_TRADABLE_CODE,
456
- isOndoNotTradableError,
457
- BPS_DENOM,
458
- applyBps,
459
- computePrice,
460
- computeSlip,
461
- SwapQuote,
462
- SWAP_LEVEL,
463
- isSwapAvailable,
464
- decodeSwappedOutputAmount,
465
391
  SUPERSTATE_ISSUER_NAME,
466
392
  SUPERSTATE_SUPPORTED_INPUT_ASSETS,
467
393
  SWAP_POLL_INTERVAL_MS,
@@ -471,13 +397,7 @@ export {
471
397
  SUPERSTATE_SWAP_CONTRACT_ADDRESS_SEPOLIA,
472
398
  superstateSwapContractAddress,
473
399
  formattedPricePerShare,
474
- OffersNamespaceImpl,
475
- swapSpender,
476
- TokenRegistrySnapshot,
477
- offerDisplayTokens,
478
400
  WalletSelection,
479
- UserId,
480
- UserEmail,
481
- User
401
+ resolveCentrifugeVaults
482
402
  };
483
- //# sourceMappingURL=chunk-IZJ4JSSC.js.map
403
+ //# sourceMappingURL=chunk-IQAJ3L25.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/universal/types/oauth.ts","../src/universal/core/auth/pkce.ts","../src/universal/types/blockchain/wallet-error.ts","../src/universal/core/offers/swap-contracts.ts","../src/universal/core/shared/blockchain/bps.ts","../src/universal/core/providers/checkout/superstate/blockchain/math.ts","../src/universal/core/providers/checkout/superstate/blockchain/status.ts","../src/universal/core/offers/offers-namespace.ts","../src/universal/core/tokens/token-registry-snapshot.ts","../src/universal/core/shared/blockchain/token-registry.ts","../src/universal/core/providers/checkout/ondo/not-tradable.ts","../src/universal/core/providers/checkout/ondo/constants.ts","../src/universal/core/providers/checkout/ondo/math.ts","../src/universal/core/providers/checkout/superstate/constants.ts","../src/universal/core/providers/checkout/superstate/formatters.ts","../src/universal/types/blockchain/wallet-selection.ts","../src/universal/core/providers/checkout/centrifuge/vaults.ts"],"sourcesContent":["import type { Newtype } from '@/universal/types/newtype';\n\nexport type AuthorizationCode = Newtype<string, 'AuthorizationCode'>;\nexport const AuthorizationCode = (value: string): AuthorizationCode =>\n value as AuthorizationCode;\n\nexport type CodeVerifier = Newtype<string, 'CodeVerifier'>;\nexport const CodeVerifier = (value: string): CodeVerifier =>\n value as CodeVerifier;\n\nexport type CodeChallenge = Newtype<string, 'CodeChallenge'>;\nexport const CodeChallenge = (value: string): CodeChallenge =>\n value as CodeChallenge;\n\nexport type PKCEState = Newtype<string, 'PKCEState'>;\nexport const PKCEState = (value: string) => value as PKCEState;\n\nexport type RedirectUri = Newtype<string, 'RedirectUri'>;\nexport const RedirectUri = (value: string): RedirectUri => value as RedirectUri;\n\nexport type ClientId = Newtype<string, 'ClientId'>;\nexport const ClientId = (value: string): ClientId => value as ClientId;\n\nexport type ClientSecret = Newtype<string, 'ClientSecret'>;\nexport const ClientSecret = (value: string): ClientSecret =>\n value as ClientSecret;\n","import {\n arrayBufferToBase64Url,\n generateSecureRandomBase64Url,\n sha256,\n} from '@/universal/core/shared/utils/crypto';\nimport type {\n CodeChallenge as CodeChallengeType,\n CodeVerifier as CodeVerifierType,\n PKCEState as PKCEStateType,\n} from '@/universal/types/oauth';\nimport {\n type ClientId,\n CodeChallenge,\n CodeVerifier,\n PKCEState,\n type RedirectUri,\n} from '@/universal/types/oauth';\n\nexport type PKCEParams = {\n clientId: ClientId;\n responseType: 'code';\n redirectUri: RedirectUri;\n codeChallenge: CodeChallengeType;\n codeChallengeMethod: 'S256';\n state: PKCEStateType;\n codeVerifier: CodeVerifierType;\n};\n\nexport type PKCEConfig = {\n clientId: ClientId;\n redirectUri: RedirectUri;\n};\n\n/**\n * Generates PKCE parameters for an OAuth2 authorization code flow.\n * Pure crypto — no React, no DOM beyond Web Crypto API. Safe to use\n * in server-side code and Next.js middleware.\n */\nexport async function generatePKCEParams(\n config: PKCEConfig\n): Promise<PKCEParams> {\n const state = generateSecureRandomBase64Url(32);\n const codeVerifier = generateSecureRandomBase64Url(32);\n const codeChallengeRaw = await sha256(codeVerifier);\n const codeChallenge = arrayBufferToBase64Url(codeChallengeRaw, false);\n\n return {\n clientId: config.clientId,\n responseType: 'code',\n redirectUri: config.redirectUri,\n codeChallenge: CodeChallenge(codeChallenge),\n codeChallengeMethod: 'S256',\n state: PKCEState(state),\n codeVerifier: CodeVerifier(codeVerifier),\n };\n}\n","import type { Hash } from 'viem';\n\n/**\n * A classified wallet or transaction failure. The SDK derives this from\n * whatever the {@link EvmWallet} throws, so hosts get a stable, typed error\n * shape regardless of the wallet library underneath.\n *\n * Lives here rather than beside its classifier because it is the failure half\n * of the {@link EvmWallet} contract, and because both `@/universal` and\n * `@/client` name it: {@link LogCause} carries one, and classifying a thrown\n * error into one needs viem's error classes, which are browser-side.\n */\nexport type WalletError =\n | { type: 'user_rejected' }\n | { type: 'insufficient_funds' }\n | {\n type: 'contract_reverted';\n /**\n * What the contract said, when it said anything: a `require` string, a\n * panic description, a custom error's name, or the four-byte selector of\n * an error the ABI could not decode.\n *\n * `null` when a revert carried no data, since the string the RPC node\n * offers in its place is not the contract's - see `classifyWalletError`.\n * Nullable rather than optional so that every arm has to answer the\n * question: \"it reverted and said nothing\" is a fact about the revert,\n * and a caller should have to read it rather than miss it.\n *\n * Never the custom error's arguments. A name is a compile-time\n * identifier; its operands are runtime values - an address, a balance -\n * and those are `'debug'` material.\n */\n reason: string | null;\n }\n | { type: 'timeout'; hash: Hash }\n | { type: 'unknown'; cause: unknown };\n\n/**\n * A {@link WalletError} as it may be reported above `'debug'`: the\n * classification, never the throw.\n *\n * Only the `unknown` arm differs, and it differs because it is the one arm\n * carrying a value the SDK did not author - the raw error the wallet library\n * threw, whose message and metadata hold the transaction's `from`, `to`,\n * `value` and calldata. The other four carry compile-time constants or a\n * server-minted identifier already, so they pass through as they stand.\n *\n * This exists as a type rather than as a scrub some function remembers to\n * apply: `LogCause` names it, so an arm that grew a raw field would fail the\n * build instead of quietly reaching {@link Logger.error}.\n */\nexport type RedactedWalletError =\n | Exclude<WalletError, { type: 'unknown' }>\n | { type: 'unknown' };\n\n/** @internal */\nexport const RedactedWalletError = {\n fromWalletError: (error: WalletError): RedactedWalletError =>\n error.type === 'unknown' ? { type: 'unknown' } : error,\n};\n","import { contractOn } from '@/universal/core/shared/blockchain/chain';\nimport type {\n EthereumChain,\n EvmContractAddress,\n} from '@/universal/types/blockchain/core';\nimport type { OfferSwapContract } from '@/universal/types/offer-detail';\n\n/**\n * The CoinList contract a swap on `chain` settles through, and therefore the\n * ERC-20 spender the user approves - or `null` where this offer cannot be\n * swapped on that chain.\n *\n * Read off the offer rather than held as a constant because the address varies\n * by environment, not only by chain: beta and production both run\n * `ethereum_sepolia` and deploy a different contract on each, and one constant\n * cannot name both. Frontline resolves it per environment and serves the\n * answer on the offer.\n *\n * The array varies per *offer* as well as per chain - frontline drops a chain\n * whose funding and swap tokens do not both resolve for this asset - so an\n * array read for one symbol must not be reused for another. An empty array\n * means \"cannot swap here\", which is an answer rather than an error.\n *\n * A capability rather than a provider slice, and named for the data it reads\n * rather than for its first caller: `swap_contracts` is an offer field, and\n * `universal-core-isolation-and-sharing` would stop Superstate reusing this if\n * it lived under `checkout/ondo/`. Superstate has not migrated yet - it still\n * reads `superstateSwapContractAddress` - so Ondo is the only caller today.\n */\nexport function swapSpender(\n swapContracts: OfferSwapContract[],\n chain: EthereumChain\n): EvmContractAddress | null {\n return contractOn(swapContracts, chain);\n}\n","import {\n assertUint256,\n Bps,\n type Uint256,\n} from '@/universal/types/blockchain/core';\n\n/** Basis-point denominator: 10_000 bps = 100%. */\nexport const BPS_DENOM: Bps = Bps(10_000n);\n\n/**\n * Applies a basis-point fraction to an amount, flooring the result.\n * `floor((amount × bps) / BPS_DENOM)`. The result is bounds-checked, so an\n * overflow (bps far above BPS_DENOM) or a negative product is rejected.\n */\nexport function applyBps(amount: Uint256, bps: Bps): Uint256 {\n return assertUint256((amount * bps) / BPS_DENOM);\n}\n","import type { SwapQuote } from '@/universal/core/providers/checkout/superstate/blockchain/quote';\nimport { applyBps, BPS_DENOM } from '@/universal/core/shared/blockchain/bps';\nimport { pricePerShare } from '@/universal/core/shared/blockchain/math';\nimport {\n assertUint256,\n BlockchainAmount,\n Bps,\n} from '@/universal/types/blockchain/core';\n\n/**\n * Price of 1 output token in USD, assuming the input token is a $1 stablecoin:\n * the quote's input divided by its output, via {@link pricePerShare}.\n * Returned decimals match the input token decimals (always the stablecoin's 6).\n *\n * `null` for a quote that fills nothing, which is an answer here rather than\n * a corrupt amount: there is no price to show for it.\n *\n * @throws MathError when the price is out of uint256 bounds.\n */\nexport function computePrice({\n inputTokenAmount,\n outputTokenAmount,\n}: SwapQuote): BlockchainAmount | null {\n if (outputTokenAmount.raw === 0n) return null;\n return pricePerShare({ usd: inputTokenAmount, shares: outputTokenAmount });\n}\n\n/**\n * Applies slippage to an amount, returning the minimum acceptable amount:\n * `amount × (BPS_DENOM − slippage) / BPS_DENOM`. Throws when `slippage` exceeds\n * `BPS_DENOM` (the retained fraction would be negative).\n */\nexport function computeSlip(\n amount: BlockchainAmount,\n slippage: Bps\n): BlockchainAmount {\n const retained = Bps(assertUint256(BPS_DENOM - slippage));\n const slipRaw = applyBps(amount.raw, retained);\n return BlockchainAmount({ raw: slipRaw, decimals: amount.decimals });\n}\n","import type { SwapStatus } from '@/universal/types/providers/superstate/swap';\n\n/**\n * The bit `Operable.paused` sets for the swap operation, mirroring the\n * contract's `SWAP_LEVEL` constant.\n *\n * A constant rather than a `SWAP_LEVEL()` read: it is `constant` in the\n * contract, so reading it would spend a round-trip to be told the same number\n * every time.\n */\nexport const SWAP_LEVEL = 2;\n\n/**\n * Whether the contract will actually accept a swap right now.\n *\n * Not the same question as \"is it active\". `paused` is a bitmask over\n * *operations*, so a contract can suspend something unrelated and go on\n * swapping; only the {@link SWAP_LEVEL} bit stops it. Reading `state ===\n * 'active'` instead would refuse swaps the contract is perfectly willing to\n * make.\n */\nexport function isSwapAvailable(status: SwapStatus): boolean {\n switch (status.state) {\n case 'active':\n return true;\n case 'stopped':\n return false;\n case 'paused':\n return (status.pausedLevels & SWAP_LEVEL) === 0;\n default: {\n const _exhaustive: never = status;\n return _exhaustive;\n }\n }\n}\n","import * as offersApi from '@/universal/api/frontline/offers';\nimport type { UniversalNamespaceContext } from '@/universal/core/shared/namespace-context';\nimport {\n type InternalLogger,\n internalLogger,\n} from '@/universal/core/shared/observability/internal-logger';\nimport type { Offer, OfferId } from '@/universal/types/offer';\nimport type { OfferDetail } from '@/universal/types/offer-detail';\nimport type {\n PaginatedResponse,\n PaginationParams,\n} from '@/universal/types/pagination';\n\n/**\n * Reads over CoinList's offers: the catalogue a user can browse, and the full\n * detail of a single offer.\n *\n * Every method requires an authenticated user and throws\n * {@link NotAuthenticatedError} otherwise. On the server, the same reads are\n * additionally available with an app-level token — see\n * `ServerOffersNamespace`.\n */\nexport interface OffersNamespace {\n /**\n * Fetches every offer, iterating through all pages. Prefer {@link listPage}\n * when you render a paginated list yourself.\n */\n list(): Promise<Offer[]>;\n\n /**\n * Fetches a single page of offers. Pass the previous response's\n * `startingAfter` as `after` to advance.\n */\n listPage(params: PaginationParams): Promise<PaginatedResponse<Offer>>;\n\n /**\n * Fetches the full detail of one offer, including its options. Note this\n * returns {@link OfferDetail} — a richer model than the {@link Offer}\n * summaries {@link list} returns.\n */\n get(id: OfferId): Promise<OfferDetail>;\n}\n\n/** @internal */\nexport class OffersNamespaceImpl implements OffersNamespace {\n private readonly log: InternalLogger;\n\n constructor(private readonly ctx: UniversalNamespaceContext) {\n this.log = internalLogger(ctx.logger, 'OFFERS');\n }\n\n async list(): Promise<Offer[]> {\n return this.log.wrap('list', undefined, async () => {\n await this.ctx.ensureUserAuthenticated();\n return offersApi.fetchOffers(this.ctx.api, undefined);\n });\n }\n\n async listPage(params: PaginationParams): Promise<PaginatedResponse<Offer>> {\n return this.log.wrap('listPage', params, async () => {\n await this.ctx.ensureUserAuthenticated();\n return offersApi.fetchOffersPage(this.ctx.api, params, undefined);\n });\n }\n\n async get(id: OfferId): Promise<OfferDetail> {\n return this.log.wrap('get', id, async () => {\n await this.ctx.ensureUserAuthenticated();\n return offersApi.fetchOfferDetails(this.ctx.api, id, undefined);\n });\n }\n}\n","import type {\n Chain,\n EvmContractAddress,\n} from '@/universal/types/blockchain/core';\nimport type { OfferToken } from '@/universal/types/offer';\nimport type { TokenMetadata } from '@/universal/types/token-metadata';\n\n/**\n * One `coinlist.tokens.list()` answer, indexed for the lookups a catalogue\n * makes: by the `(chain, address)` pairs `Offer.tokens` carries.\n *\n * The registry is fetched whole - a few hundred tokens across every chain in\n * one request - and then asked one question per offer. Building the index\n * once is what keeps that a map lookup per card rather than a scan of the\n * snapshot per card. The same rule frontline-web and every other host wrote\n * for themselves, kept here so that none of them has to.\n */\nexport type TokenRegistrySnapshot = {\n /** Every token the snapshot lists, in registry order. */\n readonly tokens: readonly TokenMetadata[];\n /** `chain:address` (address lowercased) to its metadata. */\n readonly byKey: ReadonlyMap<string, TokenMetadata>;\n};\n\n/**\n * A token as a lookup names it. `Chain` rather than `EthereumChain` because\n * `OfferToken.chain` is the wider type; a Solana entry simply never matches,\n * since the snapshot models EVM chains only.\n */\nexport type TokenKey = { chain: Chain; address: EvmContractAddress };\n\nexport const TokenRegistrySnapshot = {\n /** Indexes a `tokens.list()` result. `[]` is a valid, empty snapshot. */\n fromTokens: (tokens: readonly TokenMetadata[]): TokenRegistrySnapshot => ({\n tokens,\n byKey: new Map(\n tokens.map((token) => [registryKey(token.identifier), token])\n ),\n }),\n\n /**\n * The registry's entry for one token, or `null` when it lists none. The\n * registry is curated, so `null` is an ordinary answer rather than an\n * error, and callers fall back to their own display defaults.\n */\n get: (\n snapshot: TokenRegistrySnapshot,\n token: TokenKey\n ): TokenMetadata | null => snapshot.byKey.get(registryKey(token)) ?? null,\n\n /**\n * The registry's entry for the token an offer is *about*, or `null` when\n * it lists none of them.\n *\n * Resolution follows {@link offerDisplayTokens}: the token a sale\n * distributes or a swap hands over, never the funding token the user pays\n * with. An offer deployed on several chains carries one such token per\n * chain, and the first the registry knows wins - they are the same asset,\n * so any listed one answers for the offer.\n */\n forOffer: (\n snapshot: TokenRegistrySnapshot,\n offer: { tokens: readonly OfferToken[] }\n ): TokenMetadata | null => {\n for (const token of offerDisplayTokens(offer)) {\n const metadata = TokenRegistrySnapshot.get(snapshot, token);\n if (metadata !== null) {\n return metadata;\n }\n }\n return null;\n },\n};\n\n/**\n * The tokens an offer is *about*, most specific first: every `swap` or\n * `vault` entry, then every `distribution` entry. `funding` entries name what\n * an offer is paid with (USDC, USDT) and never the asset on offer, so they are\n * left out.\n *\n * `swap` and `vault` rank together - no offer type carries both - and outrank\n * `distribution` because a swap or vault product names the token it hands over\n * precisely, while a sale's distribution entry names the same token for a sale\n * product and is accepted as the fallback. The checkout's\n * per-chain lookup and the catalogue's any-chain lookup both read this\n * ordering, which is why it is stated once, here.\n */\nexport function offerDisplayTokens(offer: {\n tokens: readonly OfferToken[];\n}): OfferToken[] {\n const swaps = offer.tokens.filter(\n (token) => token.role === 'swap' || token.role === 'vault'\n );\n const distributions = offer.tokens.filter(\n (token) => token.role === 'distribution'\n );\n return [...swaps, ...distributions];\n}\n\n/**\n * The registry serves EIP-55 checksummed addresses while an offer may carry\n * any casing, so an EVM address compares case-insensitively. Every chain the\n * registry snapshot models is an EVM chain (`TokenMetadata.identifier.chain`\n * is an `EthereumChain`), so lowercasing is safe for every entry it holds.\n */\nfunction registryKey(token: TokenKey): string {\n return `${token.chain}:${token.address.toLowerCase()}`;\n}\n","import {\n AssetDecimals,\n type Erc20Asset,\n type EthereumChain,\n EvmContractAddress,\n type KnownAssetSymbol,\n StablecoinSymbol,\n} from '@/universal/types/blockchain/core';\nimport { InvariantError } from '@/universal/types/errors';\n\nexport const USDC_SYMBOL: StablecoinSymbol = StablecoinSymbol('USDC');\nexport const USDC: Erc20Asset = {\n name: 'USD Coin',\n symbol: USDC_SYMBOL,\n decimals: AssetDecimals(6),\n};\n\nexport const USDT_SYMBOL: StablecoinSymbol = StablecoinSymbol('USDT');\nexport const USDT: Erc20Asset = {\n name: 'Tether USD',\n symbol: USDT_SYMBOL,\n decimals: AssetDecimals(6),\n};\n\n/** ERC-20 contract addresses for a supported stablecoin, keyed by chain. */\ntype TokenAddresses = Record<EthereumChain, EvmContractAddress>;\n\nconst USDC_ADDRESSES: TokenAddresses = {\n ethereum_mainnet: EvmContractAddress(\n '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48'\n ),\n ethereum_sepolia: EvmContractAddress(\n '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238'\n ),\n base_mainnet: EvmContractAddress(\n '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913'\n ),\n base_sepolia: EvmContractAddress(\n '0x036CbD53842c5426634e7929541eC2318f3dCF7e'\n ),\n};\n\n/**\n * USDT is not deployed on every chain the SDK models: Tether publishes no\n * Base Sepolia token. The table stays total, with that one absence an\n * explicit `null`, so a new {@link EthereumChain} is still a compile error\n * here until the author decides whether USDT exists on it — the same\n * exhaustiveness the rest of the chain model relies on. A lookup then\n * answers the honest `null` rather than calling a fake address.\n */\nconst USDT_ADDRESSES: Record<EthereumChain, EvmContractAddress | null> = {\n ethereum_mainnet: EvmContractAddress(\n '0xdac17f958d2ee523a2206206994597c13d831ec7'\n ),\n ethereum_sepolia: EvmContractAddress(\n '0x7169D38820dfd117C3FA1f22a697dBA58d90BA06'\n ),\n base_mainnet: EvmContractAddress(\n '0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2'\n ),\n base_sepolia: null,\n};\n\n/** Lookups for the stablecoins the SDK's swap flows support out of the box. */\nexport const TOKEN_REGISTRY = {\n erc20: (symbol: KnownAssetSymbol): Erc20Asset => {\n switch (symbol) {\n case 'USDC':\n return USDC;\n case 'USDT':\n return USDT;\n default:\n throw new InvariantError(`Unknown asset symbol: ${symbol}`);\n }\n },\n /**\n * USDC's contract on `chain`. USDC is deployed on every chain the SDK\n * models, so the table is total and the answer is never `null`.\n */\n usdcAddress: (chain: EthereumChain): EvmContractAddress =>\n USDC_ADDRESSES[chain],\n /**\n * USDT's contract on `chain`, or `null` where Tether publishes none —\n * Base Sepolia today. The honest answer, never a fake address a balance\n * read would call.\n */\n usdtAddress: (chain: EthereumChain): EvmContractAddress | null =>\n USDT_ADDRESSES[chain],\n};\n","import { apiErrorCode, type HttpError } from '@/universal/api/http';\n\n/**\n * The CoinList API's error code for an Ondo quote refused because the asset\n * cannot be traded right now: the market is closed or paused, or the asset is\n * paused or closed for the session. It arrives on a 409.\n *\n * One code for all four of Ondo's reasons, because the remedy is the same:\n * wait for the market to open. Ondo pauses for a moment at every US session\n * change (04:00 and 16:00 ET), so a poll can land on one even while\n * `getTradingStatus` reported the asset tradable a second earlier.\n *\n * @internal\n */\nexport const ONDO_NOT_TRADABLE_CODE = 'not_tradable';\n\n/**\n * Whether `error` is the CoinList API refusing an Ondo quote because the\n * market is not open, as opposed to a request that failed.\n *\n * Total: anything that is not an `HttpError` carrying\n * {@link ONDO_NOT_TRADABLE_CODE} is `false`.\n */\nexport function isOndoNotTradableError(error: unknown): error is HttpError {\n return apiErrorCode(error) === ONDO_NOT_TRADABLE_CODE;\n}\n","import { USDC_SYMBOL } from '@/universal/core/shared/blockchain/token-registry';\nimport {\n DecimalString,\n type StablecoinSymbol,\n} from '@/universal/types/blockchain/core';\nimport type { NonEmptyArray } from '@/universal/types/collections';\n\n/**\n * How often the Ondo checkout refreshes what it is allowed to poll: the market\n * status and the indicative price. Both are free - neither spends an\n * attestation - so this is paced for a price the user can trust rather than\n * for cost.\n *\n * A built transaction is deliberately not on this timer. Building spends an\n * attestation, so it happens once per order and once per refresh the user\n * asks for.\n */\nexport const ONDO_POLL_INTERVAL_MS = 15_000;\n\n/** Max time the review step offers a built quote. */\nexport const ONDO_QUOTE_MAX_TTL_MS = 15_000;\n\n/**\n * The order size the sidebar prices against before the user names one.\n *\n * Ondo prices by size, so some amount has to be sent. $1,000 is a plausible\n * order rather than a token one: a size so small that Ondo's minimum rejects\n * it would leave the panel permanently blank.\n *\n * Named distinctly from `DEFAULT_AMOUNT_TO_COMPUTE_PRICE` in the swap\n * constants, which is a raw `bigint` of USDC base units for a different\n * endpoint. Both barrels are flat, so two constants of the same name could not\n * coexist - and they mean different things anyway.\n */\nexport const DEFAULT_ONDO_AMOUNT_TO_COMPUTE_PRICE = DecimalString('1000');\n\n/**\n * The coin an Ondo sell settles into, for display only.\n *\n * The scale of every amount on a built transaction comes off the response, so\n * this names the token and never sizes it - `receive_output_decimals` is the\n * only authority on how many decimals the proceeds are counted in, and the two\n * are allowed to disagree.\n *\n * Named apart from {@link ONDO_SUPPORTED_INPUT_ASSETS} rather than read out of\n * it, though both are USDC today. On a buy USDC is what the user funds with\n * and one of a list that may grow; on a sell it is what they settle into and\n * there is one of it. Reading `ONDO_SUPPORTED_INPUT_ASSETS[0]` here would make\n * the sell screen quietly follow whichever funding coin happened to be listed\n * first.\n */\nexport const ONDO_SETTLEMENT_ASSET: StablecoinSymbol = USDC_SYMBOL;\n\n/**\n * The order size the sidebar prices a sell against before the user names one.\n *\n * Sells are quoted by token amount rather than by notional: the fee comes out\n * of dollars, and Ondo's price is size-aware, so a buy's quantity depends on\n * the quote being asked for while a sell is sized by what the user already\n * holds. One whole share is a size Ondo will price - small enough to be\n * plausible for any asset, large enough that Ondo's minimum does not reject it\n * and leave the panel permanently blank.\n *\n * The buy counterpart is {@link DEFAULT_ONDO_AMOUNT_TO_COMPUTE_PRICE}, which\n * is a dollar figure for the same reason in reverse.\n */\nexport const DEFAULT_ONDO_SELL_TOKENS_TO_COMPUTE_PRICE = 1;\n\n/**\n * The coins an Ondo buy can be funded with, in display order, with the first\n * preselected.\n *\n * USDC alone today: it is what the Sepolia integration contract accepts. The\n * amount step renders a single entry as a plain card and two or more as a\n * picker, so adding one here is all it takes.\n */\nexport const ONDO_SUPPORTED_INPUT_ASSETS: NonEmptyArray<StablecoinSymbol> = [\n USDC_SYMBOL,\n];\n","import { ONDO_QUOTE_MAX_TTL_MS } from '@/universal/core/providers/checkout/ondo/constants';\nimport { pricePerShare } from '@/universal/core/shared/blockchain/math';\nimport {\n BlockchainAmount,\n MAX_UINT_256,\n} from '@/universal/types/blockchain/core';\nimport { MathError } from '@/universal/types/errors';\nimport type {\n OndoBuyTransaction,\n OndoSellOutcome,\n OndoSellTransaction,\n} from '@/universal/types/providers/ondo/ondo';\n\n/**\n * The price of one whole asset token in a built Ondo purchase, in the funding\n * token's units - USD per share.\n *\n * Neither builder publishes a price. Frontline drops Ninshubur's deliberately,\n * because `GET /v1/ondo/swap/quote` already serves one under that name at a\n * different scale, and echoing both would leave a caller to guess which was\n * which.\n *\n * Dividing the two amounts the response *does* carry is better than reading\n * the indicative one anyway: it is the price this transaction fills at, rather\n * than a poll that has since moved and was struck against a different size.\n *\n * **Fee-exclusive.** `notionalValue` is the deposit after CoinList's fee comes\n * off, so this is the price Ondo filled at, not the buyer's all-in cost per\n * token - that would be `spendInputAmount / receiveOutputAmount`, and it is\n * higher. Fee-exclusive is what the review screen wants, because it renders\n * the fee on its own line: price x quantity, plus fee, comes to the total.\n * Making this all-in would double-count the fee against that breakdown.\n *\n * The two are equal until ENG-1718 turns a fee on, which frontline rejects\n * today. They diverge the moment it does, so the choice is load-bearing rather\n * than academic.\n */\nexport function computeOndoBuyPrice(\n transaction: OndoBuyTransaction\n): BlockchainAmount {\n const { notionalValue, receiveOutputAmount } = transaction;\n return pricePerShare({\n usd: notionalValue,\n shares: receiveOutputAmount,\n });\n}\n\n/**\n * The price of one whole asset token in a built Ondo sale, in the settlement\n * token's units - USD per share, the same thing\n * {@link computeOndoBuyPrice} answers with the ratio inverted.\n *\n * **Fee-exclusive, and it takes arithmetic to be so.** `expected.quantity` is\n * published already net of `expected.fee`, so the proceeds are added back\n * before dividing: what comes out is the price Ondo filled at, which is the\n * buy arm's meaning rather than a second one. That is what lets one review row\n * render on either screen, and what keeps the sell breakdown honest - the fee\n * sits on its own line beside this, and a net price would count it twice.\n *\n * Read against {@link OndoSellTransaction.expected} alone. The `minimum` arm\n * describes the same trade at a different outcome, and pricing that one would\n * answer \"the worst price this could fill at\", which no screen asks for.\n *\n * The two readings coincide while frontline forces the fee to zero, which it\n * does today. They diverge the day ENG-1718 lands.\n */\nexport function computeOndoSellPrice(\n transaction: OndoSellTransaction\n): BlockchainAmount {\n const { expected, spendInputAmount } = transaction;\n return pricePerShare({\n usd: grossProceeds(expected),\n shares: spendInputAmount,\n });\n}\n\n/**\n * The sooner of Ondo's deadline and now + {@link ONDO_QUOTE_MAX_TTL_MS}.\n *\n * @internal\n */\nexport function ondoQuoteOfferDeadline(\n expiresAt: Date,\n nowMs: number = Date.now()\n): Date {\n return new Date(Math.min(expiresAt.getTime(), nowMs + ONDO_QUOTE_MAX_TTL_MS));\n}\n\n/**\n * What Ondo returned before CoinList took its cut: the published quantity with\n * the fee charged on it added back.\n *\n * Bounded before the addition rather than after. The two amounts are parsed\n * independently, each a uint256 in its own right, so nothing in the mapper\n * stops their sum leaving the range - and `BlockchainAmount.add` answers an\n * out-of-range sum with an `InvariantError`, which says the SDK's own\n * arithmetic went wrong. It did not: a gross that no uint256 can hold is a\n * corrupt response, the same kind of thing {@link pricePerShare} reports for a price, and\n * it has to say so here rather than take the checkout down mid-render.\n *\n * The addition itself is still `BlockchainAmount.add`, so the two amounts\n * disagreeing about their scale stays an `InvariantError`. That one really is\n * internal: `OndoSellTransaction.fromDto` reads both off\n * `receive_output_decimals`.\n */\nfunction grossProceeds(expected: OndoSellOutcome): BlockchainAmount {\n const raw = expected.quantity.raw + expected.fee.raw;\n if (raw > MAX_UINT_256) {\n throw new MathError(`Ondo sell proceeds: out of uint256 bounds (${raw})`);\n }\n return BlockchainAmount.add(expected.quantity, expected.fee);\n}\n","import { USDC_SYMBOL } from '@/universal/core/shared/blockchain/token-registry';\nimport {\n Bps,\n type EthereumChain,\n EvmContractAddress,\n type StablecoinSymbol,\n} from '@/universal/types/blockchain/core';\nimport type { NonEmptyArray } from '@/universal/types/collections';\n\n/**\n * Who issues the asset a Superstate swap pays out.\n *\n * A constant rather than a field off the offer: no frontline endpoint carries\n * an issuer, and every offer this checkout serves is Superstate's by\n * definition — `CheckoutContainer` routes here on `superstate::swap` alone.\n *\n * @internal\n */\nexport const SUPERSTATE_ISSUER_NAME = 'Superstate';\n\n/**\n * The coins a Superstate swap can be funded with, in display order, with the\n * first preselected.\n *\n * USDC alone today: it is what the deployed swap contract accepts. The amount\n * step renders a single entry as a plain card and two or more as a picker, so\n * adding one here is all it takes.\n *\n * @internal\n */\nexport const SUPERSTATE_SUPPORTED_INPUT_ASSETS: NonEmptyArray<StablecoinSymbol> =\n [USDC_SYMBOL];\n\n/**\n * Poll interval for refreshing on-chain swap quotes and balances.\n *\n * @internal\n */\nexport const SWAP_POLL_INTERVAL_MS = 15_000;\n\n/**\n * Notional input used to derive a display price-per-share when the user has\n * not yet entered an amount (1 USDC at 6 decimals).\n *\n * @internal\n */\nexport const DEFAULT_AMOUNT_TO_COMPUTE_PRICE = 1_000_000n;\n\n/** Slippage tolerances offered in the review step, in basis points. */\nexport const SLIPPAGE_OPTIONS_BPS: Bps[] = [25n, 50n, 100n, 200n, 500n].map(\n (n) => Bps(n)\n);\n\n/** Default slippage tolerance (0.5%). */\nexport const DEFAULT_SLIPPAGE_BPS: Bps = Bps(50n);\n\n/**\n * The deployed Superstate swap contract on Ethereum Sepolia, and therefore the\n * ERC-20 spender the user approves there.\n *\n * Exported in its own right for a partner driving `coinlist.superstate.execute`\n * at Level 1, where the contract is an explicit parameter.\n *\n * @internal\n */\nexport const SUPERSTATE_SWAP_CONTRACT_ADDRESS_SEPOLIA: EvmContractAddress =\n EvmContractAddress('0x27E8CE9Ca1A1E98Bc4009F08Dc596bFcf88aCED1');\n\n/**\n * The Superstate swap contract per chain.\n *\n * Mainnet is absent, not zeroed: the production address is not finalized\n * upstream, and a zero address would be approved happily and revert only later.\n * A chain with no entry has no checkout — `useSuperstateSwapCheckoutViewModel`\n * reports it as the flow-level error rather than quoting against nothing.\n */\nconst SUPERSTATE_SWAP_CONTRACT_ADDRESSES: Partial<\n Record<EthereumChain, EvmContractAddress>\n> = {\n ethereum_sepolia: SUPERSTATE_SWAP_CONTRACT_ADDRESS_SEPOLIA,\n};\n\n/**\n * The Superstate swap contract on `chain`, or `null` where none is deployed.\n *\n * TODO(ENG-1734): Ondo now reads its spender off the offer's `swap_contracts`\n * via `swapSpender`, which is why that helper sits in `shared/core/offers/`\n * rather than under a provider. Superstate still resolves from this table, so\n * two mechanisms answer one question. Migrate once frontline serves\n * `swap_contracts` on Superstate offers too.\n */\nexport function superstateSwapContractAddress(\n chain: EthereumChain\n): EvmContractAddress | null {\n return SUPERSTATE_SWAP_CONTRACT_ADDRESSES[chain] ?? null;\n}\n","import { computePrice } from '@/universal/core/providers/checkout/superstate/blockchain/math';\nimport type { SwapQuote } from '@/universal/core/providers/checkout/superstate/blockchain/quote';\nimport {\n formattedUsdPrice,\n NA_AMOUNT_ASSET_UI,\n} from '@/universal/core/shared/blockchain/formatters';\nimport type { FormattedAmountAssetUi } from '@/universal/types/blockchain/ui';\n\n/**\n * Formats a quote's implied price per output token as a USD amount.\n *\n * Lives with the provider rather than in `@/universal/core/shared/blockchain/formatters`\n * because {@link SwapQuote} and {@link computePrice} are Superstate's: the\n * shared formatters stay provider-agnostic.\n */\nexport function formattedPricePerShare(\n quote: SwapQuote | null,\n locale: string\n): FormattedAmountAssetUi {\n if (!quote) return NA_AMOUNT_ASSET_UI;\n return formattedUsdPrice(computePrice(quote), locale);\n}\n","import type { EvmWalletAddress } from '@/universal/types/blockchain/core';\nimport type {\n EvmWallet,\n ExternalWalletAdapter,\n} from '@/universal/types/blockchain/evm-wallet';\n\n/**\n * The wallets a screen reads for and acts from, supplied by the host.\n *\n * The SDK ships no wallet stack, so wallet discovery and connection are\n * inverted onto the host: it hands over ready {@link EvmWallet}s, and an\n * adapter for connecting an external one when it supports that. Every wallet\n * here is one that can sign for itself, so a screen can broadcast from the\n * wallet that holds a position.\n */\nexport type WalletSelection = {\n /**\n * The user's embedded (custodial) wallets, in display order. Empty when\n * they have none, which is a normal state, not an error.\n */\n embedded: EvmWallet[];\n /** The connected external wallet, or `null` while none is connected. */\n external: EvmWallet | null;\n /**\n * The host's external-wallet connector, or `null` when it offers none - in\n * which case the screen shows no connect affordance at all. A host may\n * still pass a connected `external` without one, to show a wallet the user\n * cannot change from here.\n */\n externalAdapter: ExternalWalletAdapter | null;\n};\n\n/** Operations over a {@link WalletSelection}. */\nexport const WalletSelection = {\n /**\n * Every wallet in display order - embedded first, then the external one -\n * each address once. Addresses compare case-insensitively, so a host that\n * hands the same wallet over as both embedded and external sees it once.\n */\n all: (selection: WalletSelection): EvmWallet[] => {\n const seen = new Set<string>();\n return [\n ...selection.embedded,\n ...(selection.external === null ? [] : [selection.external]),\n ].filter((wallet) => {\n const key = wallet.address.toLowerCase();\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n },\n};\n\n/**\n * Names a wallet for display, e.g. `'CoinList Wallet'` for the user's\n * embedded one. `null` means it has no name, and the screen shows its\n * shortened address instead.\n *\n * @alpha\n */\nexport type WalletLabelResolver = (address: EvmWalletAddress) => string | null;\n","import {\n ETHEREUM_CHAINS,\n type EthereumChain,\n type EvmContractAddress,\n} from '@/universal/types/blockchain/core';\nimport type { OfferToken } from '@/universal/types/offer';\nimport type { CentrifugeVaultOfferDetail } from '@/universal/types/offer-detail';\nimport type { TokenMetadata } from '@/universal/types/token-metadata';\n\n/**\n * One chain a vault offer runs on, with everything a screen needs to read and\n * show a position there: the proxy every request and claim goes through, the\n * share token it issues, and the funding token it is paid in.\n *\n * The share token's `symbol` is the one amounts are labelled with. Vault\n * routes are keyed by the offer's asset code, from `centrifugeShareSymbol`.\n *\n * @alpha\n */\nexport type CentrifugeVault = {\n chain: EthereumChain;\n proxy: EvmContractAddress;\n share: TokenMetadata;\n funding: TokenMetadata;\n};\n\n/**\n * The vaults an offer runs on, or why a chain could not be resolved: one\n * entry per `vaultContracts` chain, in the offer's order.\n *\n * @alpha\n */\nexport type CentrifugeVaultResolution =\n | { type: 'resolved'; vault: CentrifugeVault }\n | {\n type: 'unresolved';\n chain: OfferToken['chain'];\n /** Which token the offer or the registry could not name. */\n missing: 'share-token' | 'funding-token' | 'evm-chain';\n };\n\n/**\n * Resolves each chain of a vault offer to its share and funding tokens.\n *\n * The offer names tokens by role and address only - the share token as\n * `vault`, the coin it is paid in as `funding` - so `lookup` turns each into\n * metadata. A function rather than a registry snapshot, so this module does\n * not depend on where the metadata comes from.\n *\n * A chain whose tokens cannot be named is reported rather than dropped: its\n * position cannot be read without the symbol, and a caller has to know it is\n * not showing it. When a chain lists several funding tokens, the first one\n * `lookup` knows wins - a vault is priced in one.\n *\n * @alpha\n */\nexport function resolveCentrifugeVaults(\n offer: CentrifugeVaultOfferDetail,\n lookup: (token: OfferToken) => TokenMetadata | null\n): CentrifugeVaultResolution[] {\n return offer.vaultContracts.map((contract) => {\n const { chain } = contract;\n if (!isEthereumChain(chain)) {\n return { type: 'unresolved', chain, missing: 'evm-chain' };\n }\n const onChain = (role: OfferToken['role']) =>\n offer.tokens.filter(\n (token) => token.role === role && token.chain === chain\n );\n const share = firstKnown(onChain('vault'), lookup);\n if (share === null) {\n return { type: 'unresolved', chain, missing: 'share-token' };\n }\n const funding = firstKnown(onChain('funding'), lookup);\n if (funding === null) {\n return { type: 'unresolved', chain, missing: 'funding-token' };\n }\n return {\n type: 'resolved',\n vault: { chain, proxy: contract.address, share, funding },\n };\n });\n}\n\nfunction firstKnown(\n tokens: OfferToken[],\n lookup: (token: OfferToken) => TokenMetadata | null\n): TokenMetadata | null {\n for (const token of tokens) {\n const metadata = lookup(token);\n if (metadata !== null) return metadata;\n }\n return null;\n}\n\nfunction isEthereumChain(chain: OfferToken['chain']): chain is EthereumChain {\n return chain in ETHEREUM_CHAINS;\n}\n"],"mappings":"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","names":[]}