@hyperbridge/simplex 0.16.5 → 0.16.7
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/bin/simplex.js +603 -186
- package/dist/bin/simplex.js.map +1 -1
- package/dist/index.cjs +387 -79
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +110 -50
- package/dist/index.d.ts +110 -50
- package/dist/index.js +387 -79
- package/dist/index.js.map +1 -1
- package/dist/ui/assets/index-Be446eYK.js +106 -0
- package/dist/ui/assets/index-C3T-gubp.css +1 -0
- package/dist/ui/index.html +2 -2
- package/package.json +2 -2
- package/dist/ui/assets/index-Bv9S1oj4.js +0 -106
- package/dist/ui/assets/index-DwJCXJ6a.css +0 -1
package/dist/index.d.cts
CHANGED
|
@@ -353,46 +353,50 @@ declare class FillerConfigService {
|
|
|
353
353
|
* What one quorum call is allowed to spend.
|
|
354
354
|
*
|
|
355
355
|
* `deadlineMs` is the ceiling on the call itself: past it, the endpoints still
|
|
356
|
-
* outstanding are treated as failures and the call
|
|
357
|
-
*
|
|
358
|
-
*
|
|
359
|
-
*
|
|
360
|
-
*
|
|
356
|
+
* outstanding are treated as failures, so they stop voting and the call is
|
|
357
|
+
* decided over the endpoints that answered, or fails with a QuorumError naming
|
|
358
|
+
* them. Early exit decides as soon as the endpoints still out could not change
|
|
359
|
+
* the outcome; the deadline decides when one of them never answers.
|
|
360
|
+
*
|
|
361
|
+
* `timeoutMs` bounds one endpoint's attempt, and there is only ever one: the
|
|
362
|
+
* transports are built with `retryCount: 0`, so an endpoint's whole
|
|
363
|
+
* contribution to a call is a single request. That is what keeps the two
|
|
364
|
+
* numbers independent — a task cannot approach `deadlineMs` by retrying inside
|
|
365
|
+
* itself, so a deadline that fires means something outside the budget went
|
|
366
|
+
* wrong rather than an endpoint using the budget as designed.
|
|
361
367
|
*/
|
|
362
368
|
interface QuorumBudget {
|
|
363
369
|
timeoutMs: number;
|
|
364
|
-
retryCount: number;
|
|
365
|
-
retryDelayMs: number;
|
|
366
370
|
deadlineMs: number;
|
|
367
371
|
}
|
|
368
372
|
/**
|
|
369
373
|
* Wraps multiple viem `PublicClient`s — one per configured RPC URL — and runs
|
|
370
374
|
* selected read paths (`getLogs`, `getBlockNumber`, `getTransactionConfirmations`)
|
|
371
|
-
* as a **BFT quorum**: a result is accepted only when `quorumThreshold(
|
|
372
|
-
*
|
|
375
|
+
* as a **BFT quorum**: a result is accepted only when `quorumThreshold(m)` of the
|
|
376
|
+
* `m` endpoints that answered agree on it.
|
|
373
377
|
*
|
|
374
378
|
* A provider that *answers with divergent data* is never special-cased away — it
|
|
375
379
|
* simply fails to join the agreeing group, which is what makes a lying or reorged
|
|
376
380
|
* endpoint detectable rather than authoritative.
|
|
377
381
|
*
|
|
378
|
-
*
|
|
379
|
-
*
|
|
380
|
-
*
|
|
381
|
-
*
|
|
382
|
-
*
|
|
383
|
-
*
|
|
384
|
-
*
|
|
385
|
-
*
|
|
386
|
-
* scanner that misses orders loses fills.
|
|
382
|
+
* A provider that *fails* does not vote. A failed request says nothing about the
|
|
383
|
+
* chain, so it must not outvote the endpoints that agree: the threshold guards
|
|
384
|
+
* against endpoints that answer wrongly, and every answer still counts. Six
|
|
385
|
+
* endpoints with two failing decide over the other four, three of which must
|
|
386
|
+
* agree. The price, worth stating plainly, is that a call can be decided by fewer
|
|
387
|
+
* endpoints than the operator configured; at the limit, one endpoint answering
|
|
388
|
+
* while the rest fail decides alone. The voters are still exclusively the
|
|
389
|
+
* operator's own.
|
|
387
390
|
*
|
|
388
|
-
*
|
|
389
|
-
*
|
|
390
|
-
*
|
|
391
|
-
*
|
|
392
|
-
*
|
|
393
|
-
*
|
|
394
|
-
*
|
|
395
|
-
*
|
|
391
|
+
* The bench is the one state this class keeps, and {@link benchFor} decides who
|
|
392
|
+
* goes on it: a request-rate limit ({@link isSuspendableRateLimit}), a response
|
|
393
|
+
* that is not JSON ({@link isMalformedResponse}), or a head behind the quorum's
|
|
394
|
+
* ({@link isStaleHead}). All three share the property that earns it — the
|
|
395
|
+
* endpoint will keep failing the same way for a while — so a benched endpoint is
|
|
396
|
+
* not asked for its window: asking would spend its quota, or hold the call open
|
|
397
|
+
* for an answer already known to fail. When every endpoint is benched, all are
|
|
398
|
+
* queried again; there is nobody left to prefer. Every other failure is per
|
|
399
|
+
* call, and the endpoint is asked again next time.
|
|
396
400
|
*
|
|
397
401
|
* The constructor validates that URLs resolve to distinct hostnames so a "quorum"
|
|
398
402
|
* isn't secretly the same upstream in disguise.
|
|
@@ -402,8 +406,8 @@ declare class QuorumPublicClient {
|
|
|
402
406
|
readonly rpcUrls: string[];
|
|
403
407
|
/**
|
|
404
408
|
* The quorum bar when every endpoint answers: `quorumThreshold(n)` over the
|
|
405
|
-
* full set.
|
|
406
|
-
*
|
|
409
|
+
* full set. Each call's bar is `quorumThreshold` over the endpoints that answer
|
|
410
|
+
* it, so this is the most it can be.
|
|
407
411
|
*/
|
|
408
412
|
readonly threshold: number;
|
|
409
413
|
private readonly logger?;
|
|
@@ -424,11 +428,10 @@ declare class QuorumPublicClient {
|
|
|
424
428
|
/** Endpoints currently benched, by URL. See {@link benchFor} for the reasons. */
|
|
425
429
|
suspended(): string[];
|
|
426
430
|
/**
|
|
427
|
-
* The endpoints this call queries
|
|
428
|
-
*
|
|
429
|
-
*
|
|
430
|
-
*
|
|
431
|
-
* queried again; there is nobody left to prefer.
|
|
431
|
+
* The endpoints this call queries: everyone not benched. A benched endpoint is
|
|
432
|
+
* dropped outright: it answers nothing while throttled, so asking it could only
|
|
433
|
+
* cost a request. With every endpoint benched, everyone is queried again; there
|
|
434
|
+
* is nobody left to prefer.
|
|
432
435
|
*/
|
|
433
436
|
private participants;
|
|
434
437
|
/**
|
|
@@ -453,22 +456,26 @@ declare class QuorumPublicClient {
|
|
|
453
456
|
* retries would otherwise stall every confirmation poll). Stragglers settle
|
|
454
457
|
* out of band and are ignored. `tryDecide` returns undefined to keep
|
|
455
458
|
* waiting; once every task has settled, `finalize` must decide (it throws
|
|
456
|
-
* the QuorumError when the full response set still has no quorum).
|
|
457
|
-
*
|
|
458
|
-
*
|
|
459
|
+
* the QuorumError when the full response set still has no quorum).
|
|
460
|
+
*
|
|
461
|
+
* Both are handed the bar: the BFT threshold over the endpoints that have not
|
|
462
|
+
* failed, answered or still out. A failure lowers it rather than counting
|
|
463
|
+
* against it. Counting the pending endpoints keeps an early decision to a bar
|
|
464
|
+
* no lower than the full response set would get, so a vote it did not wait for
|
|
465
|
+
* could never have reversed it.
|
|
459
466
|
*
|
|
460
467
|
* `deadlineMs` bounds the other direction: when the bar is NOT reachable
|
|
461
468
|
* from the fast responders, the call used to wait out every straggler, and
|
|
462
469
|
* the caller's own retry loop multiplied that into minutes of a chain not
|
|
463
470
|
* being scanned at all, silently. At the deadline the outstanding endpoints
|
|
464
471
|
* are treated as failures — named in the QuorumError, so the operator sees
|
|
465
|
-
* which ones held the call up — and `finalize` decides
|
|
466
|
-
*
|
|
472
|
+
* which ones held the call up — and `finalize` decides over the endpoints
|
|
473
|
+
* that answered.
|
|
467
474
|
*/
|
|
468
475
|
private settleUntilQuorum;
|
|
469
476
|
/**
|
|
470
|
-
* Highest block head backed by a
|
|
471
|
-
*
|
|
477
|
+
* Highest block head backed by a quorum of the endpoints that answer. Throws
|
|
478
|
+
* {@link QuorumError} when none do.
|
|
472
479
|
*/
|
|
473
480
|
getBlockNumber(): Promise<bigint>;
|
|
474
481
|
/**
|
|
@@ -2652,13 +2659,11 @@ interface PostedOrder {
|
|
|
2652
2659
|
* Every code the orderbook's `RejectionCode` enum can send, listed rather than
|
|
2653
2660
|
* written as a union so a test can hold it against the published schema.
|
|
2654
2661
|
*
|
|
2655
|
-
* Why the orderbook refuses an order. `MIN_ORDER_SIZE
|
|
2656
|
-
* prevented by validation before posting
|
|
2657
|
-
*
|
|
2658
|
-
*
|
|
2659
|
-
*
|
|
2660
|
-
* register the order's input symbol on the server, which is the server's own
|
|
2661
|
-
* config and nothing here can check ahead of asking.
|
|
2662
|
+
* Why the orderbook refuses an order. `MIN_ORDER_SIZE`, `TTL_TOO_SHORT` and
|
|
2663
|
+
* `UNSUPPORTED_SOURCE_CHAIN` are prevented by validation before posting, the last
|
|
2664
|
+
* against the chains the server serves and the tokens its registry lists on each;
|
|
2665
|
+
* `REPLAYED` and `ORDER_EXISTS` are answered by bumping the nonce; the rest are
|
|
2666
|
+
* encoding bugs on our side.
|
|
2662
2667
|
*/
|
|
2663
2668
|
declare const REJECTION_CODES: readonly ["MALFORMED_USER_OP", "NO_FILL_ORDER", "UNSUPPORTED_CHAIN", "UNSUPPORTED_SHAPE", "NOT_PHANTOM", "TTL_TOO_SHORT", "UNSUPPORTED_PAIR", "BAD_SIGNATURE", "BAD_NONCE_BINDING", "REPLAYED", "ORDER_EXISTS", "TOO_MANY_ORDERS", "MIN_ORDER_SIZE", "MISSING_DECLARATION", "EMPTY_DECLARATION", "UNSUPPORTED_SOURCE_CHAIN"];
|
|
2664
2669
|
type RejectionCode = (typeof REJECTION_CODES)[number];
|
|
@@ -2733,9 +2738,10 @@ type CancelOrderResult = {
|
|
|
2733
2738
|
* {@link OrderbookRequestError} because it could not get one.
|
|
2734
2739
|
*/
|
|
2735
2740
|
declare class OrderbookClient {
|
|
2736
|
-
private readonly url;
|
|
2737
2741
|
private readonly requestTimeoutMs;
|
|
2738
2742
|
private logger;
|
|
2743
|
+
/** The configured endpoint, with `/graphql` if it was left off. */
|
|
2744
|
+
private readonly url;
|
|
2739
2745
|
constructor(url: string, requestTimeoutMs: number, loggers?: LoggerContext);
|
|
2740
2746
|
/** The limits to validate against before posting, plus the books on offer. */
|
|
2741
2747
|
limits(): Promise<OrderbookLimits>;
|
|
@@ -2844,6 +2850,13 @@ interface ReconcileReport {
|
|
|
2844
2850
|
* orderbook's answer is then written back onto that row: an accepted order
|
|
2845
2851
|
* carries its commitment, a rejected one carries the reason.
|
|
2846
2852
|
*/
|
|
2853
|
+
/**
|
|
2854
|
+
* The configured ERC-4626 vaults' holdings, as `VaultFundingPlanner` reports them. A fill sources
|
|
2855
|
+
* a payout shortfall from these, so they back a limit order as much as the wallet does.
|
|
2856
|
+
*/
|
|
2857
|
+
interface VaultHoldings {
|
|
2858
|
+
getBalanceSnapshot(chain?: string): Promise<VaultBalancePosition[]>;
|
|
2859
|
+
}
|
|
2847
2860
|
declare class LimitOrderService {
|
|
2848
2861
|
private readonly store;
|
|
2849
2862
|
private readonly client;
|
|
@@ -2855,12 +2868,16 @@ declare class LimitOrderService {
|
|
|
2855
2868
|
private readonly delegationService?;
|
|
2856
2869
|
/** Where a new order's nonce starts; tests pin it, production draws it at random. */
|
|
2857
2870
|
private readonly startingNonce;
|
|
2871
|
+
/** The configured ERC-4626 vaults, when the operator runs any. */
|
|
2872
|
+
private readonly vaultBalances?;
|
|
2858
2873
|
private logger;
|
|
2859
2874
|
private cachedLimits?;
|
|
2860
2875
|
private onEvent?;
|
|
2861
2876
|
constructor(store: LimitOrderStore, client: OrderbookClient, contractService: ContractInteractionService, configService: FillerConfigService, assetRegistry: AssetRegistry, signer: Signer, defaultTtlSecs: number, delegationService?: DelegationService | undefined, loggers?: LoggerContext,
|
|
2862
2877
|
/** Where a new order's nonce starts; tests pin it, production draws it at random. */
|
|
2863
|
-
startingNonce?: () => bigint
|
|
2878
|
+
startingNonce?: () => bigint,
|
|
2879
|
+
/** The configured ERC-4626 vaults, when the operator runs any. */
|
|
2880
|
+
vaultBalances?: VaultHoldings | undefined);
|
|
2864
2881
|
/**
|
|
2865
2882
|
* Attaches the listener fill-driven changes are reported to. `Simplex` does
|
|
2866
2883
|
* this after boot, the same way the filler is handed the service itself.
|
|
@@ -2896,6 +2913,19 @@ declare class LimitOrderService {
|
|
|
2896
2913
|
*/
|
|
2897
2914
|
private withdraw;
|
|
2898
2915
|
private signAndCancel;
|
|
2916
|
+
/**
|
|
2917
|
+
* The pairs an order can be written against, the smallest payout each token may carry, and
|
|
2918
|
+
* the tokens the orderbook registers on each chain.
|
|
2919
|
+
*
|
|
2920
|
+
* The orderbook lists the books; `resolveBook` refuses a request naming anything else, so the
|
|
2921
|
+
* operator is offered exactly these and no combination of symbols they could not post. The
|
|
2922
|
+
* chains do the same for the source chains an order can accept.
|
|
2923
|
+
*/
|
|
2924
|
+
books(): Promise<{
|
|
2925
|
+
books: Book[];
|
|
2926
|
+
minOrderSizes: TokenMinSize[];
|
|
2927
|
+
chains: ChainInfo[];
|
|
2928
|
+
}>;
|
|
2899
2929
|
/**
|
|
2900
2930
|
* Reads `serverInfo` and `books`, reusing the last read for {@link LIMITS_TTL_MS}.
|
|
2901
2931
|
*
|
|
@@ -2915,15 +2945,30 @@ declare class LimitOrderService {
|
|
|
2915
2945
|
* balance on the fill chain, so the operator hears it while they are creating
|
|
2916
2946
|
* the order.
|
|
2917
2947
|
*
|
|
2948
|
+
* A fill pays out of the wallet and then withdraws any shortfall from the
|
|
2949
|
+
* configured ERC-4626 vaults in the same batch, so what those vaults hold of
|
|
2950
|
+
* the payout token backs the order too and is counted here. Without it an
|
|
2951
|
+
* operator who sweeps inventory into a vault is refused orders their filler
|
|
2952
|
+
* would have filled.
|
|
2953
|
+
*
|
|
2918
2954
|
* Each order is checked against the whole balance, not against what is left of
|
|
2919
2955
|
* it after the others. One balance backs every order resting on it — that is
|
|
2920
2956
|
* what quoting both sides of a book is — and the orderbook says as much: it
|
|
2921
2957
|
* advertises each entry at `min(quoted, balance)` rather than dividing the
|
|
2922
2958
|
* balance between them. Whichever order fills first draws the inventory down,
|
|
2923
2959
|
* and the rest are cut to what is left. Netting them here would refuse the
|
|
2924
|
-
* second side of every book.
|
|
2960
|
+
* second side of every book. Vault positions are counted the same way: the
|
|
2961
|
+
* whole position, not what is left after reservations for fills in flight.
|
|
2925
2962
|
*/
|
|
2926
2963
|
private assertWalletCanPay;
|
|
2964
|
+
/**
|
|
2965
|
+
* What the configured vaults hold of `token` on `chain`, in scaled units.
|
|
2966
|
+
*
|
|
2967
|
+
* Zero when no vault is configured. A snapshot that cannot be read is also
|
|
2968
|
+
* zero: the wallet alone then has to cover the order, which refuses one the
|
|
2969
|
+
* filler might have managed rather than accepting one it could not.
|
|
2970
|
+
*/
|
|
2971
|
+
private vaultHoldings;
|
|
2927
2972
|
/**
|
|
2928
2973
|
* Works a limit order down by what a fill delivered, and puts the rest back on
|
|
2929
2974
|
* the orderbook.
|
|
@@ -3457,6 +3502,15 @@ declare class FXFiller implements FillerStrategy {
|
|
|
3457
3502
|
* the output token's own decimals.
|
|
3458
3503
|
*/
|
|
3459
3504
|
private matchLeg;
|
|
3505
|
+
/** Why no limit order serves the order, leg by leg, for the line that says it was passed over. */
|
|
3506
|
+
private explainUnmatched;
|
|
3507
|
+
/**
|
|
3508
|
+
* One leg as the matcher sees it, or null when its input token is not one the asset
|
|
3509
|
+
* registry knows on the source chain.
|
|
3510
|
+
*
|
|
3511
|
+
* Amounts cross into the matcher at 1e18, the unit limit orders are kept in.
|
|
3512
|
+
*/
|
|
3513
|
+
private incomingFor;
|
|
3460
3514
|
/**
|
|
3461
3515
|
* The order's input in **USD**, or null when no limit order connects its input
|
|
3462
3516
|
* token to a dollar.
|
|
@@ -3794,6 +3848,12 @@ declare class LimitOrderController {
|
|
|
3794
3848
|
fills: LimitOrderFill[];
|
|
3795
3849
|
bids: StoredBid[];
|
|
3796
3850
|
} | null>;
|
|
3851
|
+
/** The pairs the orderbook lists, the smallest payout each token may carry, and its tokens per chain. */
|
|
3852
|
+
books(): Promise<{
|
|
3853
|
+
books: Book[];
|
|
3854
|
+
minOrderSizes: TokenMinSize[];
|
|
3855
|
+
chains: ChainInfo[];
|
|
3856
|
+
}>;
|
|
3797
3857
|
/** Creates the order, posts it, and reports what the orderbook made of it. */
|
|
3798
3858
|
create(request: CreateLimitOrderRequest): Promise<PostedLimitOrder>;
|
|
3799
3859
|
cancel(id: string): Promise<CancelledLimitOrder>;
|
package/dist/index.d.ts
CHANGED
|
@@ -353,46 +353,50 @@ declare class FillerConfigService {
|
|
|
353
353
|
* What one quorum call is allowed to spend.
|
|
354
354
|
*
|
|
355
355
|
* `deadlineMs` is the ceiling on the call itself: past it, the endpoints still
|
|
356
|
-
* outstanding are treated as failures and the call
|
|
357
|
-
*
|
|
358
|
-
*
|
|
359
|
-
*
|
|
360
|
-
*
|
|
356
|
+
* outstanding are treated as failures, so they stop voting and the call is
|
|
357
|
+
* decided over the endpoints that answered, or fails with a QuorumError naming
|
|
358
|
+
* them. Early exit decides as soon as the endpoints still out could not change
|
|
359
|
+
* the outcome; the deadline decides when one of them never answers.
|
|
360
|
+
*
|
|
361
|
+
* `timeoutMs` bounds one endpoint's attempt, and there is only ever one: the
|
|
362
|
+
* transports are built with `retryCount: 0`, so an endpoint's whole
|
|
363
|
+
* contribution to a call is a single request. That is what keeps the two
|
|
364
|
+
* numbers independent — a task cannot approach `deadlineMs` by retrying inside
|
|
365
|
+
* itself, so a deadline that fires means something outside the budget went
|
|
366
|
+
* wrong rather than an endpoint using the budget as designed.
|
|
361
367
|
*/
|
|
362
368
|
interface QuorumBudget {
|
|
363
369
|
timeoutMs: number;
|
|
364
|
-
retryCount: number;
|
|
365
|
-
retryDelayMs: number;
|
|
366
370
|
deadlineMs: number;
|
|
367
371
|
}
|
|
368
372
|
/**
|
|
369
373
|
* Wraps multiple viem `PublicClient`s — one per configured RPC URL — and runs
|
|
370
374
|
* selected read paths (`getLogs`, `getBlockNumber`, `getTransactionConfirmations`)
|
|
371
|
-
* as a **BFT quorum**: a result is accepted only when `quorumThreshold(
|
|
372
|
-
*
|
|
375
|
+
* as a **BFT quorum**: a result is accepted only when `quorumThreshold(m)` of the
|
|
376
|
+
* `m` endpoints that answered agree on it.
|
|
373
377
|
*
|
|
374
378
|
* A provider that *answers with divergent data* is never special-cased away — it
|
|
375
379
|
* simply fails to join the agreeing group, which is what makes a lying or reorged
|
|
376
380
|
* endpoint detectable rather than authoritative.
|
|
377
381
|
*
|
|
378
|
-
*
|
|
379
|
-
*
|
|
380
|
-
*
|
|
381
|
-
*
|
|
382
|
-
*
|
|
383
|
-
*
|
|
384
|
-
*
|
|
385
|
-
*
|
|
386
|
-
* scanner that misses orders loses fills.
|
|
382
|
+
* A provider that *fails* does not vote. A failed request says nothing about the
|
|
383
|
+
* chain, so it must not outvote the endpoints that agree: the threshold guards
|
|
384
|
+
* against endpoints that answer wrongly, and every answer still counts. Six
|
|
385
|
+
* endpoints with two failing decide over the other four, three of which must
|
|
386
|
+
* agree. The price, worth stating plainly, is that a call can be decided by fewer
|
|
387
|
+
* endpoints than the operator configured; at the limit, one endpoint answering
|
|
388
|
+
* while the rest fail decides alone. The voters are still exclusively the
|
|
389
|
+
* operator's own.
|
|
387
390
|
*
|
|
388
|
-
*
|
|
389
|
-
*
|
|
390
|
-
*
|
|
391
|
-
*
|
|
392
|
-
*
|
|
393
|
-
*
|
|
394
|
-
*
|
|
395
|
-
*
|
|
391
|
+
* The bench is the one state this class keeps, and {@link benchFor} decides who
|
|
392
|
+
* goes on it: a request-rate limit ({@link isSuspendableRateLimit}), a response
|
|
393
|
+
* that is not JSON ({@link isMalformedResponse}), or a head behind the quorum's
|
|
394
|
+
* ({@link isStaleHead}). All three share the property that earns it — the
|
|
395
|
+
* endpoint will keep failing the same way for a while — so a benched endpoint is
|
|
396
|
+
* not asked for its window: asking would spend its quota, or hold the call open
|
|
397
|
+
* for an answer already known to fail. When every endpoint is benched, all are
|
|
398
|
+
* queried again; there is nobody left to prefer. Every other failure is per
|
|
399
|
+
* call, and the endpoint is asked again next time.
|
|
396
400
|
*
|
|
397
401
|
* The constructor validates that URLs resolve to distinct hostnames so a "quorum"
|
|
398
402
|
* isn't secretly the same upstream in disguise.
|
|
@@ -402,8 +406,8 @@ declare class QuorumPublicClient {
|
|
|
402
406
|
readonly rpcUrls: string[];
|
|
403
407
|
/**
|
|
404
408
|
* The quorum bar when every endpoint answers: `quorumThreshold(n)` over the
|
|
405
|
-
* full set.
|
|
406
|
-
*
|
|
409
|
+
* full set. Each call's bar is `quorumThreshold` over the endpoints that answer
|
|
410
|
+
* it, so this is the most it can be.
|
|
407
411
|
*/
|
|
408
412
|
readonly threshold: number;
|
|
409
413
|
private readonly logger?;
|
|
@@ -424,11 +428,10 @@ declare class QuorumPublicClient {
|
|
|
424
428
|
/** Endpoints currently benched, by URL. See {@link benchFor} for the reasons. */
|
|
425
429
|
suspended(): string[];
|
|
426
430
|
/**
|
|
427
|
-
* The endpoints this call queries
|
|
428
|
-
*
|
|
429
|
-
*
|
|
430
|
-
*
|
|
431
|
-
* queried again; there is nobody left to prefer.
|
|
431
|
+
* The endpoints this call queries: everyone not benched. A benched endpoint is
|
|
432
|
+
* dropped outright: it answers nothing while throttled, so asking it could only
|
|
433
|
+
* cost a request. With every endpoint benched, everyone is queried again; there
|
|
434
|
+
* is nobody left to prefer.
|
|
432
435
|
*/
|
|
433
436
|
private participants;
|
|
434
437
|
/**
|
|
@@ -453,22 +456,26 @@ declare class QuorumPublicClient {
|
|
|
453
456
|
* retries would otherwise stall every confirmation poll). Stragglers settle
|
|
454
457
|
* out of band and are ignored. `tryDecide` returns undefined to keep
|
|
455
458
|
* waiting; once every task has settled, `finalize` must decide (it throws
|
|
456
|
-
* the QuorumError when the full response set still has no quorum).
|
|
457
|
-
*
|
|
458
|
-
*
|
|
459
|
+
* the QuorumError when the full response set still has no quorum).
|
|
460
|
+
*
|
|
461
|
+
* Both are handed the bar: the BFT threshold over the endpoints that have not
|
|
462
|
+
* failed, answered or still out. A failure lowers it rather than counting
|
|
463
|
+
* against it. Counting the pending endpoints keeps an early decision to a bar
|
|
464
|
+
* no lower than the full response set would get, so a vote it did not wait for
|
|
465
|
+
* could never have reversed it.
|
|
459
466
|
*
|
|
460
467
|
* `deadlineMs` bounds the other direction: when the bar is NOT reachable
|
|
461
468
|
* from the fast responders, the call used to wait out every straggler, and
|
|
462
469
|
* the caller's own retry loop multiplied that into minutes of a chain not
|
|
463
470
|
* being scanned at all, silently. At the deadline the outstanding endpoints
|
|
464
471
|
* are treated as failures — named in the QuorumError, so the operator sees
|
|
465
|
-
* which ones held the call up — and `finalize` decides
|
|
466
|
-
*
|
|
472
|
+
* which ones held the call up — and `finalize` decides over the endpoints
|
|
473
|
+
* that answered.
|
|
467
474
|
*/
|
|
468
475
|
private settleUntilQuorum;
|
|
469
476
|
/**
|
|
470
|
-
* Highest block head backed by a
|
|
471
|
-
*
|
|
477
|
+
* Highest block head backed by a quorum of the endpoints that answer. Throws
|
|
478
|
+
* {@link QuorumError} when none do.
|
|
472
479
|
*/
|
|
473
480
|
getBlockNumber(): Promise<bigint>;
|
|
474
481
|
/**
|
|
@@ -2652,13 +2659,11 @@ interface PostedOrder {
|
|
|
2652
2659
|
* Every code the orderbook's `RejectionCode` enum can send, listed rather than
|
|
2653
2660
|
* written as a union so a test can hold it against the published schema.
|
|
2654
2661
|
*
|
|
2655
|
-
* Why the orderbook refuses an order. `MIN_ORDER_SIZE
|
|
2656
|
-
* prevented by validation before posting
|
|
2657
|
-
*
|
|
2658
|
-
*
|
|
2659
|
-
*
|
|
2660
|
-
* register the order's input symbol on the server, which is the server's own
|
|
2661
|
-
* config and nothing here can check ahead of asking.
|
|
2662
|
+
* Why the orderbook refuses an order. `MIN_ORDER_SIZE`, `TTL_TOO_SHORT` and
|
|
2663
|
+
* `UNSUPPORTED_SOURCE_CHAIN` are prevented by validation before posting, the last
|
|
2664
|
+
* against the chains the server serves and the tokens its registry lists on each;
|
|
2665
|
+
* `REPLAYED` and `ORDER_EXISTS` are answered by bumping the nonce; the rest are
|
|
2666
|
+
* encoding bugs on our side.
|
|
2662
2667
|
*/
|
|
2663
2668
|
declare const REJECTION_CODES: readonly ["MALFORMED_USER_OP", "NO_FILL_ORDER", "UNSUPPORTED_CHAIN", "UNSUPPORTED_SHAPE", "NOT_PHANTOM", "TTL_TOO_SHORT", "UNSUPPORTED_PAIR", "BAD_SIGNATURE", "BAD_NONCE_BINDING", "REPLAYED", "ORDER_EXISTS", "TOO_MANY_ORDERS", "MIN_ORDER_SIZE", "MISSING_DECLARATION", "EMPTY_DECLARATION", "UNSUPPORTED_SOURCE_CHAIN"];
|
|
2664
2669
|
type RejectionCode = (typeof REJECTION_CODES)[number];
|
|
@@ -2733,9 +2738,10 @@ type CancelOrderResult = {
|
|
|
2733
2738
|
* {@link OrderbookRequestError} because it could not get one.
|
|
2734
2739
|
*/
|
|
2735
2740
|
declare class OrderbookClient {
|
|
2736
|
-
private readonly url;
|
|
2737
2741
|
private readonly requestTimeoutMs;
|
|
2738
2742
|
private logger;
|
|
2743
|
+
/** The configured endpoint, with `/graphql` if it was left off. */
|
|
2744
|
+
private readonly url;
|
|
2739
2745
|
constructor(url: string, requestTimeoutMs: number, loggers?: LoggerContext);
|
|
2740
2746
|
/** The limits to validate against before posting, plus the books on offer. */
|
|
2741
2747
|
limits(): Promise<OrderbookLimits>;
|
|
@@ -2844,6 +2850,13 @@ interface ReconcileReport {
|
|
|
2844
2850
|
* orderbook's answer is then written back onto that row: an accepted order
|
|
2845
2851
|
* carries its commitment, a rejected one carries the reason.
|
|
2846
2852
|
*/
|
|
2853
|
+
/**
|
|
2854
|
+
* The configured ERC-4626 vaults' holdings, as `VaultFundingPlanner` reports them. A fill sources
|
|
2855
|
+
* a payout shortfall from these, so they back a limit order as much as the wallet does.
|
|
2856
|
+
*/
|
|
2857
|
+
interface VaultHoldings {
|
|
2858
|
+
getBalanceSnapshot(chain?: string): Promise<VaultBalancePosition[]>;
|
|
2859
|
+
}
|
|
2847
2860
|
declare class LimitOrderService {
|
|
2848
2861
|
private readonly store;
|
|
2849
2862
|
private readonly client;
|
|
@@ -2855,12 +2868,16 @@ declare class LimitOrderService {
|
|
|
2855
2868
|
private readonly delegationService?;
|
|
2856
2869
|
/** Where a new order's nonce starts; tests pin it, production draws it at random. */
|
|
2857
2870
|
private readonly startingNonce;
|
|
2871
|
+
/** The configured ERC-4626 vaults, when the operator runs any. */
|
|
2872
|
+
private readonly vaultBalances?;
|
|
2858
2873
|
private logger;
|
|
2859
2874
|
private cachedLimits?;
|
|
2860
2875
|
private onEvent?;
|
|
2861
2876
|
constructor(store: LimitOrderStore, client: OrderbookClient, contractService: ContractInteractionService, configService: FillerConfigService, assetRegistry: AssetRegistry, signer: Signer, defaultTtlSecs: number, delegationService?: DelegationService | undefined, loggers?: LoggerContext,
|
|
2862
2877
|
/** Where a new order's nonce starts; tests pin it, production draws it at random. */
|
|
2863
|
-
startingNonce?: () => bigint
|
|
2878
|
+
startingNonce?: () => bigint,
|
|
2879
|
+
/** The configured ERC-4626 vaults, when the operator runs any. */
|
|
2880
|
+
vaultBalances?: VaultHoldings | undefined);
|
|
2864
2881
|
/**
|
|
2865
2882
|
* Attaches the listener fill-driven changes are reported to. `Simplex` does
|
|
2866
2883
|
* this after boot, the same way the filler is handed the service itself.
|
|
@@ -2896,6 +2913,19 @@ declare class LimitOrderService {
|
|
|
2896
2913
|
*/
|
|
2897
2914
|
private withdraw;
|
|
2898
2915
|
private signAndCancel;
|
|
2916
|
+
/**
|
|
2917
|
+
* The pairs an order can be written against, the smallest payout each token may carry, and
|
|
2918
|
+
* the tokens the orderbook registers on each chain.
|
|
2919
|
+
*
|
|
2920
|
+
* The orderbook lists the books; `resolveBook` refuses a request naming anything else, so the
|
|
2921
|
+
* operator is offered exactly these and no combination of symbols they could not post. The
|
|
2922
|
+
* chains do the same for the source chains an order can accept.
|
|
2923
|
+
*/
|
|
2924
|
+
books(): Promise<{
|
|
2925
|
+
books: Book[];
|
|
2926
|
+
minOrderSizes: TokenMinSize[];
|
|
2927
|
+
chains: ChainInfo[];
|
|
2928
|
+
}>;
|
|
2899
2929
|
/**
|
|
2900
2930
|
* Reads `serverInfo` and `books`, reusing the last read for {@link LIMITS_TTL_MS}.
|
|
2901
2931
|
*
|
|
@@ -2915,15 +2945,30 @@ declare class LimitOrderService {
|
|
|
2915
2945
|
* balance on the fill chain, so the operator hears it while they are creating
|
|
2916
2946
|
* the order.
|
|
2917
2947
|
*
|
|
2948
|
+
* A fill pays out of the wallet and then withdraws any shortfall from the
|
|
2949
|
+
* configured ERC-4626 vaults in the same batch, so what those vaults hold of
|
|
2950
|
+
* the payout token backs the order too and is counted here. Without it an
|
|
2951
|
+
* operator who sweeps inventory into a vault is refused orders their filler
|
|
2952
|
+
* would have filled.
|
|
2953
|
+
*
|
|
2918
2954
|
* Each order is checked against the whole balance, not against what is left of
|
|
2919
2955
|
* it after the others. One balance backs every order resting on it — that is
|
|
2920
2956
|
* what quoting both sides of a book is — and the orderbook says as much: it
|
|
2921
2957
|
* advertises each entry at `min(quoted, balance)` rather than dividing the
|
|
2922
2958
|
* balance between them. Whichever order fills first draws the inventory down,
|
|
2923
2959
|
* and the rest are cut to what is left. Netting them here would refuse the
|
|
2924
|
-
* second side of every book.
|
|
2960
|
+
* second side of every book. Vault positions are counted the same way: the
|
|
2961
|
+
* whole position, not what is left after reservations for fills in flight.
|
|
2925
2962
|
*/
|
|
2926
2963
|
private assertWalletCanPay;
|
|
2964
|
+
/**
|
|
2965
|
+
* What the configured vaults hold of `token` on `chain`, in scaled units.
|
|
2966
|
+
*
|
|
2967
|
+
* Zero when no vault is configured. A snapshot that cannot be read is also
|
|
2968
|
+
* zero: the wallet alone then has to cover the order, which refuses one the
|
|
2969
|
+
* filler might have managed rather than accepting one it could not.
|
|
2970
|
+
*/
|
|
2971
|
+
private vaultHoldings;
|
|
2927
2972
|
/**
|
|
2928
2973
|
* Works a limit order down by what a fill delivered, and puts the rest back on
|
|
2929
2974
|
* the orderbook.
|
|
@@ -3457,6 +3502,15 @@ declare class FXFiller implements FillerStrategy {
|
|
|
3457
3502
|
* the output token's own decimals.
|
|
3458
3503
|
*/
|
|
3459
3504
|
private matchLeg;
|
|
3505
|
+
/** Why no limit order serves the order, leg by leg, for the line that says it was passed over. */
|
|
3506
|
+
private explainUnmatched;
|
|
3507
|
+
/**
|
|
3508
|
+
* One leg as the matcher sees it, or null when its input token is not one the asset
|
|
3509
|
+
* registry knows on the source chain.
|
|
3510
|
+
*
|
|
3511
|
+
* Amounts cross into the matcher at 1e18, the unit limit orders are kept in.
|
|
3512
|
+
*/
|
|
3513
|
+
private incomingFor;
|
|
3460
3514
|
/**
|
|
3461
3515
|
* The order's input in **USD**, or null when no limit order connects its input
|
|
3462
3516
|
* token to a dollar.
|
|
@@ -3794,6 +3848,12 @@ declare class LimitOrderController {
|
|
|
3794
3848
|
fills: LimitOrderFill[];
|
|
3795
3849
|
bids: StoredBid[];
|
|
3796
3850
|
} | null>;
|
|
3851
|
+
/** The pairs the orderbook lists, the smallest payout each token may carry, and its tokens per chain. */
|
|
3852
|
+
books(): Promise<{
|
|
3853
|
+
books: Book[];
|
|
3854
|
+
minOrderSizes: TokenMinSize[];
|
|
3855
|
+
chains: ChainInfo[];
|
|
3856
|
+
}>;
|
|
3797
3857
|
/** Creates the order, posts it, and reports what the orderbook made of it. */
|
|
3798
3858
|
create(request: CreateLimitOrderRequest): Promise<PostedLimitOrder>;
|
|
3799
3859
|
cancel(id: string): Promise<CancelledLimitOrder>;
|