@minswap/sdk-v2 1.0.0 → 1.0.1
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/CHANGELOG.md +19 -0
- package/README.md +2 -2
- package/dist/index.cjs +355 -481
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +132 -289
- package/dist/index.d.ts +132 -289
- package/dist/index.js +354 -478
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
package/dist/index.cjs
CHANGED
|
@@ -190,6 +190,61 @@ var AppApiClient = class {
|
|
|
190
190
|
}
|
|
191
191
|
};
|
|
192
192
|
|
|
193
|
+
// src/client/config.ts
|
|
194
|
+
var DEFAULT_ENDPOINTS = {
|
|
195
|
+
mainnet: {
|
|
196
|
+
appApiUrl: "https://api-internal.minswap.org",
|
|
197
|
+
aggregatorApiUrl: "https://agg-api.minswap.org",
|
|
198
|
+
keyAppApiUrl: "https://k-app-monorepo-mainnet-prod.minswap.org/graphql"
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
202
|
+
var DEFAULT_RETRY = {
|
|
203
|
+
retries: 2,
|
|
204
|
+
baseDelayMs: 300
|
|
205
|
+
};
|
|
206
|
+
function invalid(param, reason) {
|
|
207
|
+
throw new MinswapError(`Invalid config: ${param} ${reason}`, "INVALID_PARAMS" /* INVALID_PARAMS */, {
|
|
208
|
+
param,
|
|
209
|
+
reason
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
function resolveConfig(config = {}) {
|
|
213
|
+
const network = config.network ?? "mainnet";
|
|
214
|
+
const fetchImpl = config.fetch ?? globalThis.fetch;
|
|
215
|
+
if (typeof fetchImpl !== "function") {
|
|
216
|
+
invalid(
|
|
217
|
+
"fetch",
|
|
218
|
+
"is not available on globalThis; pass an implementation via `new MinswapSdk({ fetch })`"
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
const timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
222
|
+
if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
|
|
223
|
+
invalid("timeoutMs", "must be a positive finite number");
|
|
224
|
+
}
|
|
225
|
+
const retries = config.retry?.retries ?? DEFAULT_RETRY.retries;
|
|
226
|
+
if (!Number.isInteger(retries) || retries < 0) {
|
|
227
|
+
invalid("retry.retries", "must be a non-negative integer");
|
|
228
|
+
}
|
|
229
|
+
const baseDelayMs = config.retry?.baseDelayMs ?? DEFAULT_RETRY.baseDelayMs;
|
|
230
|
+
if (!Number.isFinite(baseDelayMs) || baseDelayMs < 0) {
|
|
231
|
+
invalid("retry.baseDelayMs", "must be a non-negative finite number");
|
|
232
|
+
}
|
|
233
|
+
return {
|
|
234
|
+
network,
|
|
235
|
+
currency: config.currency ?? "USD",
|
|
236
|
+
apiKey: config.apiKey,
|
|
237
|
+
endpoints: {
|
|
238
|
+
...DEFAULT_ENDPOINTS[network],
|
|
239
|
+
...config.endpoints
|
|
240
|
+
},
|
|
241
|
+
fetch: fetchImpl,
|
|
242
|
+
timeoutMs,
|
|
243
|
+
retry: { retries, baseDelayMs },
|
|
244
|
+
rpcProvider: config.rpcProvider
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
|
|
193
248
|
// src/client/http.ts
|
|
194
249
|
var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
195
250
|
function isRetryable(error) {
|
|
@@ -379,8 +434,6 @@ async function readBody(response) {
|
|
|
379
434
|
function truncate(value, max = 300) {
|
|
380
435
|
return value.length <= max ? value : `${value.slice(0, max)}\u2026`;
|
|
381
436
|
}
|
|
382
|
-
|
|
383
|
-
// src/client/app-graphql-client.ts
|
|
384
437
|
var graphqlEnvelope = zod.z.object({
|
|
385
438
|
data: zod.z.unknown().nullish(),
|
|
386
439
|
errors: zod.z.array(
|
|
@@ -390,137 +443,6 @@ var graphqlEnvelope = zod.z.object({
|
|
|
390
443
|
})
|
|
391
444
|
).nullish()
|
|
392
445
|
});
|
|
393
|
-
var AppGraphqlClient = class {
|
|
394
|
-
constructor(http, config) {
|
|
395
|
-
this.http = http;
|
|
396
|
-
this.config = config;
|
|
397
|
-
}
|
|
398
|
-
http;
|
|
399
|
-
config;
|
|
400
|
-
async execute(operation) {
|
|
401
|
-
const endpoint = `GraphQL ${operation.operation}`;
|
|
402
|
-
const response = await this.http.request({
|
|
403
|
-
url: this.config.endpoints.appGraphqlUrl,
|
|
404
|
-
method: "POST",
|
|
405
|
-
endpoint,
|
|
406
|
-
body: {
|
|
407
|
-
// No `operationName`: each document defines exactly one operation, so
|
|
408
|
-
// the server runs it without one. Sending the field name would have to
|
|
409
|
-
// match the document's operation name exactly — a needless coupling.
|
|
410
|
-
query: operation.document,
|
|
411
|
-
variables: operation.variables ?? {}
|
|
412
|
-
},
|
|
413
|
-
schema: graphqlEnvelope,
|
|
414
|
-
// Resolver errors can come back with a 400/500 status; decode the body
|
|
415
|
-
// anyway so the GraphQL `errors` array is not lost as an opaque API error.
|
|
416
|
-
parseErrorBody: true
|
|
417
|
-
});
|
|
418
|
-
if (response.errors && response.errors.length > 0) {
|
|
419
|
-
throw new MinswapError(
|
|
420
|
-
`${operation.operation} failed: ${response.errors.map((e) => e.message).join("; ")}`,
|
|
421
|
-
"GRAPHQL_ERROR" /* GRAPHQL_ERROR */,
|
|
422
|
-
{
|
|
423
|
-
operation: operation.operation,
|
|
424
|
-
errors: response.errors.map((e) => ({
|
|
425
|
-
message: e.message,
|
|
426
|
-
path: e.path ?? void 0
|
|
427
|
-
}))
|
|
428
|
-
}
|
|
429
|
-
);
|
|
430
|
-
}
|
|
431
|
-
const data = response.data;
|
|
432
|
-
if (data === null || data === void 0) {
|
|
433
|
-
throw new MinswapError(
|
|
434
|
-
`${operation.operation} returned no data and no errors`,
|
|
435
|
-
"PARSE_ERROR" /* PARSE_ERROR */,
|
|
436
|
-
{
|
|
437
|
-
endpoint,
|
|
438
|
-
issues: [{ path: "data", message: "Expected an object, received null" }]
|
|
439
|
-
}
|
|
440
|
-
);
|
|
441
|
-
}
|
|
442
|
-
const root = data;
|
|
443
|
-
const keys = Object.keys(root);
|
|
444
|
-
if (keys.length !== 1) {
|
|
445
|
-
throw new MinswapError(
|
|
446
|
-
`${operation.operation} expected a single root field, got [${keys.join(", ")}]`,
|
|
447
|
-
"PARSE_ERROR" /* PARSE_ERROR */,
|
|
448
|
-
{
|
|
449
|
-
endpoint,
|
|
450
|
-
issues: [
|
|
451
|
-
{ path: "data", message: `expected exactly one root field, got ${keys.length}` }
|
|
452
|
-
]
|
|
453
|
-
}
|
|
454
|
-
);
|
|
455
|
-
}
|
|
456
|
-
return parseOrThrow(operation.schema, root[keys[0]], endpoint);
|
|
457
|
-
}
|
|
458
|
-
};
|
|
459
|
-
|
|
460
|
-
// src/client/config.ts
|
|
461
|
-
var DEFAULT_ENDPOINTS = {
|
|
462
|
-
mainnet: {
|
|
463
|
-
appApiUrl: "https://api-internal.minswap.org",
|
|
464
|
-
aggregatorApiUrl: "https://agg-api.minswap.org",
|
|
465
|
-
keyAppApiUrl: "https://k-app-monorepo-mainnet-prod.minswap.org/graphql",
|
|
466
|
-
appGraphqlUrl: "https://app-monorepo-mainnet-prod.minswap.org/graphql"
|
|
467
|
-
}
|
|
468
|
-
};
|
|
469
|
-
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
470
|
-
var DEFAULT_RETRY = {
|
|
471
|
-
retries: 2,
|
|
472
|
-
baseDelayMs: 300
|
|
473
|
-
};
|
|
474
|
-
function invalid(param, reason) {
|
|
475
|
-
throw new MinswapError(`Invalid config: ${param} ${reason}`, "INVALID_PARAMS" /* INVALID_PARAMS */, {
|
|
476
|
-
param,
|
|
477
|
-
reason
|
|
478
|
-
});
|
|
479
|
-
}
|
|
480
|
-
function resolveConfig(config = {}) {
|
|
481
|
-
const network = config.network ?? "mainnet";
|
|
482
|
-
const fetchImpl = config.fetch ?? globalThis.fetch;
|
|
483
|
-
if (typeof fetchImpl !== "function") {
|
|
484
|
-
invalid(
|
|
485
|
-
"fetch",
|
|
486
|
-
"is not available on globalThis; pass an implementation via `new MinswapSdk({ fetch })`"
|
|
487
|
-
);
|
|
488
|
-
}
|
|
489
|
-
const timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
490
|
-
if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
|
|
491
|
-
invalid("timeoutMs", "must be a positive finite number");
|
|
492
|
-
}
|
|
493
|
-
const retries = config.retry?.retries ?? DEFAULT_RETRY.retries;
|
|
494
|
-
if (!Number.isInteger(retries) || retries < 0) {
|
|
495
|
-
invalid("retry.retries", "must be a non-negative integer");
|
|
496
|
-
}
|
|
497
|
-
const baseDelayMs = config.retry?.baseDelayMs ?? DEFAULT_RETRY.baseDelayMs;
|
|
498
|
-
if (!Number.isFinite(baseDelayMs) || baseDelayMs < 0) {
|
|
499
|
-
invalid("retry.baseDelayMs", "must be a non-negative finite number");
|
|
500
|
-
}
|
|
501
|
-
return {
|
|
502
|
-
network,
|
|
503
|
-
currency: config.currency ?? "USD",
|
|
504
|
-
apiKey: config.apiKey,
|
|
505
|
-
endpoints: {
|
|
506
|
-
...DEFAULT_ENDPOINTS[network],
|
|
507
|
-
...config.endpoints
|
|
508
|
-
},
|
|
509
|
-
fetch: fetchImpl,
|
|
510
|
-
timeoutMs,
|
|
511
|
-
retry: { retries, baseDelayMs },
|
|
512
|
-
rpcProvider: config.rpcProvider
|
|
513
|
-
};
|
|
514
|
-
}
|
|
515
|
-
var graphqlEnvelope2 = zod.z.object({
|
|
516
|
-
data: zod.z.unknown().nullish(),
|
|
517
|
-
errors: zod.z.array(
|
|
518
|
-
zod.z.object({
|
|
519
|
-
message: zod.z.string(),
|
|
520
|
-
path: zod.z.array(zod.z.union([zod.z.string(), zod.z.number()])).nullish()
|
|
521
|
-
})
|
|
522
|
-
).nullish()
|
|
523
|
-
});
|
|
524
446
|
var KeyAppApiClient = class {
|
|
525
447
|
constructor(http, config) {
|
|
526
448
|
this.http = http;
|
|
@@ -543,7 +465,7 @@ var KeyAppApiClient = class {
|
|
|
543
465
|
query: operation.document,
|
|
544
466
|
variables: operation.variables ?? {}
|
|
545
467
|
},
|
|
546
|
-
schema:
|
|
468
|
+
schema: graphqlEnvelope,
|
|
547
469
|
// This host returns resolver errors with a 400/500 status; decode the
|
|
548
470
|
// body anyway so the GraphQL `errors` array is not lost.
|
|
549
471
|
parseErrorBody: true
|
|
@@ -623,115 +545,6 @@ function inputAssetToCoinId(asset2) {
|
|
|
623
545
|
}
|
|
624
546
|
return asset2.tokenName === "" ? asset2.currencySymbol : `${asset2.currencySymbol}.${asset2.tokenName}`;
|
|
625
547
|
}
|
|
626
|
-
function arrayOf(schema) {
|
|
627
|
-
return zod.z.array(schema).nullish().transform((value) => value ?? []);
|
|
628
|
-
}
|
|
629
|
-
var zeroableNumber = zod.z.number().nullish().transform((value) => value ?? 0);
|
|
630
|
-
var coinBasicInfoSchema = zod.z.object({
|
|
631
|
-
coin_type: zod.z.string().nullish(),
|
|
632
|
-
symbol: zod.z.string(),
|
|
633
|
-
decimals: zod.z.number(),
|
|
634
|
-
icon_url: zod.z.string(),
|
|
635
|
-
verified: zod.z.boolean()
|
|
636
|
-
}).transform((c) => ({
|
|
637
|
-
coinId: c.coin_type ?? null,
|
|
638
|
-
symbol: c.symbol,
|
|
639
|
-
decimals: c.decimals,
|
|
640
|
-
iconUrl: c.icon_url,
|
|
641
|
-
verified: c.verified
|
|
642
|
-
}));
|
|
643
|
-
var coinAmountInfoSchema = zod.z.object({
|
|
644
|
-
coin_type: zod.z.string().nullish(),
|
|
645
|
-
symbol: zod.z.string(),
|
|
646
|
-
decimals: zod.z.number(),
|
|
647
|
-
icon_url: zod.z.string(),
|
|
648
|
-
verified: zod.z.boolean(),
|
|
649
|
-
amount: zod.z.number(),
|
|
650
|
-
usd_value: zod.z.number()
|
|
651
|
-
}).transform((c) => ({
|
|
652
|
-
coinId: c.coin_type ?? null,
|
|
653
|
-
symbol: c.symbol,
|
|
654
|
-
decimals: c.decimals,
|
|
655
|
-
iconUrl: c.icon_url,
|
|
656
|
-
verified: c.verified,
|
|
657
|
-
amount: c.amount,
|
|
658
|
-
usdValue: c.usd_value
|
|
659
|
-
}));
|
|
660
|
-
var poolCoinSchema = zod.z.object({
|
|
661
|
-
coin_type: zod.z.string().nullish(),
|
|
662
|
-
symbol: zod.z.string(),
|
|
663
|
-
decimals: zod.z.number(),
|
|
664
|
-
icon_url: zod.z.string(),
|
|
665
|
-
verified: zod.z.boolean(),
|
|
666
|
-
category: zod.z.string().nullish()
|
|
667
|
-
}).transform((c) => ({
|
|
668
|
-
coinId: c.coin_type ?? null,
|
|
669
|
-
symbol: c.symbol,
|
|
670
|
-
decimals: c.decimals,
|
|
671
|
-
iconUrl: c.icon_url,
|
|
672
|
-
verified: c.verified,
|
|
673
|
-
/** Free-form; not constrained to the `categoryGroup` filter values. */
|
|
674
|
-
category: c.category ?? null
|
|
675
|
-
}));
|
|
676
|
-
var poolRewardSchema = zod.z.object({
|
|
677
|
-
coin_type: zod.z.string().nullish(),
|
|
678
|
-
symbol: zod.z.string(),
|
|
679
|
-
decimals: zod.z.number(),
|
|
680
|
-
icon_url: zod.z.string(),
|
|
681
|
-
verified: zod.z.boolean(),
|
|
682
|
-
daily_amount: zod.z.number(),
|
|
683
|
-
daily_amount_usd: zod.z.number(),
|
|
684
|
-
apr: zod.z.number()
|
|
685
|
-
}).transform((r) => ({
|
|
686
|
-
coinId: r.coin_type ?? null,
|
|
687
|
-
symbol: r.symbol,
|
|
688
|
-
decimals: r.decimals,
|
|
689
|
-
iconUrl: r.icon_url,
|
|
690
|
-
verified: r.verified,
|
|
691
|
-
dailyAmount: r.daily_amount,
|
|
692
|
-
dailyAmountUsd: r.daily_amount_usd,
|
|
693
|
-
apr: r.apr
|
|
694
|
-
}));
|
|
695
|
-
var poolFeeSchema = zod.z.object({ fee_raw: zod.z.number(), fee_usd: zod.z.number() }).transform((f) => ({ feeRaw: f.fee_raw, feeUsd: f.fee_usd }));
|
|
696
|
-
var coinCandleSchema = zod.z.object({
|
|
697
|
-
t: zod.z.string(),
|
|
698
|
-
ohlcv: zod.z.array(zod.z.number()).nullish()
|
|
699
|
-
}).transform(({ t, ohlcv }) => {
|
|
700
|
-
const [open = 0, high = 0, low = 0, close = 0, volume = 0] = ohlcv ?? [];
|
|
701
|
-
return { timestamp: Date.parse(t), open, high, low, close, volume };
|
|
702
|
-
});
|
|
703
|
-
var poolCandleSchema = zod.z.array(zod.z.number()).transform(([seconds = 0, open = 0, high = 0, low = 0, close = 0, volume = 0]) => ({
|
|
704
|
-
timestamp: seconds * 1e3,
|
|
705
|
-
open,
|
|
706
|
-
high,
|
|
707
|
-
low,
|
|
708
|
-
close,
|
|
709
|
-
volume
|
|
710
|
-
}));
|
|
711
|
-
var VALID_BUCKET_MINUTES = [
|
|
712
|
-
1,
|
|
713
|
-
5,
|
|
714
|
-
15,
|
|
715
|
-
30,
|
|
716
|
-
60,
|
|
717
|
-
120,
|
|
718
|
-
240,
|
|
719
|
-
360,
|
|
720
|
-
720,
|
|
721
|
-
1440,
|
|
722
|
-
5760,
|
|
723
|
-
10080,
|
|
724
|
-
43200
|
|
725
|
-
];
|
|
726
|
-
function assertBucket(bucketMinutes) {
|
|
727
|
-
if (!VALID_BUCKET_MINUTES.includes(bucketMinutes)) {
|
|
728
|
-
throw new MinswapError(
|
|
729
|
-
`bucketMinutes must be one of ${VALID_BUCKET_MINUTES.join(", ")}; received ${bucketMinutes}`,
|
|
730
|
-
"INVALID_PARAMS" /* INVALID_PARAMS */,
|
|
731
|
-
{ param: "bucketMinutes", reason: "unsupported bucket size" }
|
|
732
|
-
);
|
|
733
|
-
}
|
|
734
|
-
}
|
|
735
548
|
|
|
736
549
|
// src/modules/aggregator-module.ts
|
|
737
550
|
var AGGREGATOR_PROTOCOLS = [
|
|
@@ -876,35 +689,6 @@ var estimateSchema = zod.z.object({
|
|
|
876
689
|
}));
|
|
877
690
|
var buildTxResponseSchema = zod.z.object({ cbor: zod.z.string() }).transform((r) => ({ cbor: r.cbor }));
|
|
878
691
|
var submitResponseSchema = zod.z.object({ tx_id: zod.z.string() }).transform((r) => ({ txId: r.tx_id }));
|
|
879
|
-
var pendingOrderSchema = zod.z.object({
|
|
880
|
-
owner_address: zod.z.string(),
|
|
881
|
-
protocol: zod.z.string(),
|
|
882
|
-
token_in: assetSchema,
|
|
883
|
-
token_out: assetSchema,
|
|
884
|
-
amount_in: zod.z.string(),
|
|
885
|
-
min_amount_out: zod.z.string(),
|
|
886
|
-
created_at: zod.z.number(),
|
|
887
|
-
tx_in: zod.z.string(),
|
|
888
|
-
dex_fee: zod.z.string(),
|
|
889
|
-
deposit: zod.z.string()
|
|
890
|
-
}).transform((o) => ({
|
|
891
|
-
ownerAddress: o.owner_address,
|
|
892
|
-
protocol: o.protocol,
|
|
893
|
-
tokenIn: o.token_in,
|
|
894
|
-
tokenOut: o.token_out,
|
|
895
|
-
amountIn: o.amount_in,
|
|
896
|
-
minAmountOut: o.min_amount_out,
|
|
897
|
-
/** Epoch seconds. */
|
|
898
|
-
createdAt: o.created_at,
|
|
899
|
-
/** The order's UTxO reference, `txHash#index` — pass to {@link AggregatorModule.cancelOrders}. */
|
|
900
|
-
txIn: o.tx_in,
|
|
901
|
-
dexFee: o.dex_fee,
|
|
902
|
-
deposit: o.deposit
|
|
903
|
-
}));
|
|
904
|
-
var pendingOrdersSchema = zod.z.object({
|
|
905
|
-
orders: arrayOf(pendingOrderSchema),
|
|
906
|
-
amount_in_decimal: zod.z.boolean()
|
|
907
|
-
}).transform((r) => r.orders);
|
|
908
692
|
function estimateBody(params) {
|
|
909
693
|
return dropUndefined({
|
|
910
694
|
amount: params.amount,
|
|
@@ -1005,23 +789,6 @@ var AggregatorModule = class {
|
|
|
1005
789
|
schema: buildTxResponseSchema
|
|
1006
790
|
});
|
|
1007
791
|
}
|
|
1008
|
-
/**
|
|
1009
|
-
* List an address's still-open aggregator orders.
|
|
1010
|
-
*
|
|
1011
|
-
* Only orders whose UTxO is still unspent are returned, so this is genuinely
|
|
1012
|
-
* "open orders" rather than history. For full history including filled and
|
|
1013
|
-
* cancelled orders, use {@link OrderModule.getHistory}.
|
|
1014
|
-
*/
|
|
1015
|
-
async getPendingOrders(ownerAddress, options = {}) {
|
|
1016
|
-
return this.sdk.clients.aggregatorApi.get({
|
|
1017
|
-
path: "/aggregator/pending-orders",
|
|
1018
|
-
query: {
|
|
1019
|
-
owner_address: ownerAddress,
|
|
1020
|
-
amount_in_decimal: options.amountInDecimal
|
|
1021
|
-
},
|
|
1022
|
-
schema: pendingOrdersSchema
|
|
1023
|
-
});
|
|
1024
|
-
}
|
|
1025
792
|
};
|
|
1026
793
|
function dropUndefined(obj) {
|
|
1027
794
|
for (const key of Object.keys(obj)) {
|
|
@@ -1112,6 +879,115 @@ async function collect(fetchPage, options = {}) {
|
|
|
1112
879
|
}
|
|
1113
880
|
return items;
|
|
1114
881
|
}
|
|
882
|
+
function arrayOf(schema) {
|
|
883
|
+
return zod.z.array(schema).nullish().transform((value) => value ?? []);
|
|
884
|
+
}
|
|
885
|
+
var zeroableNumber = zod.z.number().nullish().transform((value) => value ?? 0);
|
|
886
|
+
var coinBasicInfoSchema = zod.z.object({
|
|
887
|
+
coin_type: zod.z.string().nullish(),
|
|
888
|
+
symbol: zod.z.string(),
|
|
889
|
+
decimals: zod.z.number(),
|
|
890
|
+
icon_url: zod.z.string(),
|
|
891
|
+
verified: zod.z.boolean()
|
|
892
|
+
}).transform((c) => ({
|
|
893
|
+
coinId: c.coin_type ?? null,
|
|
894
|
+
symbol: c.symbol,
|
|
895
|
+
decimals: c.decimals,
|
|
896
|
+
iconUrl: c.icon_url,
|
|
897
|
+
verified: c.verified
|
|
898
|
+
}));
|
|
899
|
+
var coinAmountInfoSchema = zod.z.object({
|
|
900
|
+
coin_type: zod.z.string().nullish(),
|
|
901
|
+
symbol: zod.z.string(),
|
|
902
|
+
decimals: zod.z.number(),
|
|
903
|
+
icon_url: zod.z.string(),
|
|
904
|
+
verified: zod.z.boolean(),
|
|
905
|
+
amount: zod.z.number(),
|
|
906
|
+
usd_value: zod.z.number()
|
|
907
|
+
}).transform((c) => ({
|
|
908
|
+
coinId: c.coin_type ?? null,
|
|
909
|
+
symbol: c.symbol,
|
|
910
|
+
decimals: c.decimals,
|
|
911
|
+
iconUrl: c.icon_url,
|
|
912
|
+
verified: c.verified,
|
|
913
|
+
amount: c.amount,
|
|
914
|
+
usdValue: c.usd_value
|
|
915
|
+
}));
|
|
916
|
+
var poolCoinSchema = zod.z.object({
|
|
917
|
+
coin_type: zod.z.string().nullish(),
|
|
918
|
+
symbol: zod.z.string(),
|
|
919
|
+
decimals: zod.z.number(),
|
|
920
|
+
icon_url: zod.z.string(),
|
|
921
|
+
verified: zod.z.boolean(),
|
|
922
|
+
category: zod.z.string().nullish()
|
|
923
|
+
}).transform((c) => ({
|
|
924
|
+
coinId: c.coin_type ?? null,
|
|
925
|
+
symbol: c.symbol,
|
|
926
|
+
decimals: c.decimals,
|
|
927
|
+
iconUrl: c.icon_url,
|
|
928
|
+
verified: c.verified,
|
|
929
|
+
/** Free-form; not constrained to the `categoryGroup` filter values. */
|
|
930
|
+
category: c.category ?? null
|
|
931
|
+
}));
|
|
932
|
+
var poolRewardSchema = zod.z.object({
|
|
933
|
+
coin_type: zod.z.string().nullish(),
|
|
934
|
+
symbol: zod.z.string(),
|
|
935
|
+
decimals: zod.z.number(),
|
|
936
|
+
icon_url: zod.z.string(),
|
|
937
|
+
verified: zod.z.boolean(),
|
|
938
|
+
daily_amount: zod.z.number(),
|
|
939
|
+
daily_amount_usd: zod.z.number(),
|
|
940
|
+
apr: zod.z.number()
|
|
941
|
+
}).transform((r) => ({
|
|
942
|
+
coinId: r.coin_type ?? null,
|
|
943
|
+
symbol: r.symbol,
|
|
944
|
+
decimals: r.decimals,
|
|
945
|
+
iconUrl: r.icon_url,
|
|
946
|
+
verified: r.verified,
|
|
947
|
+
dailyAmount: r.daily_amount,
|
|
948
|
+
dailyAmountUsd: r.daily_amount_usd,
|
|
949
|
+
apr: r.apr
|
|
950
|
+
}));
|
|
951
|
+
var poolFeeSchema = zod.z.object({ fee_raw: zod.z.number(), fee_usd: zod.z.number() }).transform((f) => ({ feeRaw: f.fee_raw, feeUsd: f.fee_usd }));
|
|
952
|
+
var coinCandleSchema = zod.z.object({
|
|
953
|
+
t: zod.z.string(),
|
|
954
|
+
ohlcv: zod.z.array(zod.z.number()).nullish()
|
|
955
|
+
}).transform(({ t, ohlcv }) => {
|
|
956
|
+
const [open = 0, high = 0, low = 0, close = 0, volume = 0] = ohlcv ?? [];
|
|
957
|
+
return { timestamp: Date.parse(t), open, high, low, close, volume };
|
|
958
|
+
});
|
|
959
|
+
var poolCandleSchema = zod.z.array(zod.z.number()).transform(([seconds = 0, open = 0, high = 0, low = 0, close = 0, volume = 0]) => ({
|
|
960
|
+
timestamp: seconds * 1e3,
|
|
961
|
+
open,
|
|
962
|
+
high,
|
|
963
|
+
low,
|
|
964
|
+
close,
|
|
965
|
+
volume
|
|
966
|
+
}));
|
|
967
|
+
var VALID_BUCKET_MINUTES = [
|
|
968
|
+
1,
|
|
969
|
+
5,
|
|
970
|
+
15,
|
|
971
|
+
30,
|
|
972
|
+
60,
|
|
973
|
+
120,
|
|
974
|
+
240,
|
|
975
|
+
360,
|
|
976
|
+
720,
|
|
977
|
+
1440,
|
|
978
|
+
5760,
|
|
979
|
+
10080,
|
|
980
|
+
43200
|
|
981
|
+
];
|
|
982
|
+
function assertBucket(bucketMinutes) {
|
|
983
|
+
if (!VALID_BUCKET_MINUTES.includes(bucketMinutes)) {
|
|
984
|
+
throw new MinswapError(
|
|
985
|
+
`bucketMinutes must be one of ${VALID_BUCKET_MINUTES.join(", ")}; received ${bucketMinutes}`,
|
|
986
|
+
"INVALID_PARAMS" /* INVALID_PARAMS */,
|
|
987
|
+
{ param: "bucketMinutes", reason: "unsupported bucket size" }
|
|
988
|
+
);
|
|
989
|
+
}
|
|
990
|
+
}
|
|
1115
991
|
|
|
1116
992
|
// src/client/rpc-provider.ts
|
|
1117
993
|
function parseTxIn(ref) {
|
|
@@ -1623,11 +1499,11 @@ function calculateDepositSwapAmount(params) {
|
|
|
1623
1499
|
const { amountIn, amountOut, reserveIn, reserveOut, tradingFeeNumerator } = params;
|
|
1624
1500
|
const x = (amountOut + reserveOut) * reserveIn;
|
|
1625
1501
|
const y = 4n * (amountOut + reserveOut) * (amountOut * reserveIn * reserveIn - amountIn * reserveIn * reserveOut);
|
|
1626
|
-
const
|
|
1502
|
+
const z13 = 2n * (amountOut + reserveOut);
|
|
1627
1503
|
const twoDenomMinusFee = 2n * FEE_DENOMINATOR - tradingFeeNumerator;
|
|
1628
1504
|
const a = x * x * (twoDenomMinusFee * twoDenomMinusFee) - y * FEE_DENOMINATOR * (FEE_DENOMINATOR - tradingFeeNumerator);
|
|
1629
1505
|
const b = twoDenomMinusFee * x;
|
|
1630
|
-
return [sqrt(a) - b,
|
|
1506
|
+
return [sqrt(a) - b, z13 * (FEE_DENOMINATOR - tradingFeeNumerator)];
|
|
1631
1507
|
}
|
|
1632
1508
|
function calculateDepositAmount(params) {
|
|
1633
1509
|
const { amountA, amountB, pool } = params;
|
|
@@ -1764,6 +1640,17 @@ async function loadDexSerializer() {
|
|
|
1764
1640
|
})();
|
|
1765
1641
|
return cached;
|
|
1766
1642
|
}
|
|
1643
|
+
function paymentCredentialHex(addr) {
|
|
1644
|
+
const credential2 = addr.toPaymentCredential();
|
|
1645
|
+
if (!credential2) {
|
|
1646
|
+
throw new MinswapError(
|
|
1647
|
+
"Sender address has no payment credential",
|
|
1648
|
+
"INVALID_PARAMS" /* INVALID_PARAMS */,
|
|
1649
|
+
{ param: "sender", reason: "address has no payment credential" }
|
|
1650
|
+
);
|
|
1651
|
+
}
|
|
1652
|
+
return credential2.payload.hex;
|
|
1653
|
+
}
|
|
1767
1654
|
async function toDatumHex(datum) {
|
|
1768
1655
|
const { PlutusData: plutus } = await loadDexSerializer();
|
|
1769
1656
|
return plutus.toDataHex(datum);
|
|
@@ -1775,8 +1662,18 @@ async function loadDexBuilder() {
|
|
|
1775
1662
|
// src/liquidity/build/assemble.ts
|
|
1776
1663
|
async function assembleOrder(order) {
|
|
1777
1664
|
const b = await loadDexBuilder();
|
|
1778
|
-
const {
|
|
1779
|
-
|
|
1665
|
+
const {
|
|
1666
|
+
TxBuilderV2,
|
|
1667
|
+
TxOut,
|
|
1668
|
+
Value,
|
|
1669
|
+
Address,
|
|
1670
|
+
Asset,
|
|
1671
|
+
Bytes,
|
|
1672
|
+
DatumSource,
|
|
1673
|
+
Utxo,
|
|
1674
|
+
EmulatorProvider,
|
|
1675
|
+
CoinSelectionAlgorithm
|
|
1676
|
+
} = b;
|
|
1780
1677
|
const valueMap = { lovelace: order.lovelace };
|
|
1781
1678
|
for (const a of order.assets) {
|
|
1782
1679
|
valueMap[Asset.fromBlockFrostString(a.unit).toString()] = a.amount;
|
|
@@ -1805,7 +1702,7 @@ var unitOf = (a) => a.policyId + a.nameHex;
|
|
|
1805
1702
|
async function resolveSender(sender) {
|
|
1806
1703
|
const b = await loadDexBuilder();
|
|
1807
1704
|
const addr = b.Address.fromBech32(sender);
|
|
1808
|
-
const paymentKeyHash = addr
|
|
1705
|
+
const paymentKeyHash = paymentCredentialHex(addr);
|
|
1809
1706
|
const stakeAddr = addr.toStakeAddress?.();
|
|
1810
1707
|
const stakeKeyHash = stakeAddr ? stakeAddr.toPubKeyHash()?.keyHash.hex ?? null : null;
|
|
1811
1708
|
const orderAddress = b.Address.fromPlutusJson(
|
|
@@ -1911,7 +1808,7 @@ var unitOf2 = (a) => a.policyId + a.nameHex;
|
|
|
1911
1808
|
async function resolveSender2(sender) {
|
|
1912
1809
|
const b = await loadDexBuilder();
|
|
1913
1810
|
const addr = b.Address.fromBech32(sender);
|
|
1914
|
-
const paymentKeyHash = addr
|
|
1811
|
+
const paymentKeyHash = paymentCredentialHex(addr);
|
|
1915
1812
|
const stakeAddr = addr.toStakeAddress?.();
|
|
1916
1813
|
const stakeKeyHash = stakeAddr ? stakeAddr.toPubKeyHash()?.keyHash.hex ?? null : null;
|
|
1917
1814
|
const orderAddress = b.Address.fromPlutusJson(
|
|
@@ -2274,7 +2171,7 @@ var unitOfLpAsset = (a) => a.policyId + a.nameHex;
|
|
|
2274
2171
|
async function resolveSender3(sender) {
|
|
2275
2172
|
const b = await loadDexBuilder();
|
|
2276
2173
|
const addr = b.Address.fromBech32(sender);
|
|
2277
|
-
const paymentKeyHash = addr
|
|
2174
|
+
const paymentKeyHash = paymentCredentialHex(addr);
|
|
2278
2175
|
const stakeAddr = addr.toStakeAddress?.();
|
|
2279
2176
|
const stakeKeyHash = stakeAddr ? stakeAddr.toPubKeyHash()?.keyHash.hex ?? null : null;
|
|
2280
2177
|
return { paymentKeyHash, stakeKeyHash };
|
|
@@ -2579,206 +2476,133 @@ function getStableswapConfigByLpAsset(lpAsset) {
|
|
|
2579
2476
|
}
|
|
2580
2477
|
return config;
|
|
2581
2478
|
}
|
|
2582
|
-
var
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2479
|
+
var POOL_STATE_PATH = "/api/v1/pool/state";
|
|
2480
|
+
var POOL_STATE_ENDPOINT = `GET ${POOL_STATE_PATH}`;
|
|
2481
|
+
var MAX_POOL_IDS = 50;
|
|
2482
|
+
var uint = zod.z.string().regex(/^\d+$/, "expected a non-negative decimal integer string").transform((s) => BigInt(s));
|
|
2483
|
+
var coinSchema = zod.z.object({
|
|
2484
|
+
coin_type: zod.z.string(),
|
|
2485
|
+
symbol: zod.z.string(),
|
|
2486
|
+
decimals: zod.z.number().nullish()
|
|
2586
2487
|
});
|
|
2587
|
-
var
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2488
|
+
var poolStateSchema = zod.z.object({
|
|
2489
|
+
protocol: zod.z.enum(["minswap-cpmm-v1", "minswap-cpmm-v2", "minswap-stable-cpmm-v1"]),
|
|
2490
|
+
pool_id: zod.z.string(),
|
|
2491
|
+
coin_a: coinSchema,
|
|
2492
|
+
coin_b: coinSchema,
|
|
2493
|
+
tx_in: zod.z.string(),
|
|
2494
|
+
address: zod.z.string(),
|
|
2495
|
+
v1: zod.z.object({ reserve_a: uint, reserve_b: uint, liquidity: uint }).nullish(),
|
|
2496
|
+
v2: zod.z.object({
|
|
2497
|
+
reserve_a: uint,
|
|
2498
|
+
reserve_b: uint,
|
|
2499
|
+
liquidity: uint,
|
|
2500
|
+
fee_a_numerator: uint,
|
|
2501
|
+
fee_b_numerator: uint
|
|
2502
|
+
}).nullish(),
|
|
2503
|
+
stable: zod.z.object({
|
|
2504
|
+
balances: zod.z.array(uint),
|
|
2505
|
+
liquidity: uint,
|
|
2506
|
+
amplification_coefficient: uint
|
|
2507
|
+
}).nullish()
|
|
2599
2508
|
});
|
|
2600
|
-
var
|
|
2601
|
-
var POOL_FIELDS = `
|
|
2602
|
-
type
|
|
2603
|
-
lpAsset { currencySymbol tokenName }
|
|
2604
|
-
poolAssets { currencySymbol tokenName metadata { decimals } }
|
|
2605
|
-
utxo { address datum txIn value }
|
|
2606
|
-
`;
|
|
2607
|
-
var BY_LP_ASSETS_QUERY = `query AppliedPoolsByLpAssets($lpAssets: [InputAsset!]!) {
|
|
2608
|
-
appliedPoolsByLPAssets(lpAssets: $lpAssets) {${POOL_FIELDS}}
|
|
2609
|
-
}`;
|
|
2610
|
-
var BY_PAIRS_QUERY = `query AppliedPoolsByPairs($pairs: [InputPair!]!) {
|
|
2611
|
-
appliedPoolsByPairs(pairs: $pairs) {${POOL_FIELDS}}
|
|
2612
|
-
}`;
|
|
2509
|
+
var poolStatesSchema = zod.z.array(poolStateSchema).nullish().transform((pools) => pools ?? []);
|
|
2613
2510
|
async function getAppliedPoolsByLpAssets(client, lpAssets) {
|
|
2614
|
-
const
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
async function getAppliedPoolsByPairs(client, pairs) {
|
|
2623
|
-
const pools = await client.execute({
|
|
2624
|
-
operation: "appliedPoolsByPairs",
|
|
2625
|
-
document: BY_PAIRS_QUERY,
|
|
2626
|
-
variables: { pairs },
|
|
2627
|
-
schema: poolsSchema
|
|
2628
|
-
});
|
|
2629
|
-
return Promise.all(pools.map(toAppliedPool));
|
|
2511
|
+
const chunks = [];
|
|
2512
|
+
for (let i = 0; i < lpAssets.length; i += MAX_POOL_IDS) {
|
|
2513
|
+
chunks.push(lpAssets.slice(i, i + MAX_POOL_IDS));
|
|
2514
|
+
}
|
|
2515
|
+
const pages = await Promise.all(
|
|
2516
|
+
chunks.map((chunk) => fetchPoolStates(client, { pool_ids: chunk, applied: true }))
|
|
2517
|
+
);
|
|
2518
|
+
return pages.flat();
|
|
2630
2519
|
}
|
|
2631
|
-
function
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
return "STABLESWAP";
|
|
2520
|
+
async function getAppliedPoolsByPair(client, coinA, coinB) {
|
|
2521
|
+
if (coinA === coinB) {
|
|
2522
|
+
throw new MinswapError(
|
|
2523
|
+
`A pool pair needs two different coins, got ${coinA} twice`,
|
|
2524
|
+
"INVALID_PARAMS" /* INVALID_PARAMS */,
|
|
2525
|
+
{ param: "pool", reason: "assetA and assetB must differ" }
|
|
2526
|
+
);
|
|
2639
2527
|
}
|
|
2528
|
+
return fetchPoolStates(client, { coin_a: coinA, coin_b: coinB, applied: true });
|
|
2640
2529
|
}
|
|
2641
|
-
function
|
|
2642
|
-
|
|
2530
|
+
async function fetchPoolStates(client, query) {
|
|
2531
|
+
const { data } = await client.get({ path: POOL_STATE_PATH, query, schema: poolStatesSchema });
|
|
2532
|
+
return data.map(toAppliedPool);
|
|
2643
2533
|
}
|
|
2644
|
-
function
|
|
2534
|
+
function coinIdOf(a) {
|
|
2645
2535
|
return a.policyId === "" ? "lovelace" : `${a.policyId}.${a.nameHex}`;
|
|
2646
2536
|
}
|
|
2647
|
-
|
|
2648
|
-
const
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2537
|
+
function toPoolAsset(coinId) {
|
|
2538
|
+
const a = coinIdToInputAsset(coinId);
|
|
2539
|
+
return { policyId: a.currencySymbol, nameHex: a.tokenName };
|
|
2540
|
+
}
|
|
2541
|
+
function parseError(path, message) {
|
|
2542
|
+
return new MinswapError(`${POOL_STATE_ENDPOINT}: ${message}`, "PARSE_ERROR" /* PARSE_ERROR */, {
|
|
2543
|
+
endpoint: POOL_STATE_ENDPOINT,
|
|
2544
|
+
issues: [{ path, message }]
|
|
2545
|
+
});
|
|
2546
|
+
}
|
|
2547
|
+
function toAppliedPool(pool) {
|
|
2548
|
+
const filled = [pool.v1, pool.v2, pool.stable].filter((s) => s != null).length;
|
|
2549
|
+
if (filled !== 1) {
|
|
2550
|
+
throw parseError(pool.pool_id, `expected exactly one of v1/v2/stable, got ${filled}`);
|
|
2659
2551
|
}
|
|
2660
|
-
|
|
2661
|
-
let assetA;
|
|
2662
|
-
let assetB;
|
|
2552
|
+
let version;
|
|
2663
2553
|
let state;
|
|
2664
|
-
if (
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2554
|
+
if (pool.protocol === "minswap-cpmm-v2" && pool.v2) {
|
|
2555
|
+
version = "V2";
|
|
2556
|
+
state = {
|
|
2557
|
+
kind: "V2",
|
|
2558
|
+
reserveA: pool.v2.reserve_a,
|
|
2559
|
+
reserveB: pool.v2.reserve_b,
|
|
2560
|
+
totalLiquidity: pool.v2.liquidity,
|
|
2561
|
+
feeANumerator: pool.v2.fee_a_numerator,
|
|
2562
|
+
feeBNumerator: pool.v2.fee_b_numerator
|
|
2563
|
+
};
|
|
2564
|
+
} else if (pool.protocol === "minswap-cpmm-v1" && pool.v1) {
|
|
2565
|
+
version = "V1";
|
|
2566
|
+
state = {
|
|
2567
|
+
kind: "V1",
|
|
2568
|
+
reserveA: pool.v1.reserve_a,
|
|
2569
|
+
reserveB: pool.v1.reserve_b,
|
|
2570
|
+
totalLiquidity: pool.v1.liquidity
|
|
2571
|
+
};
|
|
2572
|
+
} else if (pool.protocol === "minswap-stable-cpmm-v1" && pool.stable) {
|
|
2573
|
+
version = "STABLESWAP";
|
|
2574
|
+
state = {
|
|
2575
|
+
kind: "STABLESWAP",
|
|
2576
|
+
balances: pool.stable.balances,
|
|
2577
|
+
totalLiquidity: pool.stable.liquidity,
|
|
2578
|
+
amp: pool.stable.amplification_coefficient
|
|
2579
|
+
};
|
|
2672
2580
|
} else {
|
|
2673
|
-
|
|
2674
|
-
assetB = decodeAssetNode(fields[1], "V1 pool datum", "assetB");
|
|
2675
|
-
state = decodeV1State(fields, pool.utxo.value, assetA, assetB);
|
|
2581
|
+
throw parseError(pool.pool_id, `state block does not match protocol ${pool.protocol}`);
|
|
2676
2582
|
}
|
|
2677
2583
|
const decimals = { lovelace: 6 };
|
|
2678
|
-
for (const
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
decimals[`${a.currencySymbol}.${a.tokenName}`] = d;
|
|
2584
|
+
for (const coin of [pool.coin_a, pool.coin_b]) {
|
|
2585
|
+
if (coin.coin_type !== "lovelace" && coin.symbol !== "" && coin.decimals != null) {
|
|
2586
|
+
decimals[coinIdOf(toPoolAsset(coin.coin_type))] = coin.decimals;
|
|
2682
2587
|
}
|
|
2683
2588
|
}
|
|
2684
2589
|
return {
|
|
2685
2590
|
version,
|
|
2686
|
-
lpAsset: toPoolAsset(pool.
|
|
2687
|
-
assetA,
|
|
2688
|
-
assetB,
|
|
2591
|
+
lpAsset: toPoolAsset(pool.pool_id),
|
|
2592
|
+
assetA: toPoolAsset(pool.coin_a.coin_type),
|
|
2593
|
+
assetB: toPoolAsset(pool.coin_b.coin_type),
|
|
2689
2594
|
state,
|
|
2690
|
-
utxoRef: pool.
|
|
2691
|
-
poolAddress: pool.
|
|
2692
|
-
rawDatum: pool.utxo.datum,
|
|
2595
|
+
utxoRef: pool.tx_in,
|
|
2596
|
+
poolAddress: pool.address,
|
|
2693
2597
|
decimals
|
|
2694
2598
|
};
|
|
2695
2599
|
}
|
|
2696
|
-
async function decodeDatumFields(datumHex) {
|
|
2697
|
-
const builder = await loadDexBuilder();
|
|
2698
|
-
const decoder = builder.PlutusData;
|
|
2699
|
-
const fields = decoder.fromDataHex(datumHex).fields;
|
|
2700
|
-
if (!fields) {
|
|
2701
|
-
throw parseError("pool datum", "fields", "datum is not a constructor with fields");
|
|
2702
|
-
}
|
|
2703
|
-
return fields;
|
|
2704
|
-
}
|
|
2705
|
-
function parseError(endpoint, path, message) {
|
|
2706
|
-
return new MinswapError(`${endpoint}: ${message}`, "PARSE_ERROR" /* PARSE_ERROR */, {
|
|
2707
|
-
endpoint,
|
|
2708
|
-
issues: [{ path, message }]
|
|
2709
|
-
});
|
|
2710
|
-
}
|
|
2711
|
-
function decodeAssetNode(node, endpoint, field) {
|
|
2712
|
-
const f = node?.fields;
|
|
2713
|
-
if (!f || f.length < 2 || f[0]?.bytes === void 0 || f[1]?.bytes === void 0) {
|
|
2714
|
-
throw parseError(endpoint, field, "expected an asset Constr[policyId, assetNameHex]");
|
|
2715
|
-
}
|
|
2716
|
-
return { policyId: f[0].bytes, nameHex: f[1].bytes };
|
|
2717
|
-
}
|
|
2718
|
-
function readInt(node, endpoint, field) {
|
|
2719
|
-
if (!node || node.int === void 0) {
|
|
2720
|
-
throw parseError(endpoint, field, "expected an integer");
|
|
2721
|
-
}
|
|
2722
|
-
return BigInt(node.int);
|
|
2723
|
-
}
|
|
2724
|
-
function requireFields(fields, min, endpoint) {
|
|
2725
|
-
if (fields.length < min) {
|
|
2726
|
-
throw parseError(endpoint, "fields", `expected >=${min}, got ${fields.length}`);
|
|
2727
|
-
}
|
|
2728
|
-
}
|
|
2729
|
-
function decodeV2State(fields) {
|
|
2730
|
-
requireFields(fields, 8, "V2 pool datum");
|
|
2731
|
-
return {
|
|
2732
|
-
kind: "V2",
|
|
2733
|
-
totalLiquidity: readInt(fields[3], "V2 pool datum", "totalLiquidity"),
|
|
2734
|
-
reserveA: readInt(fields[4], "V2 pool datum", "reserveA"),
|
|
2735
|
-
reserveB: readInt(fields[5], "V2 pool datum", "reserveB"),
|
|
2736
|
-
feeANumerator: readInt(fields[6], "V2 pool datum", "feeANumerator"),
|
|
2737
|
-
feeBNumerator: readInt(fields[7], "V2 pool datum", "feeBNumerator")
|
|
2738
|
-
};
|
|
2739
|
-
}
|
|
2740
|
-
function decodeStableswapState(fields) {
|
|
2741
|
-
requireFields(fields, 3, "Stableswap pool datum");
|
|
2742
|
-
const balancesList = fields[0]?.list;
|
|
2743
|
-
if (!balancesList) {
|
|
2744
|
-
throw parseError("Stableswap pool datum", "balances", "expected a list");
|
|
2745
|
-
}
|
|
2746
|
-
return {
|
|
2747
|
-
kind: "STABLESWAP",
|
|
2748
|
-
balances: balancesList.map((b, i) => readInt(b, "Stableswap pool datum", `balances[${i}]`)),
|
|
2749
|
-
totalLiquidity: readInt(fields[1], "Stableswap pool datum", "totalLiquidity"),
|
|
2750
|
-
amp: readInt(fields[2], "Stableswap pool datum", "amp")
|
|
2751
|
-
};
|
|
2752
|
-
}
|
|
2753
|
-
var ledgerValueSchema = zod.z.object({ $ledgerValue: zod.z.record(zod.z.string(), zod.z.string()) });
|
|
2754
|
-
function decodeV1State(fields, valueJson, assetA, assetB) {
|
|
2755
|
-
requireFields(fields, 3, "V1 pool datum");
|
|
2756
|
-
const totalLiquidity = readInt(fields[2], "V1 pool datum", "totalLiquidity");
|
|
2757
|
-
let parsed;
|
|
2758
|
-
try {
|
|
2759
|
-
parsed = JSON.parse(valueJson);
|
|
2760
|
-
} catch {
|
|
2761
|
-
throw parseError("V1 pool value", "value", "not valid JSON");
|
|
2762
|
-
}
|
|
2763
|
-
const ledger = ledgerValueSchema.safeParse(parsed);
|
|
2764
|
-
if (!ledger.success) {
|
|
2765
|
-
throw parseError("V1 pool value", "$ledgerValue", "missing ledger value map");
|
|
2766
|
-
}
|
|
2767
|
-
const amounts = ledger.data.$ledgerValue;
|
|
2768
|
-
return {
|
|
2769
|
-
kind: "V1",
|
|
2770
|
-
reserveA: BigInt(amounts[unitOf3(assetA)] ?? "0"),
|
|
2771
|
-
reserveB: BigInt(amounts[unitOf3(assetB)] ?? "0"),
|
|
2772
|
-
totalLiquidity
|
|
2773
|
-
};
|
|
2774
|
-
}
|
|
2775
2600
|
|
|
2776
2601
|
// src/modules/liquidity-module.ts
|
|
2777
2602
|
var assetId = (coinId) => {
|
|
2778
2603
|
const a = coinIdToInputAsset(coinId);
|
|
2779
2604
|
return { policyId: a.currencySymbol, nameHex: a.tokenName };
|
|
2780
2605
|
};
|
|
2781
|
-
var coinIdOf = (a) => a.policyId === "" ? "lovelace" : `${a.policyId}.${a.nameHex}`;
|
|
2782
2606
|
var eqAsset = (x, y) => x.policyId === y.policyId && x.nameHex === y.nameHex;
|
|
2783
2607
|
var LiquidityModule = class {
|
|
2784
2608
|
constructor(sdk) {
|
|
@@ -2941,17 +2765,15 @@ var LiquidityModule = class {
|
|
|
2941
2765
|
});
|
|
2942
2766
|
}
|
|
2943
2767
|
async resolvePool(ref) {
|
|
2944
|
-
const client = this.sdk.clients.
|
|
2768
|
+
const client = this.sdk.clients.appApi;
|
|
2945
2769
|
if (typeof ref === "string") {
|
|
2946
|
-
const [pool] = await getAppliedPoolsByLpAssets(client, [
|
|
2770
|
+
const [pool] = await getAppliedPoolsByLpAssets(client, [ref]);
|
|
2947
2771
|
if (!pool) {
|
|
2948
2772
|
throw poolNotFound("LP asset", ref);
|
|
2949
2773
|
}
|
|
2950
2774
|
return pool;
|
|
2951
2775
|
}
|
|
2952
|
-
const pools = await
|
|
2953
|
-
{ assetA: coinIdToInputAsset(ref.assetA), assetB: coinIdToInputAsset(ref.assetB) }
|
|
2954
|
-
]);
|
|
2776
|
+
const pools = await getAppliedPoolsByPair(client, ref.assetA, ref.assetB);
|
|
2955
2777
|
const pairId = `${ref.assetA}/${ref.assetB}`;
|
|
2956
2778
|
if (pools.length === 0) {
|
|
2957
2779
|
throw poolNotFound("pair", pairId);
|
|
@@ -3156,6 +2978,36 @@ var orderSchema = zod.z.object({
|
|
|
3156
2978
|
*/
|
|
3157
2979
|
splits: o.splits
|
|
3158
2980
|
}));
|
|
2981
|
+
var pendingOrderSchema = zod.z.object({
|
|
2982
|
+
tx_in: zod.z.string(),
|
|
2983
|
+
protocol: zod.z.string(),
|
|
2984
|
+
source: zod.z.string().nullish(),
|
|
2985
|
+
coin_in: zod.z.string(),
|
|
2986
|
+
coin_out: zod.z.string(),
|
|
2987
|
+
amount_in: zod.z.string(),
|
|
2988
|
+
min_amount_out: zod.z.string(),
|
|
2989
|
+
dex_fee: zod.z.string(),
|
|
2990
|
+
deposit: zod.z.string(),
|
|
2991
|
+
created_at: zod.z.number()
|
|
2992
|
+
}).transform((o) => ({
|
|
2993
|
+
/** The order's UTxO reference, `txHash#index`. */
|
|
2994
|
+
txIn: o.tx_in,
|
|
2995
|
+
/** App API protocol code, e.g. `"minswap-cpmm-v2"`. */
|
|
2996
|
+
protocol: o.protocol,
|
|
2997
|
+
/** Aggregator whose transaction placed the order (`"minswap"`, `"dex-hunter"`, …); `null` when placed on the DEX directly. */
|
|
2998
|
+
source: o.source ?? null,
|
|
2999
|
+
coinIn: o.coin_in,
|
|
3000
|
+
coinOut: o.coin_out,
|
|
3001
|
+
amountIn: o.amount_in,
|
|
3002
|
+
/** `"0"` when the order sets no minimum. */
|
|
3003
|
+
minAmountOut: o.min_amount_out,
|
|
3004
|
+
/** Batcher fee, lovelace. */
|
|
3005
|
+
dexFee: o.dex_fee,
|
|
3006
|
+
/** Deposit returned with the output, lovelace. */
|
|
3007
|
+
deposit: o.deposit,
|
|
3008
|
+
/** Epoch milliseconds. */
|
|
3009
|
+
createdAt: o.created_at
|
|
3010
|
+
}));
|
|
3159
3011
|
var OrderModule = class {
|
|
3160
3012
|
constructor(sdk) {
|
|
3161
3013
|
this.sdk = sdk;
|
|
@@ -3187,6 +3039,31 @@ var OrderModule = class {
|
|
|
3187
3039
|
});
|
|
3188
3040
|
return cursorPage(data, pagination?.lastCursor);
|
|
3189
3041
|
}
|
|
3042
|
+
/**
|
|
3043
|
+
* List an address's open swap orders, newest first, across every protocol
|
|
3044
|
+
* and aggregator.
|
|
3045
|
+
*
|
|
3046
|
+
* An order is listed while its UTxO is unspent; each leg of a split or
|
|
3047
|
+
* multi-hop submission is its own entry. Only `SWAP` orders are listed; the
|
|
3048
|
+
* other types (deposit, withdraw, zap, limit, …) are in
|
|
3049
|
+
* {@link OrderModule.getHistory}.
|
|
3050
|
+
*
|
|
3051
|
+
* @param params - `address`, plus `limit` (1..50, default 20) and `cursor` from a previous page
|
|
3052
|
+
* @returns one page of pending orders and the cursor for the next
|
|
3053
|
+
*/
|
|
3054
|
+
async getPending(params) {
|
|
3055
|
+
assertLimit(params.limit, 50);
|
|
3056
|
+
const { data, pagination } = await this.sdk.clients.appApi.get({
|
|
3057
|
+
path: "/api/v1/order/pending",
|
|
3058
|
+
query: {
|
|
3059
|
+
address: params.address,
|
|
3060
|
+
cursor: params.cursor,
|
|
3061
|
+
limit: params.limit ?? 20
|
|
3062
|
+
},
|
|
3063
|
+
schema: arrayOf(pendingOrderSchema)
|
|
3064
|
+
});
|
|
3065
|
+
return cursorPage(data, pagination?.lastCursor);
|
|
3066
|
+
}
|
|
3190
3067
|
/**
|
|
3191
3068
|
* Collect the UTxO references that can still be cancelled for an order.
|
|
3192
3069
|
*
|
|
@@ -3833,7 +3710,7 @@ var DOC_LIQUID_UNSTAKE = `mutation MinBarBuildLiquidUnstakeTx($options: MinBarBu
|
|
|
3833
3710
|
minBarBuildLiquidUnstakeTx(options: $options)
|
|
3834
3711
|
}`;
|
|
3835
3712
|
var amountString = zod.z.string();
|
|
3836
|
-
var
|
|
3713
|
+
var coinSchema2 = zod.z.object({
|
|
3837
3714
|
coin_type: zod.z.string().nullish(),
|
|
3838
3715
|
symbol: zod.z.string(),
|
|
3839
3716
|
name: zod.z.string(),
|
|
@@ -3945,7 +3822,7 @@ var securitySchema = zod.z.object({
|
|
|
3945
3822
|
}));
|
|
3946
3823
|
var tagSchema = zod.z.object({ id: zod.z.number(), name: zod.z.string() });
|
|
3947
3824
|
var tokenDetailSchema = zod.z.object({
|
|
3948
|
-
coin:
|
|
3825
|
+
coin: coinSchema2,
|
|
3949
3826
|
price_change: priceSchema,
|
|
3950
3827
|
volume: volumeSchema.nullish(),
|
|
3951
3828
|
social_media: socialMediaSchema,
|
|
@@ -4333,8 +4210,7 @@ var MinswapSdk = class {
|
|
|
4333
4210
|
this.clients = {
|
|
4334
4211
|
appApi: new AppApiClient(http, this.config),
|
|
4335
4212
|
aggregatorApi: new AggregatorApiClient(http, this.config),
|
|
4336
|
-
keyAppApi: new KeyAppApiClient(http, this.config)
|
|
4337
|
-
appGraphql: new AppGraphqlClient(http, this.config)
|
|
4213
|
+
keyAppApi: new KeyAppApiClient(http, this.config)
|
|
4338
4214
|
};
|
|
4339
4215
|
this.token = new TokenModule(this);
|
|
4340
4216
|
this.pool = new PoolModule(this);
|
|
@@ -4563,7 +4439,6 @@ exports.AGGREGATOR_PROTOCOLS = AGGREGATOR_PROTOCOLS;
|
|
|
4563
4439
|
exports.AggregatorApiClient = AggregatorApiClient;
|
|
4564
4440
|
exports.AggregatorModule = AggregatorModule;
|
|
4565
4441
|
exports.AppApiClient = AppApiClient;
|
|
4566
|
-
exports.AppGraphqlClient = AppGraphqlClient;
|
|
4567
4442
|
exports.BATCHER_FEE = BATCHER_FEE;
|
|
4568
4443
|
exports.CANCEL_ADAPTER_PROTOCOL = CANCEL_ADAPTER_PROTOCOL;
|
|
4569
4444
|
exports.DEFAULT_ENDPOINTS = DEFAULT_ENDPOINTS;
|
|
@@ -4606,6 +4481,7 @@ exports.buildUrl = buildUrl;
|
|
|
4606
4481
|
exports.coinAmountInfoSchema = coinAmountInfoSchema;
|
|
4607
4482
|
exports.coinBasicInfoSchema = coinBasicInfoSchema;
|
|
4608
4483
|
exports.coinCandleSchema = coinCandleSchema;
|
|
4484
|
+
exports.coinIdOf = coinIdOf;
|
|
4609
4485
|
exports.coinIdToAssetUnit = coinIdToAssetUnit;
|
|
4610
4486
|
exports.coinIdToInputAsset = coinIdToInputAsset;
|
|
4611
4487
|
exports.collect = collect;
|
|
@@ -4615,10 +4491,9 @@ exports.decodeOffsetCursor = decodeOffsetCursor;
|
|
|
4615
4491
|
exports.encodeOffsetCursor = encodeOffsetCursor;
|
|
4616
4492
|
exports.formatTxIn = formatTxIn;
|
|
4617
4493
|
exports.getAppliedPoolsByLpAssets = getAppliedPoolsByLpAssets;
|
|
4618
|
-
exports.
|
|
4494
|
+
exports.getAppliedPoolsByPair = getAppliedPoolsByPair;
|
|
4619
4495
|
exports.inputAssetToCoinId = inputAssetToCoinId;
|
|
4620
4496
|
exports.isPureAda = isPureAda;
|
|
4621
|
-
exports.loadDexBuilder = loadDexBuilder;
|
|
4622
4497
|
exports.lovelaceOf = lovelaceOf;
|
|
4623
4498
|
exports.offsetPage = offsetPage;
|
|
4624
4499
|
exports.paginate = paginate;
|
|
@@ -4632,7 +4507,6 @@ exports.resolveConfig = resolveConfig;
|
|
|
4632
4507
|
exports.resolveWalletInputs = resolveWalletInputs;
|
|
4633
4508
|
exports.selectCollateral = selectCollateral;
|
|
4634
4509
|
exports.toBigIntString = toBigIntString;
|
|
4635
|
-
exports.toDatumHex = toDatumHex;
|
|
4636
4510
|
exports.toEpochMs = toEpochMs;
|
|
4637
4511
|
exports.toEpochSeconds = toEpochSeconds;
|
|
4638
4512
|
exports.toRfc3339 = toRfc3339;
|