@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.
@@ -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 loanToken = accounts.privateKeyToAccount(accounts.generatePrivateKey()).address;
1284
- const maturity = from3("end_of_month");
1285
- const expiry = from3("end_of_week") - 1;
1286
- const lltv = from(0.965);
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: BigInt(Math.floor(Math.random() * 1e6)),
1290
- rate: BigInt(Math.floor(Math.random() * 1e6)),
1352
+ offering: config?.offering ?? accounts.privateKeyToAccount(accounts.generatePrivateKey()).address,
1353
+ assets: assetsScaled,
1354
+ rate,
1291
1355
  maturity,
1292
- expiry,
1293
- start: expiry - 10,
1356
+ expiry: config?.expiry ?? maturity - 1,
1357
+ start: config?.start ?? maturity - 10,
1294
1358
  nonce: BigInt(Math.floor(Math.random() * 1e6)),
1295
- buy: Math.random() > 0.5,
1296
- chainId: 1n,
1359
+ buy,
1360
+ chainId: chain.id,
1297
1361
  loanToken,
1298
- collaterals: [
1362
+ collaterals: config?.collaterals ?? [
1299
1363
  from2({
1300
- asset: viem.zeroAddress,
1364
+ asset: collateralAsset,
1301
1365
  oracle: viem.zeroAddress,
1302
1366
  lltv
1303
1367
  })
1304
1368
  ],
1305
- callback: {
1306
- address: viem.zeroAddress,
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;