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