@coinlist-co/react 0.11.0 → 0.11.1-rc.10770e8
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-UIIXXLA7.js → chunk-7CTH4KPU.js} +734 -198
- package/dist/chunk-7CTH4KPU.js.map +1 -0
- package/dist/{chunk-B2HCVPCQ.js → chunk-LSPZETDH.js} +81 -33
- package/dist/chunk-LSPZETDH.js.map +1 -0
- package/dist/chunk-UZUQALFY.js +279 -0
- package/dist/chunk-UZUQALFY.js.map +1 -0
- package/dist/client/index.cjs +5415 -2413
- package/dist/client/index.cjs.map +1 -1
- package/dist/client/index.d.cts +2439 -1209
- package/dist/client/index.d.ts +2439 -1209
- package/dist/client/index.js +4457 -2178
- package/dist/client/index.js.map +1 -1
- package/dist/collections-BBI_XydI.d.cts +116 -0
- package/dist/collections-BrX9rRWc.d.ts +116 -0
- package/dist/{config-B5mwS_2l.d.cts → config-CMl1bR3F.d.cts} +1183 -150
- package/dist/{config-B5mwS_2l.d.ts → config-CMl1bR3F.d.ts} +1183 -150
- package/dist/server/index.cjs +1005 -265
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.d.cts +81 -4
- package/dist/server/index.d.ts +81 -4
- package/dist/server/index.js +120 -51
- package/dist/server/index.js.map +1 -1
- package/dist/shared/index.cjs +798 -204
- package/dist/shared/index.cjs.map +1 -1
- package/dist/shared/index.d.cts +98 -16
- package/dist/shared/index.d.ts +98 -16
- package/dist/shared/index.js +22 -6
- package/package.json +3 -2
- package/dist/chunk-B2HCVPCQ.js.map +0 -1
- package/dist/chunk-KDGNDAHA.js +0 -146
- package/dist/chunk-KDGNDAHA.js.map +0 -1
- package/dist/chunk-UIIXXLA7.js.map +0 -1
- package/dist/collections-BhDkYmzV.d.cts +0 -65
- package/dist/collections-CZhHoQHr.d.ts +0 -65
|
@@ -25,6 +25,8 @@ var retryAttempt = (attempt) => ({
|
|
|
25
25
|
var renewAttempted = (value) => ({
|
|
26
26
|
renewAttempted: value
|
|
27
27
|
});
|
|
28
|
+
var requestId = (id) => ({ requestId: id });
|
|
29
|
+
var getRequestId = (attrs) => attrs?.requestId ?? null;
|
|
28
30
|
var isProtected = (attrs) => attrs?.protected === true;
|
|
29
31
|
var needUserAgent = (attrs) => attrs?.userAgent === true;
|
|
30
32
|
var isIdempotent = (attrs) => attrs?.idempotencyKey === true;
|
|
@@ -46,7 +48,9 @@ var Attributes = {
|
|
|
46
48
|
renewAttempted,
|
|
47
49
|
wasRenewAttempted,
|
|
48
50
|
clientCredentials,
|
|
49
|
-
getClientCredentials
|
|
51
|
+
getClientCredentials,
|
|
52
|
+
requestId,
|
|
53
|
+
getRequestId
|
|
50
54
|
};
|
|
51
55
|
|
|
52
56
|
// src/shared/api/http.ts
|
|
@@ -56,6 +60,16 @@ var HttpError = class extends Error {
|
|
|
56
60
|
this.name = "HttpError";
|
|
57
61
|
this.response = response;
|
|
58
62
|
}
|
|
63
|
+
/**
|
|
64
|
+
* Correlates this failure with the `[HTTP]` log lines for the same request,
|
|
65
|
+
* which carry the method, the URL, the duration and every retry. `null` when
|
|
66
|
+
* the response did not come from an {@link HttpClient}.
|
|
67
|
+
*
|
|
68
|
+
* Worth quoting in a bug report: it is what makes a log excerpt readable.
|
|
69
|
+
*/
|
|
70
|
+
get requestId() {
|
|
71
|
+
return this.response.requestId ?? null;
|
|
72
|
+
}
|
|
59
73
|
};
|
|
60
74
|
function apiErrorCode(error) {
|
|
61
75
|
if (!(error instanceof HttpError)) return null;
|
|
@@ -163,22 +177,6 @@ var Request = {
|
|
|
163
177
|
concatAttributes
|
|
164
178
|
};
|
|
165
179
|
|
|
166
|
-
// src/shared/api/pagination.ts
|
|
167
|
-
async function fetchAllPages(fetchPage, baseParams) {
|
|
168
|
-
const items = [];
|
|
169
|
-
let cursor = null;
|
|
170
|
-
do {
|
|
171
|
-
const params = {
|
|
172
|
-
...baseParams ?? {},
|
|
173
|
-
after: cursor ?? void 0
|
|
174
|
-
};
|
|
175
|
-
const page = await fetchPage(params);
|
|
176
|
-
items.push(...page.data);
|
|
177
|
-
cursor = page.startingAfter;
|
|
178
|
-
} while (cursor);
|
|
179
|
-
return items;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
180
|
// src/shared/types/errors.ts
|
|
183
181
|
var NotImplementedError = class extends Error {
|
|
184
182
|
constructor(message = "Not implemented yet") {
|
|
@@ -198,11 +196,41 @@ var ValidationError = class extends Error {
|
|
|
198
196
|
this.name = "ValidationError";
|
|
199
197
|
}
|
|
200
198
|
};
|
|
199
|
+
var InvariantError = class extends Error {
|
|
200
|
+
constructor(message) {
|
|
201
|
+
super(message);
|
|
202
|
+
this.name = "InvariantError";
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
var MathError = class extends Error {
|
|
206
|
+
constructor(message) {
|
|
207
|
+
super(message);
|
|
208
|
+
this.name = "MathError";
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
// src/shared/api/pagination.ts
|
|
213
|
+
async function fetchAllPages(fetchPage, baseParams) {
|
|
214
|
+
const items = [];
|
|
215
|
+
let cursor = null;
|
|
216
|
+
do {
|
|
217
|
+
const params = {
|
|
218
|
+
...baseParams ?? {},
|
|
219
|
+
after: cursor ?? void 0
|
|
220
|
+
};
|
|
221
|
+
const page = await fetchPage(params);
|
|
222
|
+
items.push(...page.data);
|
|
223
|
+
cursor = page.startingAfter;
|
|
224
|
+
} while (cursor);
|
|
225
|
+
return items;
|
|
226
|
+
}
|
|
201
227
|
|
|
202
228
|
// src/shared/types/blockchain/core.ts
|
|
203
229
|
var ETHEREUM_CHAINS = {
|
|
204
230
|
ethereum_mainnet: true,
|
|
205
|
-
ethereum_sepolia: true
|
|
231
|
+
ethereum_sepolia: true,
|
|
232
|
+
base_mainnet: true,
|
|
233
|
+
base_sepolia: true
|
|
206
234
|
};
|
|
207
235
|
var EthereumChain = (value) => {
|
|
208
236
|
if (!Object.keys(ETHEREUM_CHAINS).includes(value)) {
|
|
@@ -245,27 +273,46 @@ var STABLE_DECIMALS = AssetDecimals(6);
|
|
|
245
273
|
var DecimalString = (value) => value;
|
|
246
274
|
var MAX_UINT_256 = 2n ** 256n - 1n;
|
|
247
275
|
var assertUint256 = (value) => {
|
|
248
|
-
if (value
|
|
249
|
-
|
|
250
|
-
}
|
|
251
|
-
return value;
|
|
276
|
+
if (isUint256(value)) return value;
|
|
277
|
+
throw new InvariantError(`Value out of uint256 bounds: ${value}`);
|
|
252
278
|
};
|
|
279
|
+
var parseUint256 = (value, label) => {
|
|
280
|
+
if (isUint256(value)) return value;
|
|
281
|
+
throw new ValidationError(`${label}: out of uint256 bounds (${value})`);
|
|
282
|
+
};
|
|
283
|
+
var isUint256 = (value) => value >= 0n && value <= MAX_UINT_256;
|
|
253
284
|
var BlockchainAmount = Object.assign(
|
|
254
285
|
(value) => value,
|
|
255
286
|
{
|
|
256
287
|
add: (a, b) => combineAmounts(a, b, (x, y) => x + y),
|
|
257
|
-
sub: (a, b) => combineAmounts(a, b, (x, y) => x - y)
|
|
288
|
+
sub: (a, b) => combineAmounts(a, b, (x, y) => x - y),
|
|
289
|
+
mul: multiplyAmounts,
|
|
290
|
+
div: divideAmounts
|
|
258
291
|
}
|
|
259
292
|
);
|
|
293
|
+
function multiplyAmounts(a, b) {
|
|
294
|
+
const product = a.raw * b.raw;
|
|
295
|
+
return BlockchainAmount({
|
|
296
|
+
raw: product / 10n ** BigInt(b.decimals),
|
|
297
|
+
decimals: a.decimals
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
function divideAmounts(a, b) {
|
|
301
|
+
if (b.raw === 0n) {
|
|
302
|
+
throw new MathError("Cannot divide a BlockchainAmount by zero");
|
|
303
|
+
}
|
|
304
|
+
const scaled = a.raw * 10n ** BigInt(b.decimals);
|
|
305
|
+
return BlockchainAmount({ raw: scaled / b.raw, decimals: a.decimals });
|
|
306
|
+
}
|
|
260
307
|
function combineAmounts(a, b, op) {
|
|
261
308
|
if (a.decimals !== b.decimals) {
|
|
262
|
-
throw new
|
|
309
|
+
throw new InvariantError(
|
|
263
310
|
`Cannot combine BlockchainAmounts with different decimals: ${a.decimals} vs ${b.decimals}`
|
|
264
311
|
);
|
|
265
312
|
}
|
|
266
313
|
const raw = op(a.raw, b.raw);
|
|
267
314
|
if (raw < 0n || raw > MAX_UINT_256) {
|
|
268
|
-
throw new
|
|
315
|
+
throw new InvariantError(`BlockchainAmount out of uint256 bounds: ${raw}`);
|
|
269
316
|
}
|
|
270
317
|
return BlockchainAmount({ raw, decimals: a.decimals });
|
|
271
318
|
}
|
|
@@ -285,7 +332,9 @@ var AssetIconUrl = (value) => value;
|
|
|
285
332
|
// src/shared/core/blockchain/chain.ts
|
|
286
333
|
var CHAIN_IDS = {
|
|
287
334
|
ethereum_mainnet: 1,
|
|
288
|
-
ethereum_sepolia: 11155111
|
|
335
|
+
ethereum_sepolia: 11155111,
|
|
336
|
+
base_mainnet: 8453,
|
|
337
|
+
base_sepolia: 84532
|
|
289
338
|
};
|
|
290
339
|
function getChainId(chain) {
|
|
291
340
|
return CHAIN_IDS[chain];
|
|
@@ -304,6 +353,10 @@ function getNetworkName(chain) {
|
|
|
304
353
|
return "Ethereum";
|
|
305
354
|
case "ethereum_sepolia":
|
|
306
355
|
return "Ethereum Sepolia";
|
|
356
|
+
case "base_mainnet":
|
|
357
|
+
return "Base";
|
|
358
|
+
case "base_sepolia":
|
|
359
|
+
return "Base Sepolia";
|
|
307
360
|
default: {
|
|
308
361
|
const _exhaustive = chain;
|
|
309
362
|
return _exhaustive;
|
|
@@ -319,6 +372,10 @@ function explorerBaseUrl(chain) {
|
|
|
319
372
|
return "https://etherscan.io";
|
|
320
373
|
case "ethereum_sepolia":
|
|
321
374
|
return "https://sepolia.etherscan.io";
|
|
375
|
+
case "base_mainnet":
|
|
376
|
+
return "https://basescan.org";
|
|
377
|
+
case "base_sepolia":
|
|
378
|
+
return "https://sepolia-explorer.base.org";
|
|
322
379
|
default: {
|
|
323
380
|
const _exhaustive = chain;
|
|
324
381
|
return _exhaustive;
|
|
@@ -334,25 +391,31 @@ var SwapAuthorization = {
|
|
|
334
391
|
};
|
|
335
392
|
var SwapPreview = {
|
|
336
393
|
fromDto: (dto) => ({
|
|
337
|
-
inputAmount:
|
|
338
|
-
|
|
339
|
-
|
|
394
|
+
inputAmount: parseUint256(
|
|
395
|
+
BigInt(dto.pay_input_amount),
|
|
396
|
+
"SwapPreview.pay_input_amount"
|
|
397
|
+
),
|
|
398
|
+
fee: parseUint256(BigInt(dto.fee), "SwapPreview.fee"),
|
|
399
|
+
outputAmount: parseUint256(
|
|
400
|
+
BigInt(dto.receive_output_amount),
|
|
401
|
+
"SwapPreview.receive_output_amount"
|
|
402
|
+
)
|
|
340
403
|
})
|
|
341
404
|
};
|
|
342
405
|
var SwapStatus = {
|
|
343
406
|
fromDto: (dto) => ({
|
|
344
|
-
stopped:
|
|
345
|
-
swapLevel:
|
|
407
|
+
stopped: parseUint256(BigInt(dto.stopped), "SwapStatus.stopped"),
|
|
408
|
+
swapLevel: parseUint256(BigInt(dto.swap_level), "SwapStatus.swap_level")
|
|
346
409
|
})
|
|
347
410
|
};
|
|
348
411
|
var TokenAllowance = {
|
|
349
412
|
fromDto: (dto) => ({
|
|
350
|
-
allowance:
|
|
413
|
+
allowance: parseUint256(BigInt(dto.allowance), "TokenAllowance.allowance")
|
|
351
414
|
})
|
|
352
415
|
};
|
|
353
416
|
var TokenBalance = {
|
|
354
417
|
fromDto: (dto) => ({
|
|
355
|
-
balance:
|
|
418
|
+
balance: parseUint256(BigInt(dto.balance), "TokenBalance.balance")
|
|
356
419
|
})
|
|
357
420
|
};
|
|
358
421
|
var AllowWalletResponse = {
|
|
@@ -477,18 +540,172 @@ function toErc20Asset(dto) {
|
|
|
477
540
|
};
|
|
478
541
|
}
|
|
479
542
|
|
|
543
|
+
// src/shared/core/observability/log-cause.ts
|
|
544
|
+
function classifyLogCause(error) {
|
|
545
|
+
if (error instanceof HttpError) {
|
|
546
|
+
return httpCause(error);
|
|
547
|
+
}
|
|
548
|
+
if (error instanceof ValidationError) {
|
|
549
|
+
return { type: "validation", message: error.message };
|
|
550
|
+
}
|
|
551
|
+
if (error instanceof InvariantError) {
|
|
552
|
+
return { type: "invariant", message: error.message };
|
|
553
|
+
}
|
|
554
|
+
if (error instanceof MathError) {
|
|
555
|
+
return { type: "math", message: error.message };
|
|
556
|
+
}
|
|
557
|
+
if (error instanceof NotAuthenticatedError) {
|
|
558
|
+
return { type: "not-authenticated" };
|
|
559
|
+
}
|
|
560
|
+
if (error instanceof NotImplementedError) {
|
|
561
|
+
return { type: "not-implemented" };
|
|
562
|
+
}
|
|
563
|
+
return { type: "generic-error", name: errorName(error) };
|
|
564
|
+
}
|
|
565
|
+
function describeErrorUnredacted(error) {
|
|
566
|
+
if (error instanceof HttpError) {
|
|
567
|
+
return describeHttpErrorRedacted(error);
|
|
568
|
+
}
|
|
569
|
+
if (error instanceof Error) {
|
|
570
|
+
return `${error.name}: ${error.message}`;
|
|
571
|
+
}
|
|
572
|
+
return `thrown non-error: ${stringifyUnredacted(error)}`;
|
|
573
|
+
}
|
|
574
|
+
function stringifyUnredacted(value) {
|
|
575
|
+
if (value === void 0) return "";
|
|
576
|
+
try {
|
|
577
|
+
return JSON.stringify(
|
|
578
|
+
value,
|
|
579
|
+
(_key, item) => typeof item === "bigint" ? `${item}` : item
|
|
580
|
+
) ?? String(value);
|
|
581
|
+
} catch (_) {
|
|
582
|
+
return "<unserializable>";
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
function describeHttpErrorRedacted(error) {
|
|
586
|
+
const code = apiErrorCode(error);
|
|
587
|
+
const status = error.response.status;
|
|
588
|
+
return code === null ? `HttpError ${status}` : `HttpError ${status} (${code})`;
|
|
589
|
+
}
|
|
590
|
+
function errorName(error) {
|
|
591
|
+
return error instanceof Error ? error.name : `non-error ${typeof error}`;
|
|
592
|
+
}
|
|
593
|
+
function httpCause(error) {
|
|
594
|
+
return {
|
|
595
|
+
type: "http",
|
|
596
|
+
requestId: error.requestId,
|
|
597
|
+
status: error.response.status,
|
|
598
|
+
code: apiErrorCode(error),
|
|
599
|
+
eventId: apiErrorEventId(error)
|
|
600
|
+
};
|
|
601
|
+
}
|
|
602
|
+
function apiErrorEventId(error) {
|
|
603
|
+
const body = error.response.body;
|
|
604
|
+
if (typeof body !== "object" || body === null) return null;
|
|
605
|
+
const eventId = body.event_id;
|
|
606
|
+
return typeof eventId === "string" ? eventId : null;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
// src/shared/core/observability/internal-logger.ts
|
|
610
|
+
function internalLogger(logger, scope) {
|
|
611
|
+
return logger ? scopedLogger(logger, scope, {}) : noopInternalLogger;
|
|
612
|
+
}
|
|
613
|
+
var LEVEL_RANK = {
|
|
614
|
+
none: 0,
|
|
615
|
+
error: 1,
|
|
616
|
+
warn: 2,
|
|
617
|
+
info: 3,
|
|
618
|
+
debug: 4
|
|
619
|
+
};
|
|
620
|
+
function scopedLogger(logger, scope, bindings) {
|
|
621
|
+
const admits = (level) => LEVEL_RANK[logger.level()] >= LEVEL_RANK[level];
|
|
622
|
+
const safe = (event) => ({
|
|
623
|
+
msg: event.msg,
|
|
624
|
+
scope,
|
|
625
|
+
bindings,
|
|
626
|
+
fields: event.fields ?? {},
|
|
627
|
+
...event.cause === void 0 ? {} : { cause: event.cause }
|
|
628
|
+
});
|
|
629
|
+
const unredacted = (event) => ({
|
|
630
|
+
msg: event.msg,
|
|
631
|
+
scope,
|
|
632
|
+
bindings,
|
|
633
|
+
fields: event.fields ?? {}
|
|
634
|
+
});
|
|
635
|
+
const self = {
|
|
636
|
+
child: (binding) => scopedLogger(logger, scope, { ...bindings, ...binding }),
|
|
637
|
+
debug: (event) => {
|
|
638
|
+
if (admits("debug")) logger.debug(() => unredacted(event()));
|
|
639
|
+
},
|
|
640
|
+
info: (event) => {
|
|
641
|
+
if (admits("info")) logger.info(() => safe(event()));
|
|
642
|
+
},
|
|
643
|
+
warn: (event) => {
|
|
644
|
+
if (admits("warn")) logger.warn(() => safe(event()));
|
|
645
|
+
},
|
|
646
|
+
error: (event) => {
|
|
647
|
+
if (admits("error")) logger.error(() => safe(event()));
|
|
648
|
+
},
|
|
649
|
+
failure: (event, error) => {
|
|
650
|
+
if (admits("debug"))
|
|
651
|
+
logger.debug(() => unredacted(verbatim(event(), error)));
|
|
652
|
+
if (admits("error")) logger.error(() => safe(classified(event(), error)));
|
|
653
|
+
},
|
|
654
|
+
warning: (event, error) => {
|
|
655
|
+
if (admits("debug"))
|
|
656
|
+
logger.debug(() => unredacted(verbatim(event(), error)));
|
|
657
|
+
if (admits("warn")) logger.warn(() => safe(classified(event(), error)));
|
|
658
|
+
},
|
|
659
|
+
wrap: async (op, params, run) => {
|
|
660
|
+
const opLog = self.child({ op });
|
|
661
|
+
opLog.debug(() => ({ msg: "call", fields: { params } }));
|
|
662
|
+
try {
|
|
663
|
+
return await run();
|
|
664
|
+
} catch (error) {
|
|
665
|
+
opLog.failure(() => ({ msg: "call failed" }), error);
|
|
666
|
+
throw error;
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
};
|
|
670
|
+
return self;
|
|
671
|
+
}
|
|
672
|
+
function verbatim(event, error) {
|
|
673
|
+
return {
|
|
674
|
+
msg: event.msg,
|
|
675
|
+
fields: { ...event.fields, error: describeErrorUnredacted(error) }
|
|
676
|
+
};
|
|
677
|
+
}
|
|
678
|
+
function classified(event, error) {
|
|
679
|
+
return { ...event, cause: event.cause ?? classifyLogCause(error) };
|
|
680
|
+
}
|
|
681
|
+
var noopInternalLogger = {
|
|
682
|
+
child: () => noopInternalLogger,
|
|
683
|
+
debug: () => void 0,
|
|
684
|
+
info: () => void 0,
|
|
685
|
+
warn: () => void 0,
|
|
686
|
+
error: () => void 0,
|
|
687
|
+
failure: () => void 0,
|
|
688
|
+
warning: () => void 0,
|
|
689
|
+
wrap: (_op, _params, run) => run()
|
|
690
|
+
};
|
|
691
|
+
|
|
480
692
|
// src/shared/core/blockchain/erc20/erc20-namespace.ts
|
|
481
693
|
var Erc20NamespaceImpl = class {
|
|
482
694
|
constructor(ctx) {
|
|
483
695
|
this.ctx = ctx;
|
|
696
|
+
this.log = internalLogger(ctx.logger, "ERC20");
|
|
484
697
|
}
|
|
485
698
|
async getAllowance(params) {
|
|
486
|
-
|
|
487
|
-
|
|
699
|
+
return this.log.wrap("getAllowance", params, async () => {
|
|
700
|
+
await this.ctx.ensureUserAuthenticated();
|
|
701
|
+
return getTokenAllowance(this.ctx.api, params);
|
|
702
|
+
});
|
|
488
703
|
}
|
|
489
704
|
async getBalance(params) {
|
|
490
|
-
|
|
491
|
-
|
|
705
|
+
return this.log.wrap("getBalance", params, async () => {
|
|
706
|
+
await this.ctx.ensureUserAuthenticated();
|
|
707
|
+
return getTokenBalance(this.ctx.api, params);
|
|
708
|
+
});
|
|
492
709
|
}
|
|
493
710
|
};
|
|
494
711
|
|
|
@@ -684,15 +901,30 @@ var Asset = {
|
|
|
684
901
|
var OfferId = (value) => value;
|
|
685
902
|
var OfferSlug = (value) => value;
|
|
686
903
|
var Offer = {
|
|
904
|
+
fromDto: (dto) => {
|
|
905
|
+
if (!Array.isArray(dto.tokens)) {
|
|
906
|
+
throw new ValidationError(
|
|
907
|
+
`Offer.tokens: expected an array, got ${typeof dto.tokens}`
|
|
908
|
+
);
|
|
909
|
+
}
|
|
910
|
+
return {
|
|
911
|
+
id: OfferId(dto.id),
|
|
912
|
+
slug: OfferSlug(dto.slug),
|
|
913
|
+
type: dto.type,
|
|
914
|
+
tagline: dto.tagline,
|
|
915
|
+
bannerUrl: dto.banner_url,
|
|
916
|
+
logoUrl: dto.logo_url,
|
|
917
|
+
startsAt: new Date(dto.starts_at),
|
|
918
|
+
endsAt: dto.ends_at ? new Date(dto.ends_at) : null,
|
|
919
|
+
tokens: dto.tokens.map(OfferToken.fromDto)
|
|
920
|
+
};
|
|
921
|
+
}
|
|
922
|
+
};
|
|
923
|
+
var OfferToken = {
|
|
687
924
|
fromDto: (dto) => ({
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
tagline: dto.tagline,
|
|
692
|
-
bannerUrl: dto.banner_url,
|
|
693
|
-
logoUrl: dto.logo_url,
|
|
694
|
-
startsAt: new Date(dto.starts_at),
|
|
695
|
-
endsAt: dto.ends_at ? new Date(dto.ends_at) : null
|
|
925
|
+
role: dto.role,
|
|
926
|
+
chain: Chain(dto.chain),
|
|
927
|
+
address: EvmContractAddress(dto.address)
|
|
696
928
|
})
|
|
697
929
|
};
|
|
698
930
|
|
|
@@ -752,25 +984,39 @@ var OfferOptionSlug = (value) => value;
|
|
|
752
984
|
var OfferDetail = {
|
|
753
985
|
fromDto: (dto) => {
|
|
754
986
|
if (!Array.isArray(dto.funding_assets)) {
|
|
755
|
-
throw new
|
|
987
|
+
throw new ValidationError(
|
|
988
|
+
`OfferDetail.funding_assets: expected an array, got ${typeof dto.funding_assets}`
|
|
989
|
+
);
|
|
756
990
|
}
|
|
757
991
|
if (!Array.isArray(dto.options)) {
|
|
758
|
-
throw new
|
|
992
|
+
throw new ValidationError(
|
|
993
|
+
`OfferDetail.options: expected an array, got ${typeof dto.options}`
|
|
994
|
+
);
|
|
759
995
|
}
|
|
760
996
|
if (!Array.isArray(dto.terms)) {
|
|
761
|
-
throw new
|
|
997
|
+
throw new ValidationError(
|
|
998
|
+
`OfferDetail.terms: expected an array, got ${typeof dto.terms}`
|
|
999
|
+
);
|
|
762
1000
|
}
|
|
763
1001
|
if (!Array.isArray(dto.links)) {
|
|
764
|
-
throw new
|
|
1002
|
+
throw new ValidationError(
|
|
1003
|
+
`OfferDetail.links: expected an array, got ${typeof dto.links}`
|
|
1004
|
+
);
|
|
765
1005
|
}
|
|
766
1006
|
if (!Array.isArray(dto.faqs)) {
|
|
767
|
-
throw new
|
|
1007
|
+
throw new ValidationError(
|
|
1008
|
+
`OfferDetail.faqs: expected an array, got ${typeof dto.faqs}`
|
|
1009
|
+
);
|
|
768
1010
|
}
|
|
769
1011
|
if (!Array.isArray(dto.milestones)) {
|
|
770
|
-
throw new
|
|
1012
|
+
throw new ValidationError(
|
|
1013
|
+
`OfferDetail.milestones: expected an array, got ${typeof dto.milestones}`
|
|
1014
|
+
);
|
|
771
1015
|
}
|
|
772
1016
|
if (!Array.isArray(dto.tokens)) {
|
|
773
|
-
throw new
|
|
1017
|
+
throw new ValidationError(
|
|
1018
|
+
`OfferDetail.tokens: expected an array, got ${typeof dto.tokens}`
|
|
1019
|
+
);
|
|
774
1020
|
}
|
|
775
1021
|
return {
|
|
776
1022
|
id: OfferId(dto.id),
|
|
@@ -832,13 +1078,6 @@ var Milestone = {
|
|
|
832
1078
|
status: dto.status
|
|
833
1079
|
})
|
|
834
1080
|
};
|
|
835
|
-
var OfferToken = {
|
|
836
|
-
fromDto: (dto) => ({
|
|
837
|
-
role: dto.role,
|
|
838
|
-
chain: Chain(dto.chain),
|
|
839
|
-
address: EvmContractAddress(dto.address)
|
|
840
|
-
})
|
|
841
|
-
};
|
|
842
1081
|
|
|
843
1082
|
// src/shared/types/providers/coin-list/token-sale.ts
|
|
844
1083
|
var ParticipationId = (value) => value;
|
|
@@ -925,22 +1164,31 @@ async function createParticipation(api, params) {
|
|
|
925
1164
|
var CoinListTokenSaleNamespaceImpl = class {
|
|
926
1165
|
constructor(ctx) {
|
|
927
1166
|
this.ctx = ctx;
|
|
1167
|
+
this.log = internalLogger(ctx.logger, "TOKEN_SALE");
|
|
928
1168
|
}
|
|
929
1169
|
async list(offerId) {
|
|
930
|
-
|
|
931
|
-
|
|
1170
|
+
return this.log.wrap("list", offerId, async () => {
|
|
1171
|
+
await this.ctx.ensureUserAuthenticated();
|
|
1172
|
+
return fetchParticipations(this.ctx.api, offerId);
|
|
1173
|
+
});
|
|
932
1174
|
}
|
|
933
1175
|
async listPage(params) {
|
|
934
|
-
|
|
935
|
-
|
|
1176
|
+
return this.log.wrap("listPage", params, async () => {
|
|
1177
|
+
await this.ctx.ensureUserAuthenticated();
|
|
1178
|
+
return fetchParticipationsPage(this.ctx.api, params);
|
|
1179
|
+
});
|
|
936
1180
|
}
|
|
937
1181
|
async get(id) {
|
|
938
|
-
|
|
939
|
-
|
|
1182
|
+
return this.log.wrap("get", id, async () => {
|
|
1183
|
+
await this.ctx.ensureUserAuthenticated();
|
|
1184
|
+
return fetchParticipation(this.ctx.api, id);
|
|
1185
|
+
});
|
|
940
1186
|
}
|
|
941
1187
|
async createParticipation(params) {
|
|
942
|
-
|
|
943
|
-
|
|
1188
|
+
return this.log.wrap("createParticipation", params, async () => {
|
|
1189
|
+
await this.ctx.ensureUserAuthenticated();
|
|
1190
|
+
return createParticipation(this.ctx.api, params);
|
|
1191
|
+
});
|
|
944
1192
|
}
|
|
945
1193
|
};
|
|
946
1194
|
|
|
@@ -985,47 +1233,122 @@ var OndoQuote = {
|
|
|
985
1233
|
};
|
|
986
1234
|
}
|
|
987
1235
|
};
|
|
988
|
-
var
|
|
1236
|
+
var OndoBuyTransaction = {
|
|
989
1237
|
fromDto: (dto) => {
|
|
990
|
-
const
|
|
1238
|
+
const spendDecimals = AssetDecimals(dto.spend_input_decimals);
|
|
991
1239
|
const outputDecimals = AssetDecimals(dto.receive_output_decimals);
|
|
992
1240
|
return {
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
data: HexEncodedTransactionData(dto.data)
|
|
996
|
-
},
|
|
997
|
-
expiresAt: parseExpiresAt(dto.expires_at),
|
|
998
|
-
payInputAmount: blockchainAmountFromRawOrThrow({
|
|
999
|
-
label: "pay_input_amount",
|
|
1000
|
-
raw: dto.pay_input_amount,
|
|
1001
|
-
decimals: inputDecimals
|
|
1002
|
-
}),
|
|
1241
|
+
...parseSwapCore(dto, spendDecimals),
|
|
1242
|
+
side: "buy",
|
|
1003
1243
|
fee: blockchainAmountFromRawOrThrow({
|
|
1004
1244
|
label: "fee",
|
|
1005
1245
|
raw: dto.fee,
|
|
1006
|
-
decimals:
|
|
1246
|
+
decimals: spendDecimals
|
|
1007
1247
|
}),
|
|
1008
1248
|
notionalValue: blockchainAmountFromRawOrThrow({
|
|
1009
1249
|
label: "notional_value",
|
|
1010
1250
|
raw: dto.notional_value,
|
|
1011
|
-
decimals:
|
|
1251
|
+
decimals: spendDecimals
|
|
1012
1252
|
}),
|
|
1013
|
-
receiveOutputAmount:
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1253
|
+
receiveOutputAmount: parsePositiveAmount({
|
|
1254
|
+
label: "receive_output_amount",
|
|
1255
|
+
raw: dto.receive_output_amount,
|
|
1256
|
+
decimals: outputDecimals,
|
|
1257
|
+
// A transaction that yields nothing is not one to sign - the user
|
|
1258
|
+
// would pay the deposit and receive no asset - and frontline refuses
|
|
1259
|
+
// to emit one. A zero here is a changed encoding, not a small order.
|
|
1260
|
+
// Rejecting it at the boundary is also what lets `computeOndoBuyPrice`
|
|
1261
|
+
// divide by it without a fallible result: the failure surfaces as the
|
|
1262
|
+
// data hook's ERROR state rather than as a division during render.
|
|
1263
|
+
reason: "a buy that yields nothing is not fillable"
|
|
1264
|
+
})
|
|
1265
|
+
};
|
|
1266
|
+
}
|
|
1267
|
+
};
|
|
1268
|
+
var OndoSellTransaction = {
|
|
1269
|
+
fromDto: (dto) => {
|
|
1270
|
+
const spendDecimals = AssetDecimals(dto.spend_input_decimals);
|
|
1271
|
+
const outputDecimals = AssetDecimals(dto.receive_output_decimals);
|
|
1272
|
+
const expectedQuantity = parsePositiveAmount({
|
|
1273
|
+
label: "expected_quantity",
|
|
1274
|
+
raw: dto.expected_quantity,
|
|
1275
|
+
decimals: outputDecimals,
|
|
1276
|
+
reason: "a sale that yields nothing is not fillable"
|
|
1277
|
+
});
|
|
1278
|
+
return {
|
|
1279
|
+
...parseSwapCore(dto, spendDecimals),
|
|
1280
|
+
side: "sell",
|
|
1281
|
+
expected: {
|
|
1282
|
+
quantity: expectedQuantity,
|
|
1283
|
+
fee: blockchainAmountFromRawOrThrow({
|
|
1284
|
+
label: "expected_fee",
|
|
1285
|
+
raw: dto.expected_fee,
|
|
1286
|
+
decimals: outputDecimals
|
|
1287
|
+
})
|
|
1288
|
+
},
|
|
1289
|
+
minimum: {
|
|
1290
|
+
quantity: parseMinimumQuantity(
|
|
1291
|
+
dto.minimum_quantity,
|
|
1292
|
+
outputDecimals,
|
|
1293
|
+
expectedQuantity
|
|
1294
|
+
),
|
|
1295
|
+
fee: blockchainAmountFromRawOrThrow({
|
|
1296
|
+
label: "minimum_fee",
|
|
1297
|
+
raw: dto.minimum_fee,
|
|
1298
|
+
decimals: outputDecimals
|
|
1299
|
+
})
|
|
1300
|
+
}
|
|
1017
1301
|
};
|
|
1018
1302
|
}
|
|
1019
1303
|
};
|
|
1020
|
-
function
|
|
1021
|
-
|
|
1022
|
-
|
|
1304
|
+
function parseSwapCore(dto, spendDecimals) {
|
|
1305
|
+
return {
|
|
1306
|
+
tx: {
|
|
1307
|
+
to: EvmContractAddress(dto.to),
|
|
1308
|
+
data: HexEncodedTransactionData(dto.data)
|
|
1309
|
+
},
|
|
1310
|
+
expiresAt: parseExpiresAt(dto.expires_at),
|
|
1311
|
+
spendInputAmount: parsePositiveAmount({
|
|
1312
|
+
label: "spend_input_amount",
|
|
1313
|
+
raw: dto.spend_input_amount,
|
|
1314
|
+
decimals: spendDecimals,
|
|
1315
|
+
// A transaction that takes nothing from the wallet is not one to sign:
|
|
1316
|
+
// it would settle one leg of a trade and skip the other. Frontline
|
|
1317
|
+
// refuses an `amount` of zero whichever way the trade runs, so this is a
|
|
1318
|
+
// changed encoding rather than a small order.
|
|
1319
|
+
//
|
|
1320
|
+
// Guarded on both sides rather than on the sale alone, because which
|
|
1321
|
+
// amount becomes the divisor in the price flips with the direction: a
|
|
1322
|
+
// guard placed by that would be a rule about the arithmetic rather than
|
|
1323
|
+
// about the trade.
|
|
1324
|
+
reason: "a swap that spends nothing is not fillable"
|
|
1325
|
+
})
|
|
1326
|
+
};
|
|
1327
|
+
}
|
|
1328
|
+
function parseMinimumQuantity(raw, decimals, expectedQuantity) {
|
|
1329
|
+
const amount = parsePositiveAmount({
|
|
1330
|
+
label: "minimum_quantity",
|
|
1023
1331
|
raw,
|
|
1024
|
-
decimals
|
|
1332
|
+
decimals,
|
|
1333
|
+
reason: "a floor of zero guarantees nothing"
|
|
1025
1334
|
});
|
|
1335
|
+
if (amount.raw > expectedQuantity.raw) {
|
|
1336
|
+
throw new ValidationError(
|
|
1337
|
+
`minimum_quantity: must not exceed expected_quantity ("${raw}" > "${expectedQuantity.raw}")`
|
|
1338
|
+
);
|
|
1339
|
+
}
|
|
1340
|
+
return amount;
|
|
1341
|
+
}
|
|
1342
|
+
function parsePositiveAmount({
|
|
1343
|
+
label,
|
|
1344
|
+
raw,
|
|
1345
|
+
decimals,
|
|
1346
|
+
reason
|
|
1347
|
+
}) {
|
|
1348
|
+
const amount = blockchainAmountFromRawOrThrow({ label, raw, decimals });
|
|
1026
1349
|
if (amount.raw <= 0n) {
|
|
1027
1350
|
throw new ValidationError(
|
|
1028
|
-
|
|
1351
|
+
`${label}: must be greater than zero ("${raw}") - ${reason}`
|
|
1029
1352
|
);
|
|
1030
1353
|
}
|
|
1031
1354
|
return amount;
|
|
@@ -1062,27 +1385,57 @@ async function getOndoQuote(api, params) {
|
|
|
1062
1385
|
});
|
|
1063
1386
|
return OndoQuote.fromDto(dto);
|
|
1064
1387
|
}
|
|
1065
|
-
async function
|
|
1388
|
+
async function buildOndoBuy(api, params) {
|
|
1066
1389
|
const dto = await api.send({
|
|
1067
1390
|
method: "POST",
|
|
1068
|
-
url: "/v1/ondo/swap/
|
|
1069
|
-
body:
|
|
1070
|
-
symbol: params.symbol,
|
|
1071
|
-
chain: params.chain,
|
|
1072
|
-
wallet_address: params.walletAddress,
|
|
1073
|
-
amount: params.amount.raw.toString()
|
|
1074
|
-
},
|
|
1391
|
+
url: "/v1/ondo/swap/buy",
|
|
1392
|
+
body: swapBody(params),
|
|
1075
1393
|
attributes: Attributes.protected()
|
|
1076
1394
|
});
|
|
1077
|
-
|
|
1078
|
-
|
|
1395
|
+
assertSpendScaleAgrees({
|
|
1396
|
+
published: dto.spend_input_decimals,
|
|
1397
|
+
sized: params.amount,
|
|
1398
|
+
trade: "purchase"
|
|
1399
|
+
});
|
|
1400
|
+
return OndoBuyTransaction.fromDto(dto);
|
|
1079
1401
|
}
|
|
1080
|
-
function
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
)
|
|
1085
|
-
|
|
1402
|
+
async function buildOndoSell(api, params) {
|
|
1403
|
+
const dto = await api.send({
|
|
1404
|
+
method: "POST",
|
|
1405
|
+
url: "/v1/ondo/swap/sell",
|
|
1406
|
+
body: swapBody(params),
|
|
1407
|
+
attributes: Attributes.protected()
|
|
1408
|
+
});
|
|
1409
|
+
assertSpendScaleAgrees({
|
|
1410
|
+
published: dto.spend_input_decimals,
|
|
1411
|
+
sized: params.amount,
|
|
1412
|
+
trade: "sale",
|
|
1413
|
+
// The two answers come from two chains, so on a testnet they can disagree
|
|
1414
|
+
// for a reason that is neither the caller's nor a corrupt response. Say so,
|
|
1415
|
+
// or a QA run reads as a puzzle rather than a diagnosis.
|
|
1416
|
+
note: "the quote resolves the asset on Ethereum mainnet while the swap executes on the chain requested, so these disagree until frontline serves a chain-scoped quote"
|
|
1417
|
+
});
|
|
1418
|
+
return OndoSellTransaction.fromDto(dto);
|
|
1419
|
+
}
|
|
1420
|
+
function swapBody(params) {
|
|
1421
|
+
return {
|
|
1422
|
+
symbol: params.symbol,
|
|
1423
|
+
chain: params.chain,
|
|
1424
|
+
wallet_address: params.walletAddress,
|
|
1425
|
+
amount: params.amount.raw.toString()
|
|
1426
|
+
};
|
|
1427
|
+
}
|
|
1428
|
+
function assertSpendScaleAgrees({
|
|
1429
|
+
published,
|
|
1430
|
+
sized,
|
|
1431
|
+
trade,
|
|
1432
|
+
note
|
|
1433
|
+
}) {
|
|
1434
|
+
if (published === sized.decimals) return;
|
|
1435
|
+
const because = note === void 0 ? "" : ` - ${note}`;
|
|
1436
|
+
throw new ValidationError(
|
|
1437
|
+
`spend_input_decimals: the ${trade} was priced in ${published} decimals but the order was sized in ${sized.decimals}${because}`
|
|
1438
|
+
);
|
|
1086
1439
|
}
|
|
1087
1440
|
function sizeParam(params) {
|
|
1088
1441
|
const tokenAmount = "tokenAmount" in params ? params.tokenAmount : void 0;
|
|
@@ -1107,18 +1460,31 @@ function sizeParam(params) {
|
|
|
1107
1460
|
var OndoNamespaceImpl = class {
|
|
1108
1461
|
constructor(ctx) {
|
|
1109
1462
|
this.ctx = ctx;
|
|
1463
|
+
this.log = internalLogger(ctx.logger, "ONDO");
|
|
1110
1464
|
}
|
|
1111
1465
|
async getTradingStatus(params) {
|
|
1112
|
-
|
|
1113
|
-
|
|
1466
|
+
return this.log.wrap("getTradingStatus", params, async () => {
|
|
1467
|
+
await this.ctx.ensureUserAuthenticated();
|
|
1468
|
+
return getOndoTradingStatus(this.ctx.api, params);
|
|
1469
|
+
});
|
|
1114
1470
|
}
|
|
1115
1471
|
async getQuote(params) {
|
|
1116
|
-
|
|
1117
|
-
|
|
1472
|
+
return this.log.wrap("getQuote", params, async () => {
|
|
1473
|
+
await this.ctx.ensureUserAuthenticated();
|
|
1474
|
+
return getOndoQuote(this.ctx.api, params);
|
|
1475
|
+
});
|
|
1118
1476
|
}
|
|
1119
|
-
async
|
|
1120
|
-
|
|
1121
|
-
|
|
1477
|
+
async buildBuyTransaction(params) {
|
|
1478
|
+
return this.log.wrap("buildBuyTransaction", params, async () => {
|
|
1479
|
+
await this.ctx.ensureUserAuthenticated();
|
|
1480
|
+
return buildOndoBuy(this.ctx.api, params);
|
|
1481
|
+
});
|
|
1482
|
+
}
|
|
1483
|
+
async buildSellTransaction(params) {
|
|
1484
|
+
return this.log.wrap("buildSellTransaction", params, async () => {
|
|
1485
|
+
await this.ctx.ensureUserAuthenticated();
|
|
1486
|
+
return buildOndoSell(this.ctx.api, params);
|
|
1487
|
+
});
|
|
1122
1488
|
}
|
|
1123
1489
|
};
|
|
1124
1490
|
|
|
@@ -1126,26 +1492,37 @@ var OndoNamespaceImpl = class {
|
|
|
1126
1492
|
var SuperstateSwapNamespaceImpl = class {
|
|
1127
1493
|
constructor(ctx) {
|
|
1128
1494
|
this.ctx = ctx;
|
|
1495
|
+
this.log = internalLogger(ctx.logger, "SUPERSTATE");
|
|
1129
1496
|
}
|
|
1130
1497
|
async getAuthorization(params) {
|
|
1131
|
-
|
|
1132
|
-
|
|
1498
|
+
return this.log.wrap("getAuthorization", params, async () => {
|
|
1499
|
+
await this.ctx.ensureUserAuthenticated();
|
|
1500
|
+
return getSwapAuthorization(this.ctx.api, params);
|
|
1501
|
+
});
|
|
1133
1502
|
}
|
|
1134
1503
|
async getPreview(params) {
|
|
1135
|
-
|
|
1136
|
-
|
|
1504
|
+
return this.log.wrap("getPreview", params, async () => {
|
|
1505
|
+
await this.ctx.ensureUserAuthenticated();
|
|
1506
|
+
return getSwapPreview(this.ctx.api, params);
|
|
1507
|
+
});
|
|
1137
1508
|
}
|
|
1138
1509
|
async getStatus(params) {
|
|
1139
|
-
|
|
1140
|
-
|
|
1510
|
+
return this.log.wrap("getStatus", params, async () => {
|
|
1511
|
+
await this.ctx.ensureUserAuthenticated();
|
|
1512
|
+
return getSwapStatus(this.ctx.api, params);
|
|
1513
|
+
});
|
|
1141
1514
|
}
|
|
1142
1515
|
async getOutputToken(params) {
|
|
1143
|
-
|
|
1144
|
-
|
|
1516
|
+
return this.log.wrap("getOutputToken", params, async () => {
|
|
1517
|
+
await this.ctx.ensureUserAuthenticated();
|
|
1518
|
+
return getSwapOutputToken(this.ctx.api, params);
|
|
1519
|
+
});
|
|
1145
1520
|
}
|
|
1146
1521
|
async allowWallet(params) {
|
|
1147
|
-
|
|
1148
|
-
|
|
1522
|
+
return this.log.wrap("allowWallet", params, async () => {
|
|
1523
|
+
await this.ctx.ensureUserAuthenticated();
|
|
1524
|
+
return allowWallet(this.ctx.api, params);
|
|
1525
|
+
});
|
|
1149
1526
|
}
|
|
1150
1527
|
};
|
|
1151
1528
|
|
|
@@ -1278,38 +1655,49 @@ async function fetchRequirementStatuses(api, offerId) {
|
|
|
1278
1655
|
var RequirementsNamespaceImpl = class {
|
|
1279
1656
|
constructor(ctx) {
|
|
1280
1657
|
this.ctx = ctx;
|
|
1658
|
+
this.log = internalLogger(ctx.logger, "REQUIREMENTS");
|
|
1281
1659
|
}
|
|
1282
1660
|
async forOffer(offerId) {
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1661
|
+
return this.log.wrap("forOffer", offerId, async () => {
|
|
1662
|
+
await this.ctx.ensureUserAuthenticated();
|
|
1663
|
+
return fetchOfferRequirements(
|
|
1664
|
+
this.ctx.api,
|
|
1665
|
+
offerId,
|
|
1666
|
+
void 0
|
|
1667
|
+
);
|
|
1668
|
+
});
|
|
1289
1669
|
}
|
|
1290
1670
|
async statuses(offerId) {
|
|
1291
|
-
|
|
1292
|
-
|
|
1671
|
+
return this.log.wrap("statuses", offerId, async () => {
|
|
1672
|
+
await this.ctx.ensureUserAuthenticated();
|
|
1673
|
+
return fetchRequirementStatuses(this.ctx.api, offerId);
|
|
1674
|
+
});
|
|
1293
1675
|
}
|
|
1294
1676
|
async createKycToken(params) {
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1677
|
+
return this.log.wrap("createKycToken", params, async () => {
|
|
1678
|
+
await this.ctx.ensureUserAuthenticated();
|
|
1679
|
+
return createKycToken(
|
|
1680
|
+
this.ctx.api,
|
|
1681
|
+
params?.levelName,
|
|
1682
|
+
params?.reset
|
|
1683
|
+
);
|
|
1684
|
+
});
|
|
1301
1685
|
}
|
|
1302
1686
|
async getPii() {
|
|
1303
|
-
|
|
1304
|
-
|
|
1687
|
+
return this.log.wrap("getPii", void 0, async () => {
|
|
1688
|
+
await this.ctx.ensureUserAuthenticated();
|
|
1689
|
+
return fetchPii(this.ctx.api);
|
|
1690
|
+
});
|
|
1305
1691
|
}
|
|
1306
1692
|
async submitDocument(params) {
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1693
|
+
return this.log.wrap("submitDocument", params, async () => {
|
|
1694
|
+
await this.ctx.ensureUserAuthenticated();
|
|
1695
|
+
return submitDocument(
|
|
1696
|
+
this.ctx.api,
|
|
1697
|
+
params.documentType,
|
|
1698
|
+
params.fields
|
|
1699
|
+
);
|
|
1700
|
+
});
|
|
1313
1701
|
}
|
|
1314
1702
|
};
|
|
1315
1703
|
|
|
@@ -1339,27 +1727,47 @@ var TokenMetadata = {
|
|
|
1339
1727
|
logoDark: dto.logo_dark === void 0 ? null : TokenLogo.fromDto(dto.logo_dark, baseUrl)
|
|
1340
1728
|
};
|
|
1341
1729
|
},
|
|
1730
|
+
/**
|
|
1731
|
+
* Maps the complete registry snapshot to every token it lists across the
|
|
1732
|
+
* chains this SDK models, skipping native coins and chains outside
|
|
1733
|
+
* {@link EthereumChain} (e.g. Solana) rather than failing on them — the
|
|
1734
|
+
* registry may serve chains ahead of the SDK's type surface.
|
|
1735
|
+
*/
|
|
1736
|
+
fromRegistryDto: (dto, baseUrl) => {
|
|
1737
|
+
assertSupportedSchemaVersion(dto.schema_version);
|
|
1738
|
+
return dto.chains.flatMap((chainDto) => {
|
|
1739
|
+
let chain;
|
|
1740
|
+
try {
|
|
1741
|
+
chain = EthereumChain(chainDto.chain);
|
|
1742
|
+
} catch {
|
|
1743
|
+
return [];
|
|
1744
|
+
}
|
|
1745
|
+
return tokensOfChain(chain, chainDto.assets, baseUrl);
|
|
1746
|
+
});
|
|
1747
|
+
},
|
|
1342
1748
|
/**
|
|
1343
1749
|
* Maps a chain snapshot to the tokens it lists, skipping the chain's native
|
|
1344
1750
|
* coin (`kind: 'COIN'`, no contract address).
|
|
1345
1751
|
*/
|
|
1346
1752
|
fromChainAssetsDto: (dto, baseUrl) => {
|
|
1347
1753
|
assertSupportedSchemaVersion(dto.schema_version);
|
|
1348
|
-
|
|
1349
|
-
return dto.assets.filter((asset) => asset.kind === "TOKEN" && asset.address !== void 0).map((asset) => ({
|
|
1350
|
-
identifier: {
|
|
1351
|
-
chain,
|
|
1352
|
-
// The filter above cannot narrow `address` for the type checker.
|
|
1353
|
-
address: EvmContractAddress(asset.address)
|
|
1354
|
-
},
|
|
1355
|
-
name: asset.name,
|
|
1356
|
-
symbol: AssetSymbol(asset.symbol),
|
|
1357
|
-
decimals: AssetDecimals(asset.decimals),
|
|
1358
|
-
logo: TokenLogo.fromDto(asset.logo, baseUrl),
|
|
1359
|
-
logoDark: asset.logo_dark === void 0 ? null : TokenLogo.fromDto(asset.logo_dark, baseUrl)
|
|
1360
|
-
}));
|
|
1754
|
+
return tokensOfChain(EthereumChain(dto.chain), dto.assets, baseUrl);
|
|
1361
1755
|
}
|
|
1362
1756
|
};
|
|
1757
|
+
function tokensOfChain(chain, assets, baseUrl) {
|
|
1758
|
+
return assets.filter((asset) => asset.kind === "TOKEN" && asset.address !== void 0).map((asset) => ({
|
|
1759
|
+
identifier: {
|
|
1760
|
+
chain,
|
|
1761
|
+
// The filter above cannot narrow `address` for the type checker.
|
|
1762
|
+
address: EvmContractAddress(asset.address)
|
|
1763
|
+
},
|
|
1764
|
+
name: asset.name,
|
|
1765
|
+
symbol: AssetSymbol(asset.symbol),
|
|
1766
|
+
decimals: AssetDecimals(asset.decimals),
|
|
1767
|
+
logo: TokenLogo.fromDto(asset.logo, baseUrl),
|
|
1768
|
+
logoDark: asset.logo_dark === void 0 ? null : TokenLogo.fromDto(asset.logo_dark, baseUrl)
|
|
1769
|
+
}));
|
|
1770
|
+
}
|
|
1363
1771
|
function assertSupportedSchemaVersion(version) {
|
|
1364
1772
|
if (version !== 1) {
|
|
1365
1773
|
throw new ValidationError(
|
|
@@ -1389,17 +1797,16 @@ var COINLIST_BASE_URL = "https://coinlist.co";
|
|
|
1389
1797
|
var OAUTH_PAGE_PATH = "/oauth/authorize";
|
|
1390
1798
|
var SUPPORT_NEW_TICKET_URL = "https://support.coinlist.co/support/tickets/new";
|
|
1391
1799
|
var VERIFY_IDENTITY_PATH = "/verify-identity";
|
|
1392
|
-
var VERIFY_IDENTITY_VERIFIED_PATH = "/verify-identity/identity_verified";
|
|
1393
|
-
var VERIFY_IDENTITY_PROOF_OF_ADDRESS_PATH = "/verify-identity/proof_of_address";
|
|
1394
|
-
var VERIFY_IDENTITY_SOURCE_OF_FUNDS_PATH = "/verify-identity/source_of_funds";
|
|
1395
1800
|
var VERIFY_IDENTITY_ACCREDITATION_PATH = "/verify-identity/accreditation_full";
|
|
1396
1801
|
var WALLET_PATH = "/wallet";
|
|
1397
1802
|
|
|
1398
1803
|
// src/shared/api/http-client.ts
|
|
1399
1804
|
var HttpClient = class {
|
|
1400
|
-
constructor(config, middleware = {}) {
|
|
1805
|
+
constructor(config, middleware = {}, logger = null, options = {}) {
|
|
1401
1806
|
this.config = config;
|
|
1402
1807
|
this.middleware = middleware;
|
|
1808
|
+
this.log = internalLogger(logger, "HTTP");
|
|
1809
|
+
this.makeRequestId = options.makeRequestId ?? defaultMakeRequestId;
|
|
1403
1810
|
}
|
|
1404
1811
|
async send(request) {
|
|
1405
1812
|
return this.runRequestWithAfterMiddleware(request);
|
|
@@ -1435,7 +1842,13 @@ var HttpClient = class {
|
|
|
1435
1842
|
return {
|
|
1436
1843
|
...request,
|
|
1437
1844
|
url,
|
|
1438
|
-
headers
|
|
1845
|
+
headers,
|
|
1846
|
+
// Only when absent: a retry or a post-renewal re-send arrives with the
|
|
1847
|
+
// first attempt's id already on it, and keeping it is the whole point.
|
|
1848
|
+
attributes: Attributes.getRequestId(request.attributes) === null ? Attributes.concat(
|
|
1849
|
+
request.attributes ?? Attributes.empty,
|
|
1850
|
+
Attributes.requestId(this.makeRequestId())
|
|
1851
|
+
) : request.attributes
|
|
1439
1852
|
};
|
|
1440
1853
|
}
|
|
1441
1854
|
/**
|
|
@@ -1459,14 +1872,93 @@ var HttpClient = class {
|
|
|
1459
1872
|
}
|
|
1460
1873
|
return request;
|
|
1461
1874
|
}
|
|
1462
|
-
|
|
1463
|
-
|
|
1875
|
+
/**
|
|
1876
|
+
* One physical attempt, logged as one line.
|
|
1877
|
+
*
|
|
1878
|
+
* A non-2xx is a `warn` rather than an `error` because the wire does not
|
|
1879
|
+
* know whether it is a failure: the retry middleware may turn a 503 into a
|
|
1880
|
+
* success, and the token registry reads a 404 as "not listed". The namespace
|
|
1881
|
+
* above decides, and logs the `error` when it does.
|
|
1882
|
+
*/
|
|
1883
|
+
async executeRequest(request) {
|
|
1884
|
+
const requestId2 = Attributes.getRequestId(request.attributes);
|
|
1885
|
+
const log = requestId2 === null ? this.log : this.log.child({ requestId: requestId2 });
|
|
1886
|
+
const attempt = Attributes.getRetryAttempt(request.attributes) + 1;
|
|
1887
|
+
const startedAt = Date.now();
|
|
1888
|
+
log.debug(() => ({
|
|
1889
|
+
msg: "request sent",
|
|
1890
|
+
fields: describeRequestUnredacted(request)
|
|
1891
|
+
}));
|
|
1892
|
+
try {
|
|
1893
|
+
const response = await makeRequest(request);
|
|
1894
|
+
const elapsed = Date.now() - startedAt;
|
|
1895
|
+
const outcome = () => ({
|
|
1896
|
+
msg: "request completed",
|
|
1897
|
+
fields: {
|
|
1898
|
+
...identifyRequest(request),
|
|
1899
|
+
"http.response.status_code": response.status,
|
|
1900
|
+
duration_ms: elapsed,
|
|
1901
|
+
attempt
|
|
1902
|
+
}
|
|
1903
|
+
});
|
|
1904
|
+
if (response.status >= 200 && response.status < 300) {
|
|
1905
|
+
log.info(outcome);
|
|
1906
|
+
} else {
|
|
1907
|
+
log.warn(outcome);
|
|
1908
|
+
}
|
|
1909
|
+
log.debug(() => ({
|
|
1910
|
+
msg: "response received",
|
|
1911
|
+
fields: { body: response.body }
|
|
1912
|
+
}));
|
|
1913
|
+
return requestId2 === null ? response : { ...response, requestId: requestId2 };
|
|
1914
|
+
} catch (error) {
|
|
1915
|
+
const elapsed = Date.now() - startedAt;
|
|
1916
|
+
log.warning(
|
|
1917
|
+
() => ({
|
|
1918
|
+
msg: "request threw",
|
|
1919
|
+
fields: {
|
|
1920
|
+
...identifyRequest(request),
|
|
1921
|
+
duration_ms: elapsed,
|
|
1922
|
+
attempt
|
|
1923
|
+
}
|
|
1924
|
+
}),
|
|
1925
|
+
error
|
|
1926
|
+
);
|
|
1927
|
+
throw error;
|
|
1928
|
+
}
|
|
1464
1929
|
}
|
|
1465
1930
|
};
|
|
1931
|
+
function identifyRequest(request) {
|
|
1932
|
+
const { host, path } = splitUrl(request.url);
|
|
1933
|
+
return {
|
|
1934
|
+
"http.request.method": request.method,
|
|
1935
|
+
"server.address": host,
|
|
1936
|
+
"url.path": path
|
|
1937
|
+
};
|
|
1938
|
+
}
|
|
1939
|
+
function splitUrl(url) {
|
|
1940
|
+
try {
|
|
1941
|
+
const parsed = new URL(url);
|
|
1942
|
+
return { host: parsed.host, path: parsed.pathname };
|
|
1943
|
+
} catch (_) {
|
|
1944
|
+
return { host: null, path: url };
|
|
1945
|
+
}
|
|
1946
|
+
}
|
|
1947
|
+
function defaultMakeRequestId() {
|
|
1948
|
+
return Math.random().toString(36).slice(2, 10).padEnd(8, "0");
|
|
1949
|
+
}
|
|
1950
|
+
function describeRequestUnredacted(request) {
|
|
1951
|
+
return {
|
|
1952
|
+
"http.request.method": request.method,
|
|
1953
|
+
"url.full": buildUrlWithQueryParams(request.url, request.queryParams),
|
|
1954
|
+
headers: request.headers,
|
|
1955
|
+
...request.method === "POST" ? { body: request.body } : {}
|
|
1956
|
+
};
|
|
1957
|
+
}
|
|
1466
1958
|
|
|
1467
1959
|
// src/shared/api/nabu/tokens.ts
|
|
1468
|
-
function createNabuApiClient(baseUrl) {
|
|
1469
|
-
return new HttpClient({ baseUrl });
|
|
1960
|
+
function createNabuApiClient(baseUrl, logger = null) {
|
|
1961
|
+
return new HttpClient({ baseUrl }, {}, logger);
|
|
1470
1962
|
}
|
|
1471
1963
|
async function fetchTokenMetadata(client, token) {
|
|
1472
1964
|
const address = checksummed(token.address);
|
|
@@ -1516,6 +2008,29 @@ async function fetchTokensMetadata(client, chain) {
|
|
|
1516
2008
|
}
|
|
1517
2009
|
return TokenMetadata.fromChainAssetsDto(response.body, client.config.baseUrl);
|
|
1518
2010
|
}
|
|
2011
|
+
async function fetchAllTokensMetadata(client) {
|
|
2012
|
+
let response;
|
|
2013
|
+
try {
|
|
2014
|
+
response = await client.send({
|
|
2015
|
+
method: "GET",
|
|
2016
|
+
url: `/assets.json`
|
|
2017
|
+
});
|
|
2018
|
+
} catch (error) {
|
|
2019
|
+
if (isRegistryHtmlFallback(error)) {
|
|
2020
|
+
throw new ValidationError(
|
|
2021
|
+
"Token registry returned non-JSON for the complete snapshot"
|
|
2022
|
+
);
|
|
2023
|
+
}
|
|
2024
|
+
throw error;
|
|
2025
|
+
}
|
|
2026
|
+
assertOk(response);
|
|
2027
|
+
if (response.body === null) {
|
|
2028
|
+
throw new ValidationError(
|
|
2029
|
+
"Token registry returned an empty complete snapshot"
|
|
2030
|
+
);
|
|
2031
|
+
}
|
|
2032
|
+
return TokenMetadata.fromRegistryDto(response.body, client.config.baseUrl);
|
|
2033
|
+
}
|
|
1519
2034
|
function isRegistryHtmlFallback(error) {
|
|
1520
2035
|
return error instanceof HttpError && error.response.status >= 200 && error.response.status < 300;
|
|
1521
2036
|
}
|
|
@@ -1539,14 +2054,23 @@ var TokensNamespaceImpl = class {
|
|
|
1539
2054
|
* registry is unauthenticated and on its own host, so the frontline sender
|
|
1540
2055
|
* and the auth check would both be dead weight here.
|
|
1541
2056
|
*/
|
|
1542
|
-
constructor(baseUrl) {
|
|
1543
|
-
this.api = createNabuApiClient(baseUrl);
|
|
2057
|
+
constructor(baseUrl, logger = null) {
|
|
2058
|
+
this.api = createNabuApiClient(baseUrl, logger);
|
|
2059
|
+
this.log = internalLogger(logger, "TOKENS");
|
|
1544
2060
|
}
|
|
1545
2061
|
get(token) {
|
|
1546
|
-
return
|
|
2062
|
+
return this.log.wrap(
|
|
2063
|
+
"get",
|
|
2064
|
+
token,
|
|
2065
|
+
() => fetchTokenMetadata(this.api, token)
|
|
2066
|
+
);
|
|
1547
2067
|
}
|
|
1548
2068
|
list(chain) {
|
|
1549
|
-
return
|
|
2069
|
+
return this.log.wrap(
|
|
2070
|
+
"list",
|
|
2071
|
+
chain,
|
|
2072
|
+
() => chain === void 0 ? fetchAllTokensMetadata(this.api) : fetchTokensMetadata(this.api, chain)
|
|
2073
|
+
);
|
|
1550
2074
|
}
|
|
1551
2075
|
};
|
|
1552
2076
|
|
|
@@ -1652,33 +2176,42 @@ async function removeOptionAddress(api, offerId, addressId) {
|
|
|
1652
2176
|
var WalletsNamespaceImpl = class {
|
|
1653
2177
|
constructor(ctx) {
|
|
1654
2178
|
this.ctx = ctx;
|
|
2179
|
+
this.log = internalLogger(ctx.logger, "WALLETS");
|
|
1655
2180
|
}
|
|
1656
2181
|
async createOwnershipChallenge(params) {
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
2182
|
+
return this.log.wrap("createOwnershipChallenge", params, async () => {
|
|
2183
|
+
await this.ctx.ensureUserAuthenticated();
|
|
2184
|
+
return createWalletOwnershipChallenge(
|
|
2185
|
+
this.ctx.api,
|
|
2186
|
+
params
|
|
2187
|
+
);
|
|
2188
|
+
});
|
|
1662
2189
|
}
|
|
1663
2190
|
async connectExternal(params) {
|
|
1664
|
-
|
|
1665
|
-
|
|
2191
|
+
return this.log.wrap("connectExternal", params, async () => {
|
|
2192
|
+
await this.ctx.ensureUserAuthenticated();
|
|
2193
|
+
return connectExternalWallet(this.ctx.api, params);
|
|
2194
|
+
});
|
|
1666
2195
|
}
|
|
1667
2196
|
async list(params) {
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
2197
|
+
return this.log.wrap("list", params, async () => {
|
|
2198
|
+
await this.ctx.ensureUserAuthenticated();
|
|
2199
|
+
return listOptionAddresses(
|
|
2200
|
+
this.ctx.api,
|
|
2201
|
+
params.offerId,
|
|
2202
|
+
params.offerOptionId
|
|
2203
|
+
);
|
|
2204
|
+
});
|
|
1674
2205
|
}
|
|
1675
2206
|
async remove(params) {
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
2207
|
+
return this.log.wrap("remove", params, async () => {
|
|
2208
|
+
await this.ctx.ensureUserAuthenticated();
|
|
2209
|
+
return removeOptionAddress(
|
|
2210
|
+
this.ctx.api,
|
|
2211
|
+
params.offerId,
|
|
2212
|
+
params.addressId
|
|
2213
|
+
);
|
|
2214
|
+
});
|
|
1682
2215
|
}
|
|
1683
2216
|
};
|
|
1684
2217
|
|
|
@@ -1740,20 +2273,21 @@ export {
|
|
|
1740
2273
|
OAUTH_PAGE_PATH,
|
|
1741
2274
|
SUPPORT_NEW_TICKET_URL,
|
|
1742
2275
|
VERIFY_IDENTITY_PATH,
|
|
1743
|
-
VERIFY_IDENTITY_VERIFIED_PATH,
|
|
1744
|
-
VERIFY_IDENTITY_PROOF_OF_ADDRESS_PATH,
|
|
1745
|
-
VERIFY_IDENTITY_SOURCE_OF_FUNDS_PATH,
|
|
1746
2276
|
VERIFY_IDENTITY_ACCREDITATION_PATH,
|
|
1747
2277
|
WALLET_PATH,
|
|
1748
2278
|
Attributes,
|
|
1749
2279
|
HttpError,
|
|
1750
2280
|
apiErrorCode,
|
|
1751
2281
|
Request,
|
|
1752
|
-
HttpClient,
|
|
1753
|
-
fetchAllPages,
|
|
1754
2282
|
NotImplementedError,
|
|
1755
2283
|
NotAuthenticatedError,
|
|
1756
2284
|
ValidationError,
|
|
2285
|
+
InvariantError,
|
|
2286
|
+
MathError,
|
|
2287
|
+
describeErrorUnredacted,
|
|
2288
|
+
internalLogger,
|
|
2289
|
+
HttpClient,
|
|
2290
|
+
fetchAllPages,
|
|
1757
2291
|
ETHEREUM_CHAINS,
|
|
1758
2292
|
EthereumChain,
|
|
1759
2293
|
SOLANA_CHAINS,
|
|
@@ -1768,6 +2302,7 @@ export {
|
|
|
1768
2302
|
DecimalString,
|
|
1769
2303
|
MAX_UINT_256,
|
|
1770
2304
|
assertUint256,
|
|
2305
|
+
parseUint256,
|
|
1771
2306
|
BlockchainAmount,
|
|
1772
2307
|
AssetSymbol,
|
|
1773
2308
|
StablecoinSymbol,
|
|
@@ -1810,6 +2345,7 @@ export {
|
|
|
1810
2345
|
OfferId,
|
|
1811
2346
|
OfferSlug,
|
|
1812
2347
|
Offer,
|
|
2348
|
+
OfferToken,
|
|
1813
2349
|
OfferOptionId,
|
|
1814
2350
|
OfferOptionSlug,
|
|
1815
2351
|
OfferDetail,
|
|
@@ -1818,7 +2354,6 @@ export {
|
|
|
1818
2354
|
Link,
|
|
1819
2355
|
TermItem,
|
|
1820
2356
|
Milestone,
|
|
1821
|
-
OfferToken,
|
|
1822
2357
|
ParticipationId,
|
|
1823
2358
|
Blockchain,
|
|
1824
2359
|
WalletAddress,
|
|
@@ -1829,7 +2364,8 @@ export {
|
|
|
1829
2364
|
Ticker,
|
|
1830
2365
|
OndoTradingStatus,
|
|
1831
2366
|
OndoQuote,
|
|
1832
|
-
|
|
2367
|
+
OndoBuyTransaction,
|
|
2368
|
+
OndoSellTransaction,
|
|
1833
2369
|
OndoNamespaceImpl,
|
|
1834
2370
|
SuperstateSwapNamespaceImpl,
|
|
1835
2371
|
fetchOffers,
|
|
@@ -1860,4 +2396,4 @@ export {
|
|
|
1860
2396
|
OAuthRefreshToken,
|
|
1861
2397
|
OAuthSession
|
|
1862
2398
|
};
|
|
1863
|
-
//# sourceMappingURL=chunk-
|
|
2399
|
+
//# sourceMappingURL=chunk-7CTH4KPU.js.map
|