@morpho-dev/router 0.0.10 → 0.0.12

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.
@@ -0,0 +1,603 @@
1
+ 'use strict';
2
+
3
+ var mempool = require('@morpho-dev/mempool');
4
+ var chains$1 = require('viem/chains');
5
+ var viem = require('viem');
6
+
7
+ var __defProp = Object.defineProperty;
8
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
9
+ var __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
+ };
13
+ var __publicField = (obj, key, value) => __defNormalProp(obj, key + "" , value);
14
+
15
+ // src/Chain.ts
16
+ var Chain_exports = {};
17
+ __export(Chain_exports, {
18
+ ChainId: () => ChainId,
19
+ chainIds: () => chainIds,
20
+ chainNames: () => chainNames,
21
+ chains: () => chains,
22
+ getChain: () => getChain
23
+ });
24
+ var chainNames = ["ethereum", "base"];
25
+ var ChainId = {
26
+ ETHEREUM: BigInt(chains$1.mainnet.id),
27
+ BASE: BigInt(chains$1.base.id)
28
+ };
29
+ var chainIds = new Set(Object.values(ChainId));
30
+ var chainNameLookup = new Map(Object.entries(ChainId).map(([key, value]) => [value, key]));
31
+ function getChain(chainId) {
32
+ const chainName = chainNameLookup.get(chainId)?.toLowerCase();
33
+ if (!chainName) {
34
+ return void 0;
35
+ }
36
+ return chains[chainName];
37
+ }
38
+ var chains = {
39
+ ethereum: {
40
+ ...chains$1.mainnet,
41
+ id: ChainId.ETHEREUM,
42
+ name: "ethereum",
43
+ whitelistedAssets: new Set(
44
+ [
45
+ "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
46
+ // USDC
47
+ "0x6B175474E89094C44Da98b954EedeAC495271d0F"
48
+ // DAI
49
+ ].map((address) => address.toLowerCase())
50
+ ),
51
+ morpho: "0x0000000000000000000000000000000000000000"
52
+ },
53
+ base: {
54
+ ...chains$1.base,
55
+ id: ChainId.BASE,
56
+ name: "base",
57
+ whitelistedAssets: new Set(
58
+ [
59
+ "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
60
+ // USDC
61
+ "0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb"
62
+ // DAI
63
+ ].map((address) => address.toLowerCase())
64
+ ),
65
+ morpho: "0x0000000000000000000000000000000000000000"
66
+ }
67
+ };
68
+
69
+ // src/core/index.ts
70
+ var core_exports = {};
71
+ __export(core_exports, {
72
+ HttpForbiddenError: () => HttpForbiddenError,
73
+ HttpGetOffersFailedError: () => HttpGetOffersFailedError,
74
+ HttpRateLimitError: () => HttpRateLimitError,
75
+ HttpUnauthorizedError: () => HttpUnauthorizedError,
76
+ InvalidUrlError: () => InvalidUrlError,
77
+ connect: () => connect,
78
+ get: () => get,
79
+ match: () => match
80
+ });
81
+ var MAX_BATCH_SIZE = 100;
82
+ function connect(opts) {
83
+ const u = new URL(opts?.url || "https://router.morpho.dev");
84
+ if (u.protocol !== "http:" && u.protocol !== "https:") {
85
+ throw new InvalidUrlError(u.toString());
86
+ }
87
+ const headers = new Headers();
88
+ headers.set("Content-Type", "application/json");
89
+ opts?.apiKey !== void 0 ? headers.set("X-API-Key", opts.apiKey) : null;
90
+ const config = {
91
+ url: u,
92
+ headers
93
+ };
94
+ return {
95
+ ...config,
96
+ get: (parameters) => get(config, parameters),
97
+ match: (parameters) => match(config, parameters)
98
+ };
99
+ }
100
+ async function get(config, parameters) {
101
+ const url = new URL(`${config.url.toString()}v1/offers`);
102
+ if (parameters.creators?.length) {
103
+ url.searchParams.set("creators", parameters.creators.join(","));
104
+ }
105
+ if (parameters.side) {
106
+ url.searchParams.set("side", parameters.side);
107
+ }
108
+ if (parameters.chains?.length) {
109
+ url.searchParams.set("chains", parameters.chains.join(","));
110
+ }
111
+ if (parameters.loanTokens?.length) {
112
+ url.searchParams.set("loan_tokens", parameters.loanTokens.join(","));
113
+ }
114
+ if (parameters.status?.length) {
115
+ url.searchParams.set("status", parameters.status.join(","));
116
+ }
117
+ if (parameters.callbackAddresses?.length) {
118
+ url.searchParams.set("callback_addresses", parameters.callbackAddresses.join(","));
119
+ }
120
+ if (parameters.minAmount !== void 0) {
121
+ url.searchParams.set("min_amount", parameters.minAmount.toString());
122
+ }
123
+ if (parameters.maxAmount !== void 0) {
124
+ url.searchParams.set("max_amount", parameters.maxAmount.toString());
125
+ }
126
+ if (parameters.minRate !== void 0) {
127
+ url.searchParams.set("min_rate", parameters.minRate.toString());
128
+ }
129
+ if (parameters.maxRate !== void 0) {
130
+ url.searchParams.set("max_rate", parameters.maxRate.toString());
131
+ }
132
+ if (parameters.minMaturity !== void 0) {
133
+ url.searchParams.set("min_maturity", parameters.minMaturity.toString());
134
+ }
135
+ if (parameters.maxMaturity !== void 0) {
136
+ url.searchParams.set("max_maturity", parameters.maxMaturity.toString());
137
+ }
138
+ if (parameters.minExpiry !== void 0) {
139
+ url.searchParams.set("min_expiry", parameters.minExpiry.toString());
140
+ }
141
+ if (parameters.maxExpiry !== void 0) {
142
+ url.searchParams.set("max_expiry", parameters.maxExpiry.toString());
143
+ }
144
+ if (parameters.collateralAssets?.length) {
145
+ url.searchParams.set("collateral_assets", parameters.collateralAssets.join(","));
146
+ }
147
+ if (parameters.collateralOracles?.length) {
148
+ url.searchParams.set("collateral_oracles", parameters.collateralOracles.join(","));
149
+ }
150
+ if (parameters.collateralTuple?.length) {
151
+ const tupleStr = parameters.collateralTuple.map(({ asset, oracle, lltv }) => {
152
+ let result = asset;
153
+ if (oracle) {
154
+ result += `:${oracle}`;
155
+ } else if (lltv !== void 0) {
156
+ result += `:`;
157
+ }
158
+ if (lltv !== void 0) result += `:${lltv}`;
159
+ return result;
160
+ }).join("#");
161
+ url.searchParams.set("collateral_tuple", tupleStr);
162
+ }
163
+ if (parameters.minLltv !== void 0) {
164
+ url.searchParams.set("min_lltv", parameters.minLltv.toString());
165
+ }
166
+ if (parameters.maxLltv !== void 0) {
167
+ url.searchParams.set("max_lltv", parameters.maxLltv.toString());
168
+ }
169
+ if (parameters.sortBy) {
170
+ url.searchParams.set("sort_by", parameters.sortBy);
171
+ }
172
+ if (parameters.sortOrder) {
173
+ url.searchParams.set("sort_order", parameters.sortOrder);
174
+ }
175
+ if (parameters.cursor) {
176
+ url.searchParams.set("cursor", parameters.cursor);
177
+ }
178
+ if (parameters.limit !== void 0) {
179
+ url.searchParams.set("limit", parameters.limit.toString());
180
+ }
181
+ const { cursor: returnedCursor, data: offers } = await getApi(config, url);
182
+ return {
183
+ cursor: returnedCursor,
184
+ offers: offers.map((offer) => {
185
+ const baseOffer = mempool.Offer.fromSnakeCase(offer);
186
+ return {
187
+ ...baseOffer,
188
+ status: offer.status,
189
+ metadata: offer.metadata
190
+ };
191
+ })
192
+ };
193
+ }
194
+ async function match(config, parameters) {
195
+ const url = new URL(`${config.url.toString()}v1/match-offers`);
196
+ url.searchParams.set("side", parameters.side);
197
+ url.searchParams.set("chain_id", parameters.chainId.toString());
198
+ if (parameters.rate !== void 0) {
199
+ url.searchParams.set("rate", parameters.rate.toString());
200
+ }
201
+ if (parameters.collaterals?.length) {
202
+ const collateralsStr = parameters.collaterals.map(({ asset, oracle, lltv }) => `${asset}:${oracle}:${lltv}`).join("#");
203
+ url.searchParams.set("collaterals", collateralsStr);
204
+ }
205
+ if (parameters.maturity !== void 0) {
206
+ url.searchParams.set("maturity", parameters.maturity.toString());
207
+ }
208
+ if (parameters.minMaturity !== void 0) {
209
+ url.searchParams.set("min_maturity", parameters.minMaturity.toString());
210
+ }
211
+ if (parameters.maxMaturity !== void 0) {
212
+ url.searchParams.set("max_maturity", parameters.maxMaturity.toString());
213
+ }
214
+ if (parameters.loanToken) {
215
+ url.searchParams.set("loan_token", parameters.loanToken);
216
+ }
217
+ if (parameters.creator) {
218
+ url.searchParams.set("creator", parameters.creator);
219
+ }
220
+ if (parameters.status?.length) {
221
+ url.searchParams.set("status", parameters.status.join(","));
222
+ }
223
+ if (parameters.cursor) {
224
+ url.searchParams.set("cursor", parameters.cursor);
225
+ }
226
+ if (parameters.limit !== void 0) {
227
+ url.searchParams.set("limit", parameters.limit.toString());
228
+ }
229
+ const { cursor: returnedCursor, data: offers } = await getApi(config, url);
230
+ return {
231
+ cursor: returnedCursor,
232
+ offers: offers.map((offer) => {
233
+ const baseOffer = mempool.Offer.fromSnakeCase(offer);
234
+ return {
235
+ ...baseOffer,
236
+ status: offer.status,
237
+ metadata: offer.metadata
238
+ };
239
+ })
240
+ };
241
+ }
242
+ async function getApi(config, url) {
243
+ if (url.searchParams.get("limit") && Number(url.searchParams.get("limit")) > MAX_BATCH_SIZE) {
244
+ throw new HttpGetOffersFailedError(
245
+ `The maximum number of offers that can be returned is ${MAX_BATCH_SIZE}.`,
246
+ {
247
+ details: `The limit is set to ${url.searchParams.get("limit")}. Maximum is ${MAX_BATCH_SIZE}.`
248
+ }
249
+ );
250
+ }
251
+ const response = await fetch(url.toString(), {
252
+ method: "GET",
253
+ headers: config.headers
254
+ });
255
+ if (!response.ok) {
256
+ switch (response.status) {
257
+ case 401:
258
+ throw new HttpUnauthorizedError();
259
+ case 403:
260
+ throw new HttpForbiddenError();
261
+ case 429:
262
+ throw new HttpRateLimitError();
263
+ }
264
+ throw new HttpGetOffersFailedError(`GET request returned ${response.status}`, {
265
+ details: await response.text()
266
+ });
267
+ }
268
+ return response.json();
269
+ }
270
+ var InvalidUrlError = class extends mempool.Errors.BaseError {
271
+ constructor(url) {
272
+ super(`URL "${url}" is not http/https.`);
273
+ __publicField(this, "name", "Router.InvalidUrlError");
274
+ }
275
+ };
276
+ var HttpUnauthorizedError = class extends mempool.Errors.BaseError {
277
+ constructor() {
278
+ super("Unauthorized.", {
279
+ metaMessages: ["Ensure that an API key is provided."]
280
+ });
281
+ __publicField(this, "name", "Router.HttpUnauthorizedError");
282
+ }
283
+ };
284
+ var HttpForbiddenError = class extends mempool.Errors.BaseError {
285
+ constructor() {
286
+ super("Forbidden.", {
287
+ metaMessages: ["Ensure that the API key is valid."]
288
+ });
289
+ __publicField(this, "name", "Router.HttpForbiddenError");
290
+ }
291
+ };
292
+ var HttpRateLimitError = class extends mempool.Errors.BaseError {
293
+ constructor() {
294
+ super("Rate limit exceeded.", {
295
+ metaMessages: [
296
+ "The number of allowed requests has been exceeded. You must wait for the rate limit to reset."
297
+ ]
298
+ });
299
+ __publicField(this, "name", "Router.HttpRateLimitError");
300
+ }
301
+ };
302
+ var HttpGetOffersFailedError = class extends mempool.Errors.BaseError {
303
+ constructor(message, { details } = {}) {
304
+ super(message, {
305
+ metaMessages: [details]
306
+ });
307
+ __publicField(this, "name", "Router.HttpGetOffersFailedError");
308
+ }
309
+ };
310
+
311
+ // src/RouterEvent.ts
312
+ var RouterEvent_exports = {};
313
+ __export(RouterEvent_exports, {
314
+ buildId: () => buildId,
315
+ types: () => types
316
+ });
317
+ var types = ["offer_created", "offer_matched", "offer_validation"];
318
+ function buildId(event) {
319
+ switch (event.type) {
320
+ case "offer_created":
321
+ return `offer_created:${event.offer.hash.toLowerCase()}`;
322
+ case "offer_matched":
323
+ return `offer_matched:${event.offer.hash.toLowerCase()}`;
324
+ case "offer_validation":
325
+ return `offer_validation:${event.offer.hash.toLowerCase()}`;
326
+ default: {
327
+ throw new Error("Unhandled event type");
328
+ }
329
+ }
330
+ }
331
+
332
+ // src/RouterOffer.ts
333
+ var RouterOffer_exports = {};
334
+ __export(RouterOffer_exports, {
335
+ OfferStatusValues: () => OfferStatusValues
336
+ });
337
+ var OfferStatusValues = [
338
+ "valid",
339
+ "callback_not_supported",
340
+ "callback_error",
341
+ "unverified"
342
+ ];
343
+
344
+ // src/utils/batch.ts
345
+ function* batch(array, batchSize) {
346
+ for (let i = 0; i < array.length; i += batchSize) {
347
+ yield array.slice(i, i + batchSize);
348
+ }
349
+ }
350
+
351
+ // src/utils/wait.ts
352
+ async function wait(time) {
353
+ return new Promise((res) => setTimeout(res, time));
354
+ }
355
+
356
+ // src/utils/poll.ts
357
+ function poll(fn, { interval }) {
358
+ let active = true;
359
+ const unwatch = () => active = false;
360
+ const watch = async () => {
361
+ await wait(interval);
362
+ const poll2 = async () => {
363
+ if (!active) return;
364
+ await fn({ unpoll: unwatch });
365
+ await wait(interval);
366
+ poll2();
367
+ };
368
+ poll2();
369
+ };
370
+ watch();
371
+ return unwatch;
372
+ }
373
+
374
+ // src/Validation.ts
375
+ var Validation_exports = {};
376
+ __export(Validation_exports, {
377
+ run: () => run
378
+ });
379
+ async function run(parameters) {
380
+ const { items, rules, ctx = {}, chunkSize } = parameters;
381
+ const issues = [];
382
+ let validItems = items.slice();
383
+ for (const rule of rules) {
384
+ if (validItems.length === 0) return { valid: [], issues };
385
+ const indicesToRemove = /* @__PURE__ */ new Set();
386
+ if (rule.kind === "single") {
387
+ for (let i = 0; i < validItems.length; i++) {
388
+ const item = validItems[i];
389
+ const issue = await rule.run(item, ctx);
390
+ if (issue) {
391
+ issues.push({ ...issue, ruleName: rule.name, item });
392
+ indicesToRemove.add(i);
393
+ }
394
+ }
395
+ } else if (rule.kind === "batch") {
396
+ const exec = async (slice, offset) => {
397
+ const map = await rule.run(slice, ctx);
398
+ for (let i = 0; i < slice.length; i++) {
399
+ const issue = map.get(i);
400
+ if (issue !== void 0) {
401
+ issues.push({ ...issue, ruleName: rule.name, item: slice[i] });
402
+ indicesToRemove.add(offset + i);
403
+ }
404
+ }
405
+ };
406
+ if (!chunkSize) await exec(validItems, 0);
407
+ else {
408
+ for (let i = 0; i < validItems.length; i += chunkSize) {
409
+ await exec(validItems.slice(i, i + chunkSize), i);
410
+ }
411
+ }
412
+ }
413
+ validItems = validItems.filter((_, i) => !indicesToRemove.has(i));
414
+ }
415
+ return {
416
+ valid: validItems,
417
+ issues
418
+ };
419
+ }
420
+
421
+ // src/ValidationRule.ts
422
+ var ValidationRule_exports = {};
423
+ __export(ValidationRule_exports, {
424
+ batch: () => batch2,
425
+ morpho: () => morpho,
426
+ single: () => single
427
+ });
428
+ function single(name, run2) {
429
+ return { kind: "single", name, run: run2 };
430
+ }
431
+ function batch2(name, run2) {
432
+ return { kind: "batch", name, run: run2 };
433
+ }
434
+ function morpho(parameters) {
435
+ const { whitelistedChains } = parameters;
436
+ const whitelistedChainIds = new Set(whitelistedChains.map((chain) => chain.id));
437
+ const whitelistedLoanTokensPerChain = new Map(
438
+ whitelistedChains.map((chain) => [
439
+ chain.id,
440
+ new Set(Array.from(chain.whitelistedAssets).map((a) => a.toLowerCase()))
441
+ ])
442
+ );
443
+ const morphoPerChain = new Map(
444
+ whitelistedChains.map((chain) => [chain.id, chain.morpho.toLowerCase()])
445
+ );
446
+ const chainId = single("chain_id", (offer, _) => {
447
+ if (!whitelistedChainIds.has(offer.chainId)) {
448
+ return { message: `Chain ID ${offer.chainId} is not whitelisted` };
449
+ }
450
+ });
451
+ const loanToken = single("loan_token", (offer, _) => {
452
+ if (!whitelistedLoanTokensPerChain.get(offer.chainId)?.has(offer.loanToken.toLowerCase())) {
453
+ return {
454
+ message: `Loan token ${offer.loanToken} is not whitelisted on chain ${offer.chainId}`
455
+ };
456
+ }
457
+ });
458
+ const expiry = single("expiry", (offer, _) => {
459
+ if (offer.expiry < Math.floor(Date.now() / 1e3)) {
460
+ return { message: "Expiry mismatch" };
461
+ }
462
+ });
463
+ const emptyCallback = single("empty_callback", (offer, _) => {
464
+ if (offer.callback.data !== "0x") {
465
+ return { message: "Callback data is not empty. Not supported yet." };
466
+ }
467
+ });
468
+ const sellOffersEmptyCallback = single(
469
+ "sell_offers_empty_callback",
470
+ (offer, _) => {
471
+ if (!offer.buy && offer.callback.data === "0x") {
472
+ return { message: "Sell offers with empty callback are not supported yet." };
473
+ }
474
+ }
475
+ );
476
+ const buyOffersEmptyCallback = batch2(
477
+ "buy_offers_empty_callback",
478
+ async (offers, { publicClients }) => {
479
+ const issues = /* @__PURE__ */ new Map();
480
+ const hashToIndex = /* @__PURE__ */ new Map();
481
+ for (let i = 0; i < offers.length; i++) {
482
+ const offer = offers[i];
483
+ hashToIndex.set(offer.hash, i);
484
+ }
485
+ const { buyOffers, sellOffers: _sellOffers } = offers.reduce(
486
+ (acc, offer) => {
487
+ offer.buy ? acc.buyOffers.push(offer) : issues.set(hashToIndex.get(offer.hash), {
488
+ message: "Onchain callback for sell offers is not supported yet."
489
+ });
490
+ return acc;
491
+ },
492
+ { buyOffers: [], sellOffers: [] }
493
+ );
494
+ const buyOffersPerLoanAsset = /* @__PURE__ */ new Map();
495
+ for (const offer of buyOffers) {
496
+ const chainName = getChain(offer.chainId)?.name;
497
+ const loanTokens = buyOffersPerLoanAsset.get(chainName) ?? /* @__PURE__ */ new Map();
498
+ const offers2 = loanTokens.get(offer.loanToken.toLowerCase()) ?? [];
499
+ offers2.push(offer);
500
+ loanTokens.set(offer.loanToken.toLowerCase(), offers2);
501
+ buyOffersPerLoanAsset.set(chainName, loanTokens);
502
+ }
503
+ await Promise.all(
504
+ Array.from(buyOffersPerLoanAsset.entries()).map(async ([name, loanTokens]) => {
505
+ const chainName = name;
506
+ const publicClient = publicClients[chainName];
507
+ const morpho2 = morphoPerChain.get(chains[chainName].id);
508
+ if (!publicClient) {
509
+ const offers2 = Array.from(loanTokens.values()).flat();
510
+ for (const offer of offers2) {
511
+ issues.set(hashToIndex.get(offer.hash), {
512
+ message: `Public client for chain "${chainName}" is not available`
513
+ });
514
+ }
515
+ return;
516
+ }
517
+ const balances = /* @__PURE__ */ new Map();
518
+ const allowances = /* @__PURE__ */ new Map();
519
+ for (const [loanToken2, offers2] of loanTokens) {
520
+ const data = await Promise.all(
521
+ offers2.flatMap((offer) => [
522
+ publicClient.readContract({
523
+ address: loanToken2,
524
+ abi: viem.parseAbi([
525
+ "function balanceOf(address owner) view returns (uint256 balance)"
526
+ ]),
527
+ functionName: "balanceOf",
528
+ args: [offer.offering]
529
+ }),
530
+ publicClient.readContract({
531
+ address: loanToken2,
532
+ abi: viem.parseAbi([
533
+ "function allowance(address owner, address spender) public view returns (uint256 remaining)"
534
+ ]),
535
+ functionName: "allowance",
536
+ args: [offer.offering, morpho2]
537
+ })
538
+ ])
539
+ );
540
+ for (let i = 0; i < offers2.length; i++) {
541
+ const user = offers2[i].offering.toLowerCase();
542
+ const balance = data[i * 2] || 0n;
543
+ const allowance = data[i * 2 + 1] || 0n;
544
+ const userBalances = balances.get(user) ?? /* @__PURE__ */ new Map();
545
+ userBalances.set(loanToken2.toLowerCase(), balance);
546
+ const userAllowances = allowances.get(user) ?? /* @__PURE__ */ new Map();
547
+ userAllowances.set(loanToken2.toLowerCase(), allowance);
548
+ balances.set(user, userBalances);
549
+ allowances.set(user, userAllowances);
550
+ }
551
+ }
552
+ for (const offer of Array.from(loanTokens.values()).flat()) {
553
+ const user = offer.offering.toLowerCase();
554
+ const userBalances = balances.get(user);
555
+ const balance = userBalances?.get(offer.loanToken.toLowerCase());
556
+ if (balance < offer.assets) {
557
+ issues.set(hashToIndex.get(offer.hash), {
558
+ message: `Insufficient balance for ${offer.loanToken} on chain ${offer.chainId} (${balance.toString()} < ${offer.assets.toString()})`
559
+ });
560
+ continue;
561
+ }
562
+ const userAllowances = allowances.get(user);
563
+ const allowance = userAllowances?.get(offer.loanToken.toLowerCase());
564
+ if (allowance < offer.assets) {
565
+ issues.set(hashToIndex.get(offer.hash), {
566
+ message: `Insufficient allowance for ${offer.loanToken} on chain ${offer.chainId} (${allowance.toString()} < ${offer.assets.toString()})`
567
+ });
568
+ }
569
+ }
570
+ })
571
+ );
572
+ return issues;
573
+ }
574
+ );
575
+ return [
576
+ chainId,
577
+ loanToken,
578
+ expiry,
579
+ // note: callback onchain check should be done last since it does not mean that the offer is forever invalid
580
+ // integrators should be able to keep the offers that have an invalid callback onchain and be sure that is the only check that is not valid
581
+ emptyCallback,
582
+ sellOffersEmptyCallback,
583
+ buyOffersEmptyCallback
584
+ ];
585
+ }
586
+
587
+ exports.Chain = Chain_exports;
588
+ exports.Router = core_exports;
589
+ exports.RouterEvent = RouterEvent_exports;
590
+ exports.RouterOffer = RouterOffer_exports;
591
+ exports.Validation = Validation_exports;
592
+ exports.ValidationRule = ValidationRule_exports;
593
+ exports.batch = batch;
594
+ exports.poll = poll;
595
+ exports.wait = wait;
596
+ Object.keys(mempool).forEach(function (k) {
597
+ if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
598
+ enumerable: true,
599
+ get: function () { return mempool[k]; }
600
+ });
601
+ });
602
+ //# sourceMappingURL=index.browser.js.map
603
+ //# sourceMappingURL=index.browser.js.map