@morpho-dev/router 0.1.17 → 0.1.18
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/README.md +6 -6
- package/dist/cli.js +204 -53
- package/dist/cli.js.map +1 -1
- package/dist/index.browser.d.cts +26 -4
- package/dist/index.browser.d.ts +26 -4
- package/dist/index.browser.js +93 -24
- package/dist/index.browser.js.map +1 -1
- package/dist/index.browser.mjs +93 -24
- package/dist/index.browser.mjs.map +1 -1
- package/dist/index.node.d.cts +170 -12
- package/dist/index.node.d.ts +170 -12
- package/dist/index.node.js +245 -24
- package/dist/index.node.js.map +1 -1
- package/dist/index.node.mjs +245 -25
- package/dist/index.node.mjs.map +1 -1
- package/package.json +5 -5
package/dist/index.node.js
CHANGED
|
@@ -447,8 +447,12 @@ var chains = {
|
|
|
447
447
|
[
|
|
448
448
|
"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
|
449
449
|
// USDC
|
|
450
|
-
"0x6B175474E89094C44Da98b954EedeAC495271d0F"
|
|
450
|
+
"0x6B175474E89094C44Da98b954EedeAC495271d0F",
|
|
451
451
|
// DAI
|
|
452
|
+
"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
|
|
453
|
+
// WETH
|
|
454
|
+
"0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599"
|
|
455
|
+
// WBTC
|
|
452
456
|
].map((address) => address.toLowerCase())
|
|
453
457
|
),
|
|
454
458
|
morpho: "0x0000000000000000000000000000000000000000",
|
|
@@ -471,8 +475,12 @@ var chains = {
|
|
|
471
475
|
[
|
|
472
476
|
"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
|
|
473
477
|
// USDC
|
|
474
|
-
"0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb"
|
|
478
|
+
"0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb",
|
|
475
479
|
// DAI
|
|
480
|
+
"0x4200000000000000000000000000000000000006",
|
|
481
|
+
// WETH
|
|
482
|
+
"0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599"
|
|
483
|
+
// WBTC
|
|
476
484
|
].map((address) => address.toLowerCase())
|
|
477
485
|
),
|
|
478
486
|
morpho: "0x0000000000000000000000000000000000000000",
|
|
@@ -495,8 +503,12 @@ var chains = {
|
|
|
495
503
|
[
|
|
496
504
|
"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
|
497
505
|
// USDC
|
|
498
|
-
"0x6B175474E89094C44Da98b954EedeAC495271d0F"
|
|
506
|
+
"0x6B175474E89094C44Da98b954EedeAC495271d0F",
|
|
499
507
|
// DAI
|
|
508
|
+
"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
|
|
509
|
+
// WETH
|
|
510
|
+
"0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599"
|
|
511
|
+
// WBTC
|
|
500
512
|
].map((address) => address.toLowerCase())
|
|
501
513
|
),
|
|
502
514
|
morpho: "0x11a002d45db720ed47a80d2f3489cba5b833eaf5",
|
|
@@ -520,8 +532,12 @@ var chains = {
|
|
|
520
532
|
[
|
|
521
533
|
"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
|
522
534
|
// USDC
|
|
523
|
-
"0x6B175474E89094C44Da98b954EedeAC495271d0F"
|
|
535
|
+
"0x6B175474E89094C44Da98b954EedeAC495271d0F",
|
|
524
536
|
// DAI
|
|
537
|
+
"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
|
|
538
|
+
// WETH
|
|
539
|
+
"0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599"
|
|
540
|
+
// WBTC
|
|
525
541
|
].map((address) => address.toLowerCase())
|
|
526
542
|
),
|
|
527
543
|
morpho: "0x23DFBc4B8B80C14CC5e25011B8491f268395BAd6",
|
|
@@ -1279,39 +1295,92 @@ function fromSnakeCase3(input) {
|
|
|
1279
1295
|
function toSnakeCase2(offer) {
|
|
1280
1296
|
return toSnakeCase(offer);
|
|
1281
1297
|
}
|
|
1282
|
-
function random2() {
|
|
1283
|
-
const
|
|
1284
|
-
const
|
|
1285
|
-
const
|
|
1286
|
-
const
|
|
1298
|
+
function random2(config) {
|
|
1299
|
+
const chain = config?.chains ? config.chains[Math.floor(Math.random() * config.chains.length)] : chains.ethereum;
|
|
1300
|
+
const loanToken = config?.loanTokens ? config.loanTokens[Math.floor(Math.random() * config.loanTokens.length)] : accounts.privateKeyToAccount(accounts.generatePrivateKey()).address;
|
|
1301
|
+
const collateralCandidates = config?.collateralTokens ? config.collateralTokens.filter((a) => a !== loanToken) : [accounts.privateKeyToAccount(accounts.generatePrivateKey()).address];
|
|
1302
|
+
const collateralAsset = collateralCandidates[Math.floor(Math.random() * collateralCandidates.length)];
|
|
1303
|
+
const maturityOption = weightedChoice([
|
|
1304
|
+
["end_of_month", 1],
|
|
1305
|
+
["end_of_next_month", 1]
|
|
1306
|
+
]);
|
|
1307
|
+
const maturity = config?.maturity ?? from3(maturityOption);
|
|
1308
|
+
const lltv = from(
|
|
1309
|
+
weightedChoice([
|
|
1310
|
+
[0.385, 1],
|
|
1311
|
+
[0.5, 1],
|
|
1312
|
+
[0.625, 2],
|
|
1313
|
+
[0.77, 8],
|
|
1314
|
+
[0.86, 10],
|
|
1315
|
+
[0.915, 8],
|
|
1316
|
+
[0.945, 6],
|
|
1317
|
+
[0.965, 4],
|
|
1318
|
+
[0.98, 2]
|
|
1319
|
+
])
|
|
1320
|
+
);
|
|
1321
|
+
const buy = config?.buy !== void 0 ? config.buy : Math.random() > 0.5;
|
|
1322
|
+
const ONE = 1000000000000000000n;
|
|
1323
|
+
const qMin = buy ? 16 : 4;
|
|
1324
|
+
const qMax = buy ? 32 : 16;
|
|
1325
|
+
const len = qMax - qMin + 1;
|
|
1326
|
+
const ratePairs = Array.from(
|
|
1327
|
+
{ length: len },
|
|
1328
|
+
(_, idx) => {
|
|
1329
|
+
const q = qMin + idx;
|
|
1330
|
+
const scaledRate = BigInt(q) * (ONE / 4n);
|
|
1331
|
+
const weight = buy ? 1 + idx : 1 + (len - 1 - idx);
|
|
1332
|
+
return [scaledRate, weight];
|
|
1333
|
+
}
|
|
1334
|
+
);
|
|
1335
|
+
const rate = config?.rate ?? weightedChoice(ratePairs);
|
|
1336
|
+
const loanTokenDecimals = config?.assetsDecimals?.[loanToken] ?? 18;
|
|
1337
|
+
const unit = BigInt(10) ** BigInt(loanTokenDecimals);
|
|
1338
|
+
const amountBase = BigInt(100 + Math.floor(Math.random() * (1e6 - 100 + 1)));
|
|
1339
|
+
const assetsScaled = config?.assets ?? amountBase * unit;
|
|
1340
|
+
const consumed2 = config?.consumed !== void 0 ? config.consumed : Math.random() < 0.8 ? 0n : assetsScaled * BigInt(1 + Math.floor(Math.random() * 900)) / 1000n;
|
|
1341
|
+
const callbackBySide = (() => {
|
|
1342
|
+
if (buy) return { address: viem.zeroAddress, data: "0x", gasLimit: 0n };
|
|
1343
|
+
const sellCallbackAddress = WhitelistedCallbackAddresses["sell_erc20_callback" /* SellERC20Callback */][0].toLowerCase();
|
|
1344
|
+
const amount = assetsScaled * 1000000000000000000000n;
|
|
1345
|
+
const data = encodeSellERC20Callback({
|
|
1346
|
+
collaterals: [collateralAsset],
|
|
1347
|
+
amounts: [amount]
|
|
1348
|
+
});
|
|
1349
|
+
return { address: sellCallbackAddress, data, gasLimit: 500000n };
|
|
1350
|
+
})();
|
|
1287
1351
|
const offer = from5({
|
|
1288
|
-
offering: accounts.privateKeyToAccount(accounts.generatePrivateKey()).address,
|
|
1289
|
-
assets:
|
|
1290
|
-
rate
|
|
1352
|
+
offering: config?.offering ?? accounts.privateKeyToAccount(accounts.generatePrivateKey()).address,
|
|
1353
|
+
assets: assetsScaled,
|
|
1354
|
+
rate,
|
|
1291
1355
|
maturity,
|
|
1292
|
-
expiry,
|
|
1293
|
-
start:
|
|
1356
|
+
expiry: config?.expiry ?? maturity - 1,
|
|
1357
|
+
start: config?.start ?? maturity - 10,
|
|
1294
1358
|
nonce: BigInt(Math.floor(Math.random() * 1e6)),
|
|
1295
|
-
buy
|
|
1296
|
-
chainId:
|
|
1359
|
+
buy,
|
|
1360
|
+
chainId: chain.id,
|
|
1297
1361
|
loanToken,
|
|
1298
|
-
collaterals: [
|
|
1362
|
+
collaterals: config?.collaterals ?? [
|
|
1299
1363
|
from2({
|
|
1300
|
-
asset:
|
|
1364
|
+
asset: collateralAsset,
|
|
1301
1365
|
oracle: viem.zeroAddress,
|
|
1302
1366
|
lltv
|
|
1303
1367
|
})
|
|
1304
1368
|
],
|
|
1305
|
-
callback:
|
|
1306
|
-
|
|
1307
|
-
data: "0x",
|
|
1308
|
-
gasLimit: 0n
|
|
1309
|
-
},
|
|
1310
|
-
consumed: 0n,
|
|
1369
|
+
callback: config?.callback ?? callbackBySide,
|
|
1370
|
+
consumed: consumed2,
|
|
1311
1371
|
blockNumber: Math.floor(Math.random() * Number.MAX_SAFE_INTEGER)
|
|
1312
1372
|
});
|
|
1313
1373
|
return offer;
|
|
1314
1374
|
}
|
|
1375
|
+
var weightedChoice = (pairs) => {
|
|
1376
|
+
const total = pairs.reduce((sum, [, weight]) => sum + weight, 0);
|
|
1377
|
+
let roll = Math.random() * total;
|
|
1378
|
+
for (const [value, weight] of pairs) {
|
|
1379
|
+
roll -= weight;
|
|
1380
|
+
if (roll < 0) return value;
|
|
1381
|
+
}
|
|
1382
|
+
return pairs[0][0];
|
|
1383
|
+
};
|
|
1315
1384
|
var domain = (chainId) => ({
|
|
1316
1385
|
chainId,
|
|
1317
1386
|
verifyingContract: viem.zeroAddress
|
|
@@ -6141,6 +6210,157 @@ function serve(parameters) {
|
|
|
6141
6210
|
});
|
|
6142
6211
|
}
|
|
6143
6212
|
|
|
6213
|
+
// src/client/Client.ts
|
|
6214
|
+
var Client_exports = {};
|
|
6215
|
+
__export(Client_exports, {
|
|
6216
|
+
HttpForbiddenError: () => HttpForbiddenError,
|
|
6217
|
+
HttpGetApiFailedError: () => HttpGetApiFailedError,
|
|
6218
|
+
HttpRateLimitError: () => HttpRateLimitError,
|
|
6219
|
+
HttpUnauthorizedError: () => HttpUnauthorizedError,
|
|
6220
|
+
InvalidUrlError: () => InvalidUrlError,
|
|
6221
|
+
connect: () => connect3,
|
|
6222
|
+
getObligations: () => getObligations2,
|
|
6223
|
+
getOffers: () => getOffers2
|
|
6224
|
+
});
|
|
6225
|
+
function connect3(options) {
|
|
6226
|
+
const u = new URL(options?.url || "https://router.morpho.dev");
|
|
6227
|
+
if (u.protocol !== "http:" && u.protocol !== "https:") {
|
|
6228
|
+
throw new InvalidUrlError(u.toString());
|
|
6229
|
+
}
|
|
6230
|
+
const headers = options?.headers ?? new Headers();
|
|
6231
|
+
headers.set("Content-Type", "application/json");
|
|
6232
|
+
options?.apiKey !== void 0 ? headers.set("X-API-Key", options.apiKey) : null;
|
|
6233
|
+
const config = {
|
|
6234
|
+
url: u,
|
|
6235
|
+
headers
|
|
6236
|
+
};
|
|
6237
|
+
return {
|
|
6238
|
+
...config,
|
|
6239
|
+
getOffers: (parameters) => getOffers2(config, parameters),
|
|
6240
|
+
getObligations: (parameters) => getObligations2(config, parameters)
|
|
6241
|
+
};
|
|
6242
|
+
}
|
|
6243
|
+
async function getOffers2(config, parameters) {
|
|
6244
|
+
const url = new URL(`${config.url.toString()}v1/offers`);
|
|
6245
|
+
url.searchParams.set("side", parameters.side);
|
|
6246
|
+
url.searchParams.set("obligation_id", parameters.obligationId.toString());
|
|
6247
|
+
if (parameters.cursor) {
|
|
6248
|
+
url.searchParams.set("cursor", parameters.cursor);
|
|
6249
|
+
}
|
|
6250
|
+
if (parameters.limit !== void 0) {
|
|
6251
|
+
url.searchParams.set("limit", parameters.limit.toString());
|
|
6252
|
+
}
|
|
6253
|
+
const { cursor: returnedCursor, data: offers2 } = await getApi(config, url);
|
|
6254
|
+
const routerOffers = offers2.map(Offer_exports.fromSnakeCase);
|
|
6255
|
+
return {
|
|
6256
|
+
cursor: returnedCursor,
|
|
6257
|
+
offers: routerOffers
|
|
6258
|
+
};
|
|
6259
|
+
}
|
|
6260
|
+
async function getObligations2(config, parameters) {
|
|
6261
|
+
const url = new URL(`${config.url.toString()}v1/obligations`);
|
|
6262
|
+
if (parameters?.cursor !== void 0) {
|
|
6263
|
+
url.searchParams.set("cursor", parameters.cursor);
|
|
6264
|
+
}
|
|
6265
|
+
if (parameters?.limit !== void 0) {
|
|
6266
|
+
url.searchParams.set("limit", parameters.limit.toString());
|
|
6267
|
+
}
|
|
6268
|
+
const { cursor: returnedCursor, data: items } = await getApi(config, url);
|
|
6269
|
+
const obligations2 = items.map((item) => {
|
|
6270
|
+
const obligation = Obligation_exports.fromSnakeCase(item);
|
|
6271
|
+
const { obligationId: _, ...returned } = {
|
|
6272
|
+
id: () => Obligation_exports.id(obligation),
|
|
6273
|
+
...obligation,
|
|
6274
|
+
...Quote_exports.fromSnakeCase({ obligation_id: item.id, ask: item.ask, bid: item.bid })
|
|
6275
|
+
};
|
|
6276
|
+
return returned;
|
|
6277
|
+
});
|
|
6278
|
+
return {
|
|
6279
|
+
cursor: returnedCursor,
|
|
6280
|
+
obligations: obligations2
|
|
6281
|
+
};
|
|
6282
|
+
}
|
|
6283
|
+
async function getApi(config, url) {
|
|
6284
|
+
const pathname = url.pathname;
|
|
6285
|
+
let action;
|
|
6286
|
+
switch (true) {
|
|
6287
|
+
case pathname.includes("/v1/offers"):
|
|
6288
|
+
action = "get_offers";
|
|
6289
|
+
break;
|
|
6290
|
+
case pathname.includes("/v1/obligations"):
|
|
6291
|
+
action = "get_obligations";
|
|
6292
|
+
break;
|
|
6293
|
+
default:
|
|
6294
|
+
throw new HttpGetApiFailedError("Unknown endpoint", {
|
|
6295
|
+
details: `Unsupported path: ${pathname}`
|
|
6296
|
+
});
|
|
6297
|
+
}
|
|
6298
|
+
const schemaParseResult = safeParse(action, Object.fromEntries(url.searchParams));
|
|
6299
|
+
if (!schemaParseResult.success) {
|
|
6300
|
+
throw new HttpGetApiFailedError(`Invalid URL parameters`, {
|
|
6301
|
+
details: schemaParseResult.error.issues[0]?.message
|
|
6302
|
+
});
|
|
6303
|
+
}
|
|
6304
|
+
const response = await fetch(url.toString(), {
|
|
6305
|
+
method: "GET",
|
|
6306
|
+
headers: config.headers
|
|
6307
|
+
});
|
|
6308
|
+
if (!response.ok) {
|
|
6309
|
+
switch (response.status) {
|
|
6310
|
+
case 401:
|
|
6311
|
+
throw new HttpUnauthorizedError();
|
|
6312
|
+
case 403:
|
|
6313
|
+
throw new HttpForbiddenError();
|
|
6314
|
+
case 429:
|
|
6315
|
+
throw new HttpRateLimitError();
|
|
6316
|
+
}
|
|
6317
|
+
throw new HttpGetApiFailedError(`GET request returned ${response.status}`, {
|
|
6318
|
+
details: await response.text()
|
|
6319
|
+
});
|
|
6320
|
+
}
|
|
6321
|
+
return response.json();
|
|
6322
|
+
}
|
|
6323
|
+
var InvalidUrlError = class extends BaseError {
|
|
6324
|
+
name = "Router.InvalidUrlError";
|
|
6325
|
+
constructor(url) {
|
|
6326
|
+
super(`URL "${url}" is not http/https.`);
|
|
6327
|
+
}
|
|
6328
|
+
};
|
|
6329
|
+
var HttpUnauthorizedError = class extends BaseError {
|
|
6330
|
+
name = "Router.HttpUnauthorizedError";
|
|
6331
|
+
constructor() {
|
|
6332
|
+
super("Unauthorized.", {
|
|
6333
|
+
metaMessages: ["Ensure that an API key is provided."]
|
|
6334
|
+
});
|
|
6335
|
+
}
|
|
6336
|
+
};
|
|
6337
|
+
var HttpForbiddenError = class extends BaseError {
|
|
6338
|
+
name = "Router.HttpForbiddenError";
|
|
6339
|
+
constructor() {
|
|
6340
|
+
super("Forbidden.", {
|
|
6341
|
+
metaMessages: ["Ensure that the API key is valid."]
|
|
6342
|
+
});
|
|
6343
|
+
}
|
|
6344
|
+
};
|
|
6345
|
+
var HttpRateLimitError = class extends BaseError {
|
|
6346
|
+
name = "Router.HttpRateLimitError";
|
|
6347
|
+
constructor() {
|
|
6348
|
+
super("Rate limit exceeded.", {
|
|
6349
|
+
metaMessages: [
|
|
6350
|
+
"The number of allowed requests has been exceeded. You must wait for the rate limit to reset."
|
|
6351
|
+
]
|
|
6352
|
+
});
|
|
6353
|
+
}
|
|
6354
|
+
};
|
|
6355
|
+
var HttpGetApiFailedError = class extends BaseError {
|
|
6356
|
+
name = "Router.HttpGetApiFailedError";
|
|
6357
|
+
constructor(message, { details } = {}) {
|
|
6358
|
+
super(message, {
|
|
6359
|
+
metaMessages: [details]
|
|
6360
|
+
});
|
|
6361
|
+
}
|
|
6362
|
+
};
|
|
6363
|
+
|
|
6144
6364
|
exports.Abi = Abi_exports;
|
|
6145
6365
|
exports.BrandTypeId = BrandTypeId;
|
|
6146
6366
|
exports.Callback = Callback_exports;
|
|
@@ -6173,6 +6393,7 @@ exports.OpenApi = OpenApi;
|
|
|
6173
6393
|
exports.PG = PG_exports;
|
|
6174
6394
|
exports.Quote = Quote_exports;
|
|
6175
6395
|
exports.RouterApi = RouterApi_exports;
|
|
6396
|
+
exports.RouterClient = Client_exports;
|
|
6176
6397
|
exports.RouterIndexer = RouterIndexer_exports;
|
|
6177
6398
|
exports.RouterStatusResponse = RouterStatusResponse;
|
|
6178
6399
|
exports.Services = Services_exports;
|