@morpho-dev/router 0.1.3 → 0.1.4
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/index.browser.d.cts +125 -67
- package/dist/index.browser.d.ts +125 -67
- package/dist/index.browser.js +338 -157
- package/dist/index.browser.js.map +1 -1
- package/dist/index.browser.mjs +338 -159
- package/dist/index.browser.mjs.map +1 -1
- package/dist/index.node.d.cts +168 -111
- package/dist/index.node.d.ts +168 -111
- package/dist/index.node.js +338 -158
- package/dist/index.node.js.map +1 -1
- package/dist/index.node.mjs +338 -160
- package/dist/index.node.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.node.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var mempool = require('@morpho-dev/mempool');
|
|
4
|
+
var jsBase64 = require('js-base64');
|
|
4
5
|
var v4 = require('zod/v4');
|
|
5
6
|
var zodOpenapi = require('zod-openapi');
|
|
6
7
|
var viem = require('viem');
|
|
7
|
-
var jsBase64 = require('js-base64');
|
|
8
8
|
var nodeServer = require('@hono/node-server');
|
|
9
9
|
var hono = require('hono');
|
|
10
10
|
var async_hooks = require('async_hooks');
|
|
@@ -15,6 +15,145 @@ var __export = (target, all) => {
|
|
|
15
15
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
16
16
|
};
|
|
17
17
|
|
|
18
|
+
// src/Callback.ts
|
|
19
|
+
var Callback_exports = {};
|
|
20
|
+
__export(Callback_exports, {
|
|
21
|
+
CallbackType: () => CallbackType,
|
|
22
|
+
buildLiquidity: () => buildLiquidity,
|
|
23
|
+
getCallbackIdForOffer: () => getCallbackIdForOffer
|
|
24
|
+
});
|
|
25
|
+
var CallbackType = /* @__PURE__ */ ((CallbackType2) => {
|
|
26
|
+
CallbackType2["BuyWithEmptyCallback"] = "buy_with_empty_callback";
|
|
27
|
+
return CallbackType2;
|
|
28
|
+
})(CallbackType || {});
|
|
29
|
+
function buildLiquidity(parameters) {
|
|
30
|
+
const { type, user, contract, chainId, amount, index = 0, updatedAt = /* @__PURE__ */ new Date() } = parameters;
|
|
31
|
+
if (type !== "buy_with_empty_callback" /* BuyWithEmptyCallback */)
|
|
32
|
+
throw new Error(`CallbackType not implemented: ${type}`);
|
|
33
|
+
const amountStr = amount.toString();
|
|
34
|
+
const id = `${user}-${chainId.toString()}-${type}-${contract}`.toLowerCase();
|
|
35
|
+
return {
|
|
36
|
+
userPosition: {
|
|
37
|
+
id,
|
|
38
|
+
availableLiquidityQueueId: id,
|
|
39
|
+
user: user.toLowerCase(),
|
|
40
|
+
chainId,
|
|
41
|
+
amount: amountStr,
|
|
42
|
+
updatedAt
|
|
43
|
+
},
|
|
44
|
+
queues: [
|
|
45
|
+
{
|
|
46
|
+
queue: {
|
|
47
|
+
queueId: id,
|
|
48
|
+
availableLiquidityPoolId: id,
|
|
49
|
+
index,
|
|
50
|
+
updatedAt
|
|
51
|
+
},
|
|
52
|
+
pool: {
|
|
53
|
+
id,
|
|
54
|
+
amount: amountStr,
|
|
55
|
+
updatedAt
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
]
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
function getCallbackIdForOffer(offer) {
|
|
62
|
+
if (offer.buy && offer.callback.data === "0x") {
|
|
63
|
+
const type = "buy_with_empty_callback" /* BuyWithEmptyCallback */;
|
|
64
|
+
const user = offer.offering;
|
|
65
|
+
const loanToken = offer.loanToken;
|
|
66
|
+
return `${user}-${offer.chainId.toString()}-${type}-${loanToken}`.toLowerCase();
|
|
67
|
+
}
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// src/Cursor.ts
|
|
72
|
+
var Cursor_exports = {};
|
|
73
|
+
__export(Cursor_exports, {
|
|
74
|
+
decode: () => decode,
|
|
75
|
+
encode: () => encode,
|
|
76
|
+
validate: () => validate
|
|
77
|
+
});
|
|
78
|
+
function validate(cursor) {
|
|
79
|
+
if (!cursor || typeof cursor !== "object") {
|
|
80
|
+
throw new Error("Cursor must be an object");
|
|
81
|
+
}
|
|
82
|
+
const c = cursor;
|
|
83
|
+
if (!["rate", "maturity", "expiry", "amount"].includes(c.sort)) {
|
|
84
|
+
throw new Error(
|
|
85
|
+
`Invalid sort field: ${c.sort}. Must be one of: rate, maturity, expiry, amount`
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
if (!["asc", "desc"].includes(c.dir)) {
|
|
89
|
+
throw new Error(`Invalid direction: ${c.dir}. Must be one of: asc, desc`);
|
|
90
|
+
}
|
|
91
|
+
if (!/^0x[a-fA-F0-9]{64}$/.test(c.hash)) {
|
|
92
|
+
throw new Error(
|
|
93
|
+
`Invalid hash format: ${c.hash}. Must be a 64-character hex string starting with 0x`
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
const validations = {
|
|
97
|
+
rate: {
|
|
98
|
+
field: "rate",
|
|
99
|
+
type: "string",
|
|
100
|
+
pattern: /^\d+$/,
|
|
101
|
+
error: "numeric string"
|
|
102
|
+
},
|
|
103
|
+
amount: {
|
|
104
|
+
field: "assets",
|
|
105
|
+
type: "string",
|
|
106
|
+
pattern: /^\d+$/,
|
|
107
|
+
error: "numeric string"
|
|
108
|
+
},
|
|
109
|
+
maturity: {
|
|
110
|
+
field: "maturity",
|
|
111
|
+
type: "number",
|
|
112
|
+
validator: (val) => val > 0,
|
|
113
|
+
error: "positive number"
|
|
114
|
+
},
|
|
115
|
+
expiry: {
|
|
116
|
+
field: "expiry",
|
|
117
|
+
type: "number",
|
|
118
|
+
validator: (val) => val > 0,
|
|
119
|
+
error: "positive number"
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
const validation = validations[c.sort];
|
|
123
|
+
if (!validation) {
|
|
124
|
+
throw new Error(`Invalid sort field: ${c.sort}`);
|
|
125
|
+
}
|
|
126
|
+
const fieldValue = c[validation.field];
|
|
127
|
+
if (!fieldValue) {
|
|
128
|
+
throw new Error(`${c.sort} sort requires '${validation.field}' field to be present`);
|
|
129
|
+
}
|
|
130
|
+
if (typeof fieldValue !== validation.type) {
|
|
131
|
+
throw new Error(
|
|
132
|
+
`${c.sort} sort requires '${validation.field}' field of type ${validation.type}`
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
if (validation.pattern && !validation.pattern.test(fieldValue)) {
|
|
136
|
+
throw new Error(
|
|
137
|
+
`Invalid ${validation.field} format: ${fieldValue}. Must be a ${validation.error}`
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
if (validation.validator && !validation.validator(fieldValue)) {
|
|
141
|
+
throw new Error(
|
|
142
|
+
`Invalid ${validation.field} value: ${fieldValue}. Must be a ${validation.error}`
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
return true;
|
|
146
|
+
}
|
|
147
|
+
function encode(c) {
|
|
148
|
+
return jsBase64.Base64.encodeURL(JSON.stringify(c));
|
|
149
|
+
}
|
|
150
|
+
function decode(token) {
|
|
151
|
+
if (!token) return null;
|
|
152
|
+
const decoded = JSON.parse(jsBase64.Base64.decode(token));
|
|
153
|
+
validate(decoded);
|
|
154
|
+
return decoded;
|
|
155
|
+
}
|
|
156
|
+
|
|
18
157
|
// src/core/apiSchema/index.ts
|
|
19
158
|
var apiSchema_exports = {};
|
|
20
159
|
__export(apiSchema_exports, {
|
|
@@ -105,140 +244,6 @@ var InvalidRouterOfferError = class extends mempool.Errors.BaseError {
|
|
|
105
244
|
}
|
|
106
245
|
};
|
|
107
246
|
|
|
108
|
-
// src/utils/index.ts
|
|
109
|
-
var utils_exports = {};
|
|
110
|
-
__export(utils_exports, {
|
|
111
|
-
batch: () => batch,
|
|
112
|
-
decodeCursor: () => decodeCursor,
|
|
113
|
-
encodeCursor: () => encodeCursor,
|
|
114
|
-
poll: () => poll,
|
|
115
|
-
retry: () => retry,
|
|
116
|
-
validateCursor: () => validateCursor,
|
|
117
|
-
wait: () => wait
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
// src/utils/batch.ts
|
|
121
|
-
function* batch(array, batchSize) {
|
|
122
|
-
for (let i = 0; i < array.length; i += batchSize) {
|
|
123
|
-
yield array.slice(i, i + batchSize);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
function validateCursor(cursor) {
|
|
127
|
-
if (!cursor || typeof cursor !== "object") {
|
|
128
|
-
throw new Error("Cursor must be an object");
|
|
129
|
-
}
|
|
130
|
-
const c = cursor;
|
|
131
|
-
if (!["rate", "maturity", "expiry", "amount"].includes(c.sort)) {
|
|
132
|
-
throw new Error(
|
|
133
|
-
`Invalid sort field: ${c.sort}. Must be one of: rate, maturity, expiry, amount`
|
|
134
|
-
);
|
|
135
|
-
}
|
|
136
|
-
if (!["asc", "desc"].includes(c.dir)) {
|
|
137
|
-
throw new Error(`Invalid direction: ${c.dir}. Must be one of: asc, desc`);
|
|
138
|
-
}
|
|
139
|
-
if (!/^0x[a-fA-F0-9]{64}$/.test(c.hash)) {
|
|
140
|
-
throw new Error(
|
|
141
|
-
`Invalid hash format: ${c.hash}. Must be a 64-character hex string starting with 0x`
|
|
142
|
-
);
|
|
143
|
-
}
|
|
144
|
-
const validations = {
|
|
145
|
-
rate: {
|
|
146
|
-
field: "rate",
|
|
147
|
-
type: "string",
|
|
148
|
-
pattern: /^\d+$/,
|
|
149
|
-
error: "numeric string"
|
|
150
|
-
},
|
|
151
|
-
amount: {
|
|
152
|
-
field: "assets",
|
|
153
|
-
type: "string",
|
|
154
|
-
pattern: /^\d+$/,
|
|
155
|
-
error: "numeric string"
|
|
156
|
-
},
|
|
157
|
-
maturity: {
|
|
158
|
-
field: "maturity",
|
|
159
|
-
type: "number",
|
|
160
|
-
validator: (val) => val > 0,
|
|
161
|
-
error: "positive number"
|
|
162
|
-
},
|
|
163
|
-
expiry: {
|
|
164
|
-
field: "expiry",
|
|
165
|
-
type: "number",
|
|
166
|
-
validator: (val) => val > 0,
|
|
167
|
-
error: "positive number"
|
|
168
|
-
}
|
|
169
|
-
};
|
|
170
|
-
const validation = validations[c.sort];
|
|
171
|
-
if (!validation) {
|
|
172
|
-
throw new Error(`Invalid sort field: ${c.sort}`);
|
|
173
|
-
}
|
|
174
|
-
const fieldValue = c[validation.field];
|
|
175
|
-
if (!fieldValue) {
|
|
176
|
-
throw new Error(`${c.sort} sort requires '${validation.field}' field to be present`);
|
|
177
|
-
}
|
|
178
|
-
if (typeof fieldValue !== validation.type) {
|
|
179
|
-
throw new Error(
|
|
180
|
-
`${c.sort} sort requires '${validation.field}' field of type ${validation.type}`
|
|
181
|
-
);
|
|
182
|
-
}
|
|
183
|
-
if (validation.pattern && !validation.pattern.test(fieldValue)) {
|
|
184
|
-
throw new Error(
|
|
185
|
-
`Invalid ${validation.field} format: ${fieldValue}. Must be a ${validation.error}`
|
|
186
|
-
);
|
|
187
|
-
}
|
|
188
|
-
if (validation.validator && !validation.validator(fieldValue)) {
|
|
189
|
-
throw new Error(
|
|
190
|
-
`Invalid ${validation.field} value: ${fieldValue}. Must be a ${validation.error}`
|
|
191
|
-
);
|
|
192
|
-
}
|
|
193
|
-
return true;
|
|
194
|
-
}
|
|
195
|
-
function encodeCursor(c) {
|
|
196
|
-
return jsBase64.Base64.encodeURL(JSON.stringify(c));
|
|
197
|
-
}
|
|
198
|
-
function decodeCursor(token) {
|
|
199
|
-
if (!token) return null;
|
|
200
|
-
const decoded = JSON.parse(jsBase64.Base64.decode(token));
|
|
201
|
-
validateCursor(decoded);
|
|
202
|
-
return decoded;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
// src/utils/wait.ts
|
|
206
|
-
async function wait(time) {
|
|
207
|
-
return new Promise((res) => setTimeout(res, time));
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
// src/utils/poll.ts
|
|
211
|
-
function poll(fn, { interval }) {
|
|
212
|
-
let active = true;
|
|
213
|
-
const unwatch = () => active = false;
|
|
214
|
-
const watch = async () => {
|
|
215
|
-
await wait(interval);
|
|
216
|
-
const poll2 = async () => {
|
|
217
|
-
if (!active) return;
|
|
218
|
-
await fn({ unpoll: unwatch });
|
|
219
|
-
await wait(interval);
|
|
220
|
-
poll2();
|
|
221
|
-
};
|
|
222
|
-
poll2();
|
|
223
|
-
};
|
|
224
|
-
watch();
|
|
225
|
-
return unwatch;
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
// src/utils/retry.ts
|
|
229
|
-
var retry = async (fn, attempts = 3, delayMs = 50) => {
|
|
230
|
-
let lastErr;
|
|
231
|
-
for (let i = 0; i < attempts; i++) {
|
|
232
|
-
try {
|
|
233
|
-
return await fn();
|
|
234
|
-
} catch (err) {
|
|
235
|
-
lastErr = err;
|
|
236
|
-
if (i < attempts - 1) await new Promise((r) => setTimeout(r, delayMs));
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
throw lastErr;
|
|
240
|
-
};
|
|
241
|
-
|
|
242
247
|
// src/core/apiSchema/requests.ts
|
|
243
248
|
var MAX_LIMIT = 100;
|
|
244
249
|
var DEFAULT_LIMIT = 20;
|
|
@@ -416,7 +421,7 @@ var GetOffersQueryParams = v4.z.object({
|
|
|
416
421
|
(val) => {
|
|
417
422
|
if (!val) return true;
|
|
418
423
|
try {
|
|
419
|
-
const decoded =
|
|
424
|
+
const decoded = decode(val);
|
|
420
425
|
return decoded !== null;
|
|
421
426
|
} catch (_error) {
|
|
422
427
|
return false;
|
|
@@ -583,21 +588,12 @@ var MatchOffersQueryParams = v4.z.object({
|
|
|
583
588
|
description: "Filter by a specific offer creator address",
|
|
584
589
|
example: "0x1234567890123456789012345678901234567890"
|
|
585
590
|
}),
|
|
586
|
-
// Status filtering
|
|
587
|
-
status: v4.z.string().regex(/^[a-zA-Z_]+(,[a-zA-Z_]+)*$/, {
|
|
588
|
-
message: "Status must be comma-separated status values"
|
|
589
|
-
}).transform((val) => val.split(",")).refine((statuses) => statuses.every((status) => OfferStatusValues.includes(status)), {
|
|
590
|
-
message: `Invalid status value. Must be one of: ${OfferStatusValues.join(", ")}`
|
|
591
|
-
}).optional().meta({
|
|
592
|
-
description: `Filter by multiple statuses (comma-separated). Valid values: ${OfferStatusValues.join(", ")}. By default, only offers with 'valid' status are returned.`,
|
|
593
|
-
example: "valid,callback_error"
|
|
594
|
-
}),
|
|
595
591
|
// Pagination
|
|
596
592
|
cursor: v4.z.string().optional().refine(
|
|
597
593
|
(val) => {
|
|
598
594
|
if (!val) return true;
|
|
599
595
|
try {
|
|
600
|
-
const decoded =
|
|
596
|
+
const decoded = decode(val);
|
|
601
597
|
return decoded !== null;
|
|
602
598
|
} catch (_error) {
|
|
603
599
|
return false;
|
|
@@ -1024,8 +1020,10 @@ function memory(parameters) {
|
|
|
1024
1020
|
const consumedIds = /* @__PURE__ */ new Set();
|
|
1025
1021
|
const create = async (parameters2) => {
|
|
1026
1022
|
if (map.has(parameters2.offer.hash.toLowerCase())) return parameters2.offer.hash;
|
|
1023
|
+
const callbackId = getCallbackIdForOffer(parameters2.offer);
|
|
1027
1024
|
map.set(parameters2.offer.hash.toLowerCase(), {
|
|
1028
1025
|
...parameters2.offer,
|
|
1026
|
+
...callbackId ? { callbackId } : {},
|
|
1029
1027
|
status: parameters2.status,
|
|
1030
1028
|
metadata: parameters2.metadata
|
|
1031
1029
|
});
|
|
@@ -1120,7 +1118,7 @@ function memory(parameters) {
|
|
|
1120
1118
|
...o,
|
|
1121
1119
|
consumed: filled.get(o.chainId)?.get(o.offering.toLowerCase())?.get(o.nonce) || 0n
|
|
1122
1120
|
})).filter((o) => o.consumed < o.assets);
|
|
1123
|
-
const cursor =
|
|
1121
|
+
const cursor = decode(queryCursor);
|
|
1124
1122
|
if (cursor) {
|
|
1125
1123
|
if (cursor.sort !== sortBy || cursor.dir !== sortOrder) {
|
|
1126
1124
|
throw new Error("Cursor does not match the current sort parameters");
|
|
@@ -1218,11 +1216,35 @@ function memory(parameters) {
|
|
|
1218
1216
|
default:
|
|
1219
1217
|
base.expiry = last.expiry;
|
|
1220
1218
|
}
|
|
1221
|
-
nextCursor =
|
|
1219
|
+
nextCursor = encode(base);
|
|
1222
1220
|
}
|
|
1223
1221
|
offers = offers.slice(0, limit);
|
|
1222
|
+
const data = offers.map((o) => ({
|
|
1223
|
+
...mempool.Offer.from({
|
|
1224
|
+
offering: o.offering,
|
|
1225
|
+
assets: o.assets,
|
|
1226
|
+
rate: o.rate,
|
|
1227
|
+
maturity: mempool.Maturity.from(o.maturity),
|
|
1228
|
+
expiry: o.expiry,
|
|
1229
|
+
start: o.start,
|
|
1230
|
+
nonce: o.nonce,
|
|
1231
|
+
buy: o.buy,
|
|
1232
|
+
chainId: o.chainId,
|
|
1233
|
+
loanToken: o.loanToken,
|
|
1234
|
+
collaterals: o.collaterals.map((c) => ({ asset: c.asset, oracle: c.oracle, lltv: c.lltv })).sort((a, b) => a.asset.toLowerCase().localeCompare(b.asset.toLowerCase())),
|
|
1235
|
+
callback: {
|
|
1236
|
+
address: o.callback.address,
|
|
1237
|
+
data: o.callback.data,
|
|
1238
|
+
gasLimit: o.callback.gasLimit
|
|
1239
|
+
},
|
|
1240
|
+
...o.signature !== null && o.signature !== void 0 ? { signature: o.signature } : {}
|
|
1241
|
+
}),
|
|
1242
|
+
consumed: o.consumed,
|
|
1243
|
+
status: o.status,
|
|
1244
|
+
...o.metadata ? { metadata: o.metadata } : {}
|
|
1245
|
+
}));
|
|
1224
1246
|
return {
|
|
1225
|
-
offers,
|
|
1247
|
+
offers: data,
|
|
1226
1248
|
nextCursor
|
|
1227
1249
|
};
|
|
1228
1250
|
},
|
|
@@ -1237,7 +1259,6 @@ function memory(parameters) {
|
|
|
1237
1259
|
maxMaturity,
|
|
1238
1260
|
loanToken,
|
|
1239
1261
|
creator,
|
|
1240
|
-
status,
|
|
1241
1262
|
cursor: queryCursor,
|
|
1242
1263
|
limit = 20
|
|
1243
1264
|
} = params;
|
|
@@ -1248,7 +1269,7 @@ function memory(parameters) {
|
|
|
1248
1269
|
...o,
|
|
1249
1270
|
consumed: filled.get(o.chainId)?.get(o.offering.toLowerCase())?.get(o.nonce) || 0n
|
|
1250
1271
|
})).filter((o) => o.consumed < o.assets);
|
|
1251
|
-
const cursor =
|
|
1272
|
+
const cursor = decode(queryCursor);
|
|
1252
1273
|
if (cursor) {
|
|
1253
1274
|
if (cursor.sort !== "rate" || cursor.dir !== sortOrder) {
|
|
1254
1275
|
throw new Error("Cursor does not match the current sort parameters");
|
|
@@ -1283,7 +1304,7 @@ function memory(parameters) {
|
|
|
1283
1304
|
maxMaturity && (offers = offers.filter((o) => o.maturity <= maxMaturity));
|
|
1284
1305
|
loanToken && (offers = offers.filter((o) => o.loanToken.toLowerCase() === loanToken.toLowerCase()));
|
|
1285
1306
|
creator && (offers = offers.filter((o) => o.offering.toLowerCase() === creator.toLowerCase()));
|
|
1286
|
-
|
|
1307
|
+
offers = offers.filter((o) => ["valid"].includes(o.status));
|
|
1287
1308
|
const byGroup = /* @__PURE__ */ new Map();
|
|
1288
1309
|
for (const offer of offers) {
|
|
1289
1310
|
const groupKey = `${offer.chainId}-${offer.offering.toLowerCase()}-${offer.nonce}-${offer.buy}`;
|
|
@@ -1318,7 +1339,7 @@ function memory(parameters) {
|
|
|
1318
1339
|
let nextCursor = null;
|
|
1319
1340
|
if (offers.length > limit) {
|
|
1320
1341
|
const last = offers[limit - 1];
|
|
1321
|
-
nextCursor =
|
|
1342
|
+
nextCursor = encode({
|
|
1322
1343
|
sort: "rate",
|
|
1323
1344
|
dir: sortOrder,
|
|
1324
1345
|
hash: last.hash,
|
|
@@ -1326,8 +1347,32 @@ function memory(parameters) {
|
|
|
1326
1347
|
});
|
|
1327
1348
|
}
|
|
1328
1349
|
offers = offers.slice(0, limit);
|
|
1350
|
+
const data = offers.map((o) => ({
|
|
1351
|
+
...mempool.Offer.from({
|
|
1352
|
+
offering: o.offering,
|
|
1353
|
+
assets: o.assets,
|
|
1354
|
+
rate: o.rate,
|
|
1355
|
+
maturity: mempool.Maturity.from(o.maturity),
|
|
1356
|
+
expiry: o.expiry,
|
|
1357
|
+
start: o.start,
|
|
1358
|
+
nonce: o.nonce,
|
|
1359
|
+
buy: o.buy,
|
|
1360
|
+
chainId: o.chainId,
|
|
1361
|
+
loanToken: o.loanToken,
|
|
1362
|
+
collaterals: o.collaterals.map((c) => ({ asset: c.asset, oracle: c.oracle, lltv: c.lltv })).sort((a, b) => a.asset.toLowerCase().localeCompare(b.asset.toLowerCase())),
|
|
1363
|
+
callback: {
|
|
1364
|
+
address: o.callback.address,
|
|
1365
|
+
data: o.callback.data,
|
|
1366
|
+
gasLimit: o.callback.gasLimit
|
|
1367
|
+
},
|
|
1368
|
+
...o.signature !== null && o.signature !== void 0 ? { signature: o.signature } : {}
|
|
1369
|
+
}),
|
|
1370
|
+
consumed: o.consumed,
|
|
1371
|
+
status: o.status,
|
|
1372
|
+
...o.metadata ? { metadata: o.metadata } : {}
|
|
1373
|
+
}));
|
|
1329
1374
|
return {
|
|
1330
|
-
offers,
|
|
1375
|
+
offers: data,
|
|
1331
1376
|
nextCursor
|
|
1332
1377
|
};
|
|
1333
1378
|
},
|
|
@@ -1434,7 +1479,6 @@ async function serve(parameters) {
|
|
|
1434
1479
|
maxMaturity: params.max_maturity,
|
|
1435
1480
|
loanToken: params.loan_token,
|
|
1436
1481
|
creator: params.creator,
|
|
1437
|
-
status: params.status,
|
|
1438
1482
|
cursor: params.cursor,
|
|
1439
1483
|
limit: params.limit
|
|
1440
1484
|
});
|
|
@@ -1550,6 +1594,140 @@ function handleAPIError(error2, c) {
|
|
|
1550
1594
|
});
|
|
1551
1595
|
}
|
|
1552
1596
|
|
|
1597
|
+
// src/Liquidity.ts
|
|
1598
|
+
var Liquidity_exports = {};
|
|
1599
|
+
__export(Liquidity_exports, {
|
|
1600
|
+
fetch: () => fetch2,
|
|
1601
|
+
fetchBalancesAndAllowances: () => fetchBalancesAndAllowances,
|
|
1602
|
+
serialize: () => serialize
|
|
1603
|
+
});
|
|
1604
|
+
async function fetchBalancesAndAllowances(parameters) {
|
|
1605
|
+
const { client, spender, pairs, options } = parameters;
|
|
1606
|
+
if (pairs.length === 0) return /* @__PURE__ */ new Map();
|
|
1607
|
+
const batchSize = Math.max(1, options?.batchSize ?? 5e3);
|
|
1608
|
+
const retryAttempts = Math.max(1, options?.retryAttempts ?? 3);
|
|
1609
|
+
const retryDelayMs = Math.max(0, options?.retryDelayMs ?? 50);
|
|
1610
|
+
const blockNumber = options?.blockNumber ? BigInt(options.blockNumber) : void 0;
|
|
1611
|
+
const out = /* @__PURE__ */ new Map();
|
|
1612
|
+
for (const pairsBatch of mempool.Utils.batch(pairs, batchSize)) {
|
|
1613
|
+
const balanceContracts = [];
|
|
1614
|
+
const allowanceContracts = [];
|
|
1615
|
+
for (const { user, token } of pairsBatch) {
|
|
1616
|
+
balanceContracts.push({
|
|
1617
|
+
address: token,
|
|
1618
|
+
abi: viem.erc20Abi,
|
|
1619
|
+
functionName: "balanceOf",
|
|
1620
|
+
args: [user]
|
|
1621
|
+
});
|
|
1622
|
+
allowanceContracts.push({
|
|
1623
|
+
address: token,
|
|
1624
|
+
abi: viem.erc20Abi,
|
|
1625
|
+
functionName: "allowance",
|
|
1626
|
+
args: [user, spender]
|
|
1627
|
+
});
|
|
1628
|
+
}
|
|
1629
|
+
const [balances, allowances] = await Promise.all([
|
|
1630
|
+
mempool.Utils.retry(
|
|
1631
|
+
() => client.multicall({
|
|
1632
|
+
allowFailure: false,
|
|
1633
|
+
contracts: balanceContracts,
|
|
1634
|
+
...blockNumber ? { blockNumber } : {}
|
|
1635
|
+
}),
|
|
1636
|
+
retryAttempts,
|
|
1637
|
+
retryDelayMs
|
|
1638
|
+
),
|
|
1639
|
+
mempool.Utils.retry(
|
|
1640
|
+
() => client.multicall({
|
|
1641
|
+
allowFailure: false,
|
|
1642
|
+
contracts: allowanceContracts,
|
|
1643
|
+
...blockNumber ? { blockNumber } : {}
|
|
1644
|
+
}),
|
|
1645
|
+
retryAttempts,
|
|
1646
|
+
retryDelayMs
|
|
1647
|
+
)
|
|
1648
|
+
]);
|
|
1649
|
+
for (let i = 0; i < pairsBatch.length; i++) {
|
|
1650
|
+
const { user, token } = pairsBatch[i];
|
|
1651
|
+
const balance = balances[i];
|
|
1652
|
+
const allowance = allowances[i];
|
|
1653
|
+
let perUser = out.get(user);
|
|
1654
|
+
if (!perUser) {
|
|
1655
|
+
perUser = /* @__PURE__ */ new Map();
|
|
1656
|
+
out.set(user, perUser);
|
|
1657
|
+
}
|
|
1658
|
+
perUser.set(token, { balance, allowance });
|
|
1659
|
+
}
|
|
1660
|
+
}
|
|
1661
|
+
return out;
|
|
1662
|
+
}
|
|
1663
|
+
async function fetch2(parameters) {
|
|
1664
|
+
const { client, chainId, spender, type, pairs, options } = parameters;
|
|
1665
|
+
if (type !== "buy_with_empty_callback" /* BuyWithEmptyCallback */)
|
|
1666
|
+
throw new Error(`CallbackType not implemented: ${type}`);
|
|
1667
|
+
const map = await fetchBalancesAndAllowances({
|
|
1668
|
+
client,
|
|
1669
|
+
spender,
|
|
1670
|
+
pairs: pairs.map(({ user, contract }) => ({ user, token: contract })),
|
|
1671
|
+
options
|
|
1672
|
+
});
|
|
1673
|
+
const out = [];
|
|
1674
|
+
for (const [user, perContract] of map) {
|
|
1675
|
+
for (const [contract, { balance, allowance }] of perContract) {
|
|
1676
|
+
const amount = balance < allowance ? balance : allowance;
|
|
1677
|
+
out.push(
|
|
1678
|
+
buildLiquidity({
|
|
1679
|
+
type,
|
|
1680
|
+
user,
|
|
1681
|
+
contract,
|
|
1682
|
+
chainId,
|
|
1683
|
+
amount: amount.toString(),
|
|
1684
|
+
index: 0
|
|
1685
|
+
})
|
|
1686
|
+
);
|
|
1687
|
+
}
|
|
1688
|
+
}
|
|
1689
|
+
return out;
|
|
1690
|
+
}
|
|
1691
|
+
function serialize(liquidity) {
|
|
1692
|
+
const normalized = {
|
|
1693
|
+
userPosition: {
|
|
1694
|
+
id: liquidity.userPosition.id,
|
|
1695
|
+
availableLiquidityQueueId: liquidity.userPosition.availableLiquidityQueueId,
|
|
1696
|
+
user: liquidity.userPosition.user,
|
|
1697
|
+
chainId: String(liquidity.userPosition.chainId),
|
|
1698
|
+
amount: String(liquidity.userPosition.amount)
|
|
1699
|
+
},
|
|
1700
|
+
queues: liquidity.queues.map((queueWithPool) => ({
|
|
1701
|
+
queue: {
|
|
1702
|
+
queueId: queueWithPool.queue.queueId,
|
|
1703
|
+
availableLiquidityPoolId: queueWithPool.queue.availableLiquidityPoolId,
|
|
1704
|
+
index: queueWithPool.queue.index
|
|
1705
|
+
},
|
|
1706
|
+
pool: {
|
|
1707
|
+
id: queueWithPool.pool.id,
|
|
1708
|
+
amount: String(queueWithPool.pool.amount)
|
|
1709
|
+
}
|
|
1710
|
+
})).sort(
|
|
1711
|
+
(left, right) => {
|
|
1712
|
+
const leftQueueId = left.queue.queueId || "";
|
|
1713
|
+
const rightQueueId = right.queue.queueId || "";
|
|
1714
|
+
if (leftQueueId < rightQueueId) return -1;
|
|
1715
|
+
if (leftQueueId > rightQueueId) return 1;
|
|
1716
|
+
const leftPoolId = left.pool.id;
|
|
1717
|
+
const rightPoolId = right.pool.id;
|
|
1718
|
+
if (leftPoolId < rightPoolId) return -1;
|
|
1719
|
+
if (leftPoolId > rightPoolId) return 1;
|
|
1720
|
+
const leftIndex = left.queue.index;
|
|
1721
|
+
const rightIndex = right.queue.index;
|
|
1722
|
+
if (leftIndex < rightIndex) return -1;
|
|
1723
|
+
if (leftIndex > rightIndex) return 1;
|
|
1724
|
+
return 0;
|
|
1725
|
+
}
|
|
1726
|
+
)
|
|
1727
|
+
};
|
|
1728
|
+
return JSON.stringify(normalized);
|
|
1729
|
+
}
|
|
1730
|
+
|
|
1553
1731
|
// src/Logger.ts
|
|
1554
1732
|
var Logger_exports = {};
|
|
1555
1733
|
__export(Logger_exports, {
|
|
@@ -1672,14 +1850,14 @@ async function run(parameters) {
|
|
|
1672
1850
|
// src/ValidationRule.ts
|
|
1673
1851
|
var ValidationRule_exports = {};
|
|
1674
1852
|
__export(ValidationRule_exports, {
|
|
1675
|
-
batch: () =>
|
|
1853
|
+
batch: () => batch,
|
|
1676
1854
|
morpho: () => morpho,
|
|
1677
1855
|
single: () => single
|
|
1678
1856
|
});
|
|
1679
1857
|
function single(name, run2) {
|
|
1680
1858
|
return { kind: "single", name, run: run2 };
|
|
1681
1859
|
}
|
|
1682
|
-
function
|
|
1860
|
+
function batch(name, run2) {
|
|
1683
1861
|
return { kind: "batch", name, run: run2 };
|
|
1684
1862
|
}
|
|
1685
1863
|
function morpho() {
|
|
@@ -1721,11 +1899,13 @@ function morpho() {
|
|
|
1721
1899
|
}
|
|
1722
1900
|
|
|
1723
1901
|
exports.ApiSchema = apiSchema_exports;
|
|
1902
|
+
exports.Callback = Callback_exports;
|
|
1903
|
+
exports.Cursor = Cursor_exports;
|
|
1904
|
+
exports.Liquidity = Liquidity_exports;
|
|
1724
1905
|
exports.Logger = Logger_exports;
|
|
1725
1906
|
exports.OfferStore = OfferStore_exports;
|
|
1726
1907
|
exports.Router = router_exports;
|
|
1727
1908
|
exports.RouterOffer = RouterOffer_exports;
|
|
1728
|
-
exports.Utils = utils_exports;
|
|
1729
1909
|
exports.Validation = Validation_exports;
|
|
1730
1910
|
exports.ValidationRule = ValidationRule_exports;
|
|
1731
1911
|
Object.keys(mempool).forEach(function (k) {
|