@hyperbridge/simplex 0.18.1 → 0.18.3

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.
@@ -113,12 +113,6 @@ interface RebalancingConfig$1 {
113
113
  USDT?: Record<string, string>;
114
114
  };
115
115
  }
116
- interface OverfillProtectionConfig {
117
- /** Ceiling bps above user-requested output; filler clamps its computed output to this. Default 500 (5%). */
118
- maxOverfillBps?: number;
119
- /** Consecutive clamped evaluations before the strategy halts itself. Default 3. */
120
- maxConsecutiveClamps?: number;
121
- }
122
116
  interface AllowlistConfig {
123
117
  /** Hex addresses eligible across all chains. */
124
118
  users?: string[];
@@ -153,10 +147,10 @@ interface FillerConfig {
153
147
  */
154
148
  minOrderSizeUsd?: number;
155
149
  /**
156
- * Overfill protection knobs. If omitted, defaults are used
157
- * (maxOverfillBps=500, maxConsecutiveClamps=3).
150
+ * Smallest payout, in USD, a partial fill may bid. Defaults to 20. Set to 0 to
151
+ * bid whatever can be filled. See `minPartialFillUsd` in filler-toml.
158
152
  */
159
- overfillProtection?: OverfillProtectionConfig;
153
+ minPartialFillUsd?: number;
160
154
  /**
161
155
  * Restricts which order `user` addresses the filler processes. When omitted, all
162
156
  * users are accepted. When present, only listed users (global ∪ per-source) are
@@ -341,10 +335,11 @@ declare class FillerConfigService {
341
335
  * Defaults to 20. An order at or above it is filled whatever fees it carries.
342
336
  */
343
337
  getMinOrderSizeUsd(): number;
344
- /** Ceiling bps above user-requested output. Default 500 (5%). */
345
- getMaxOverfillBps(): bigint;
346
- /** Consecutive clamped evaluations before the strategy halts. Default 3. */
347
- getMaxConsecutiveClamps(): number;
338
+ /**
339
+ * The smallest payout, in USD, a partial fill may bid. Defaults to 20. `0` bids
340
+ * whatever can be filled. Full fills are not checked.
341
+ */
342
+ getMinPartialFillUsd(): number;
348
343
  }
349
344
 
350
345
  /**
@@ -369,9 +364,10 @@ interface QuorumBudget {
369
364
  }
370
365
  /**
371
366
  * Wraps multiple viem `PublicClient`s — one per configured RPC URL — and runs
372
- * selected read paths (`getLogs`, `getBlockNumber`, `getTransactionConfirmations`)
373
- * as a **BFT quorum**: a result is accepted only when `quorumThreshold(m)` of the
374
- * `m` endpoints that answered agree on it.
367
+ * selected read paths (`getLogs`, `getBlockNumber`, `getTransactionInclusion` /
368
+ * `getTransactionConfirmations`, `readWithQuorum`) as a **BFT quorum**: a result is
369
+ * accepted only when `quorumThreshold(m)` of the `m` endpoints that answered agree
370
+ * on it.
375
371
  *
376
372
  * A provider that *answers with divergent data* is never special-cased away — it
377
373
  * simply fails to join the agreeing group, which is what makes a lying or reorged
@@ -477,22 +473,46 @@ declare class QuorumPublicClient {
477
473
  */
478
474
  getBlockNumber(): Promise<bigint>;
479
475
  /**
480
- * Confirmation count for a transaction under the quorum.
476
+ * The inclusion a quorum of endpoints agreed on for a transaction, and its depth.
481
477
  *
482
478
  * Every endpoint is asked for the receipt and its head. A "receipt not found"
483
479
  * answer is a valid **no** vote — the endpoint is responsive but does not see
484
480
  * the transaction (not yet propagated, or reorged out) — so it counts toward
485
- * responsiveness but joins no inclusion group. The transaction is confirmed
486
- * only when a quorum agrees on the same `(blockHash, blockNumber)`; the depth
487
- * is then the quorum head of that agreeing group. A minority still serving a
488
- * reorged/fabricated receipt can never reach the quorum.
481
+ * responsiveness but joins no inclusion group. The block is reported only when a
482
+ * quorum agrees on the same `(blockHash, blockNumber)`; the depth is then the
483
+ * quorum head of that agreeing group. A minority still serving a
484
+ * reorged/fabricated receipt can never reach the quorum. Returning the block as
485
+ * well as the depth lets a caller bind the count to the block it read the event
486
+ * from: a placement re-mined elsewhere keeps its transaction hash but not its
487
+ * block, and not the commitment built from it.
489
488
  *
490
489
  * Throws {@link QuorumError} when no inclusion reaches the quorum — including
491
490
  * the ordinary window where the tx is not yet mined on enough endpoints.
492
491
  */
492
+ getTransactionInclusion({ hash }: {
493
+ hash: Hash;
494
+ }): Promise<TransactionInclusion>;
495
+ /**
496
+ * Confirmation count for a transaction under the quorum. See
497
+ * {@link getTransactionInclusion}, whose depth this is.
498
+ */
493
499
  getTransactionConfirmations({ hash }: {
494
500
  hash: Hash;
495
501
  }): Promise<bigint>;
502
+ /**
503
+ * Runs an arbitrary read on every endpoint and returns the value a quorum
504
+ * agrees on. The `read` callback is the whole vote: one endpoint's answer is
505
+ * whatever its callback resolves to, so a caller that reads a vector of slots
506
+ * (e.g. every leg's escrow) votes on the vector, not on each slot separately.
507
+ * Values are compared under `JSON.stringify(..., bigIntReplacer)`, so bigints
508
+ * and arrays compare by value rather than by identity.
509
+ *
510
+ * An endpoint whose `read` throws does not vote — the class's rule for every
511
+ * quorum path. A quorum-meeting group is unique, so the first satisfiable
512
+ * agreement is final. Fails with {@link QuorumError} when no value reaches the
513
+ * bar, naming `label`.
514
+ */
515
+ readWithQuorum<T>(label: string, read: (client: PublicClient) => Promise<T>): Promise<T>;
496
516
  /**
497
517
  * Fetches logs from every endpoint in parallel and returns the result once a
498
518
  * quorum agrees. Fails with {@link QuorumError} otherwise.
@@ -510,6 +530,12 @@ declare class QuorumPublicClient {
510
530
  private describeResponders;
511
531
  private formatFailures;
512
532
  }
533
+ /** The inclusion a quorum of endpoints agreed on for a transaction, and its depth. */
534
+ interface TransactionInclusion {
535
+ blockHash: string;
536
+ blockNumber: bigint;
537
+ confirmations: bigint;
538
+ }
513
539
 
514
540
  /**
515
541
  * The signing contract a solver runs on, and the config shapes the bundled
@@ -755,93 +781,6 @@ declare class ChainClientManager {
755
781
  };
756
782
  }
757
783
 
758
- /**
759
- * Raw EIP-7702 authorization, as produced by the delegation flow. Attached to the
760
- * bundler UserOp so a not-yet-delegated EOA can be delegated in the same op.
761
- */
762
- interface Eip7702Authorization {
763
- chainId: number;
764
- address: HexString;
765
- nonce: number;
766
- r: HexString;
767
- s: HexString;
768
- yParity: number;
769
- }
770
- interface UserOpGasLimits {
771
- verificationGasLimit: bigint;
772
- callGasLimit: bigint;
773
- preVerificationGas: bigint;
774
- }
775
- interface SponsoredUserOpRequest {
776
- chain: string;
777
- /** ERC-7821 batch (or "0x" for a no-op, e.g. delegation). */
778
- callData: HexString;
779
- /**
780
- * Attach when the EOA still needs delegating in this op. Pass a factory rather
781
- * than a pre-signed tuple: building paymaster data can send an approve tx from
782
- * the authority EOA (the Simplex bootstrap approve to Permit2), and an authorization signed before
783
- * that tx embeds a stale nonce the bundler will reject. The factory runs only
784
- * after paymaster data is built.
785
- */
786
- eip7702Auth?: Eip7702Authorization | (() => Promise<Eip7702Authorization>);
787
- /** EntryPoint nonce key. Defaults to 0. */
788
- nonceKey?: bigint;
789
- /**
790
- * Explicit gas limits. Provide them to skip bundler estimation — required for
791
- * the not-yet-delegated EIP-7702 case, where the account has no code to
792
- * simulate so estimation is unreliable. When omitted, limits are estimated.
793
- */
794
- gas?: UserOpGasLimits;
795
- /**
796
- * Lets the paymaster fall back to an EIP-2612 permit when the fee token has no
797
- * Permit2 allowance yet. Only a first-time delegation sets this — it carries the
798
- * `approve(Permit2, max)` in its own callData, so the permit buys the one op that
799
- * makes every later Permit2 op possible without native.
800
- */
801
- permitBootstrap?: boolean;
802
- }
803
- /**
804
- * Submits self-initiated, paymaster-sponsored UserOperations through the bundler,
805
- * so the solver pays gas in stablecoins rather than native token. Shared by the
806
- * delegation setup and the vault sweep/redeem paths.
807
- *
808
- * Submission contract (so callers can safely fall back to a native tx without
809
- * risking a double-execution):
810
- * - Returns `null` when the op was **never submitted** — paymaster/bundler not
811
- * configured, insufficient USDC, preparation failed (approve tx or signing), or
812
- * the bundler rejected `eth_sendUserOperation` outright (it never entered the
813
- * mempool). The caller may fall back to native.
814
- * - Returns `{ txHash }` once a receipt is observed.
815
- * - **Throws** only when the op **was submitted** but no receipt arrived. The
816
- * caller must NOT fall back (the op may still land) — retry on the next cycle.
817
- */
818
- declare class UserOpSender {
819
- private readonly clientManager;
820
- private readonly configService;
821
- private readonly signer;
822
- private logger;
823
- constructor(clientManager: ChainClientManager, configService: FillerConfigService, signer: Signer);
824
- /** True when a sponsored UserOp is even possible on this chain (paymaster + bundler configured). */
825
- canSponsor(chain: string): boolean;
826
- trySendSponsored(req: SponsoredUserOpRequest): Promise<{
827
- txHash: HexString;
828
- } | null>;
829
- /**
830
- * Estimates account gas limits via the bundler. The op is signed first so the
831
- * estimation simulation passes the account's ECDSA validation. Falls back to
832
- * generous constants when the bundler estimate is unavailable.
833
- */
834
- private estimateGas;
835
- private buildSignedUserOp;
836
- /**
837
- * Prices the op for the rundler bundler, as the fill path does: its suggested fees, or the
838
- * chain's gas price raised to the priority fee it requires where it suggests none.
839
- */
840
- private getGasPrice;
841
- private sendBundlerRpc;
842
- private waitForUserOpReceipt;
843
- }
844
-
845
784
  /**
846
785
  * Service for managing EIP-7702 delegation of the filler's EOA to the SolverAccount contract.
847
786
  * This enables the filler to participate in solver selection mode.
@@ -866,8 +805,18 @@ declare class DelegationService {
866
805
  private readonly userOpSender;
867
806
  constructor(clientManager: ChainClientManager, configService: FillerConfigService, signer: Signer);
868
807
  /**
869
- * @param viaBundler When true, uses the current nonce (bundler submits the tx).
870
- * When false, uses nonce+1 (EOA submits the type-0x04 tx itself).
808
+ * Signs the authorization tuple and reports the nonce a direct set-code tx must carry.
809
+ *
810
+ * The tx nonce and the tuple nonce are two different counters, and the tuple's is the
811
+ * one *after* the tx's: EIP-7702 compares the tuple's nonce against the authority's
812
+ * nonce once the tx has bumped it. A direct tx therefore reads `pending` — what viem
813
+ * would fill anyway — and signs the tuple at `nonce + 1`. Reading `latest` instead
814
+ * signs one too low whenever an EOA tx is in flight, and a mismatched tuple is skipped
815
+ * without reverting: the receipt reads success while the account stays undelegated.
816
+ *
817
+ * @param viaBundler When true, the bundler submits the tx, so the tuple uses the
818
+ * authority's current nonce. When false, the EOA sends the type-0x04
819
+ * tx itself and the tuple is signed at that tx's nonce + 1.
871
820
  */
872
821
  private buildAuthorization;
873
822
  private sendDelegationTransaction;
@@ -879,8 +828,27 @@ declare class DelegationService {
879
828
  private resolvePendingPermit2Approval;
880
829
  /**
881
830
  * Checks if the filler's EOA is already delegated to the SolverAccount contract on a specific chain.
831
+ *
832
+ * Best-effort: callers retry, so a read failure answers "not delegated".
882
833
  */
883
834
  isDelegated(chain: string): Promise<boolean>;
835
+ /**
836
+ * Whether the EOA's code is the EIP-7702 delegation to the configured SolverAccount.
837
+ *
838
+ * A `blockNumber` makes this a claim about one mined block, so a read failure throws
839
+ * rather than answering "not delegated"; `confirmDelegationAt` turns that into "not
840
+ * confirmed". Without one it is a best-effort check, and `isDelegated` swallows a
841
+ * read failure to false.
842
+ */
843
+ private readDelegation;
844
+ /**
845
+ * Confirms the delegation at the block a tx mined in. A failed read of that one block is
846
+ * not a verdict, so the wallet's delegation at `latest` decides instead: a delegation that
847
+ * landed is not reported as failed because a node could not serve a historical `getCode`.
848
+ * `isDelegated` answers false when `latest` cannot be read either, which is "not confirmed",
849
+ * never a pass.
850
+ */
851
+ private confirmDelegationAt;
884
852
  /**
885
853
  * Sets up EIP-7702 delegation via the bundler. Uses the Simplex paymaster when
886
854
  * configured and the filler holds a sufficient stablecoin balance.
@@ -891,8 +859,46 @@ declare class DelegationService {
891
859
  * paymaster for PERMIT mode: the permit covers this op's gas, and the op installs
892
860
  * the allowance every later op authorizes against. That is the whole zero-native
893
861
  * bootstrap — one sponsored op, after which the account never needs a permit again.
862
+ *
863
+ * Returns an outcome rather than a boolean because only "unavailable" may fall back to
864
+ * a native tx: once the op reached the bundler it may still land, and a native retry
865
+ * alongside it would delegate twice.
894
866
  */
895
867
  private setupDelegationViaBundler;
868
+ /**
869
+ * Resolves the sponsored delegation op an earlier attempt left unconfirmed, before anything
870
+ * new is built on its nonce.
871
+ *
872
+ * - Its receipt is found: the delegation is confirmed on chain.
873
+ * - The EntryPoint nonce at `latest` has moved past the op's and the wallet is not delegated:
874
+ * the nonce was consumed without delegating, so the op is gone.
875
+ * - The nonce has not moved, but the bundler definitely no longer holds the op and it is past
876
+ * the grace period (see {@link DelegationService.bundlerDroppedOp}): it was dropped, so "gone".
877
+ * - Anything else, including a lookup or read that failed: still unresolved, so "pending".
878
+ * The op may land, and a replacement or a native delegation alongside it would double up.
879
+ */
880
+ private resolveUnconfirmedOp;
881
+ /**
882
+ * Whether the bundler has definitely dropped an unconfirmed delegation op. Rundler's
883
+ * `eth_getUserOperationByHash` checks its mempool and then the chain, so a definite `null`
884
+ * means the op is neither pooled nor landed. That only counts once the op is older than
885
+ * {@link UNCONFIRMED_OP_GRACE_MS}, so a lookup racing the bundler's own indexing is not read
886
+ * as a drop, and a failed or ambiguous lookup is not an answer at all.
887
+ *
888
+ * A wrong "gone" costs at most one set-code transaction's gas: once a native set-code tx
889
+ * lands it consumes the EOA nonce the old op's 7702 authorization was signed for, so the
890
+ * old op can no longer delegate. And "gone" only falls through to the normal setup, which
891
+ * tries a sponsored op first.
892
+ */
893
+ private bundlerDroppedOp;
894
+ /**
895
+ * Confirms the delegation at the block a sponsored op's transaction mined in. The public
896
+ * RPC can lag the bundler's, so the receipt is waited for, bounded by
897
+ * {@link BUNDLER_RECEIPT_WAIT_TIMEOUT_MS}. A receipt that cannot be read is not evidence
898
+ * either way, so the wallet's delegation at `latest` decides instead: a delegation that
899
+ * landed is not reported as failed because the receipt wait timed out.
900
+ */
901
+ private confirmBundlerDelegation;
896
902
  /**
897
903
  * Installs `approve(Permit2, max)` on an account that is ALREADY delegated, using the same
898
904
  * permit-funded op the first-time delegation carries — minus the authorization, which it
@@ -923,8 +929,25 @@ declare class DelegationService {
923
929
  *
924
930
  * With nothing pending — the allowance is already in place — the bundler path goes
925
931
  * first as usual. A plain direct tx is the last fallback in every case.
932
+ *
933
+ * One operation runs per wallet and chain at a time. Two services delegate the same
934
+ * wallet (the filler's and the limit-order service's, see
935
+ * `inFlightDelegationByWallet`), so a second call joins the attempt already in flight
936
+ * instead of sending a competing op.
926
937
  */
927
938
  setupDelegation(chain: string): Promise<boolean>;
939
+ /** The key every per-wallet, per-chain delegation map shares. */
940
+ private walletKey;
941
+ /**
942
+ * Runs one delegation operation under the per-wallet/chain lock.
943
+ *
944
+ * A second call of the same operation joins the one in flight (they would do the same
945
+ * thing). A different operation — a revoke during a setup — queues behind it so the
946
+ * two never overlap, but still runs: returning the other operation's result would
947
+ * report a revoke that never happened.
948
+ */
949
+ private withDelegationLock;
950
+ private setupDelegationOnce;
928
951
  /** Whether the EOA can pay for one direct set-code tx at the current gas price. */
929
952
  private nativeCoversDirectTx;
930
953
  /**
@@ -942,9 +965,180 @@ declare class DelegationService {
942
965
  results: Record<string, boolean>;
943
966
  }>;
944
967
  /**
945
- * Revokes delegation by delegating to the zero address.
968
+ * Revokes delegation by delegating to the zero address, under the same per-wallet/chain
969
+ * lock setupDelegation uses so a revoke and a setup cannot overlap.
946
970
  */
947
971
  revokeDelegation(chain: string): Promise<boolean>;
972
+ private revokeDelegationOnce;
973
+ /** Confirms the EOA's code is empty at the block a revoke tx mined in. */
974
+ private confirmRevokedAt;
975
+ }
976
+
977
+ /** A sponsored UserOp the bundler accepted but had no receipt for. */
978
+ interface SubmittedUserOp {
979
+ kind: "userOp";
980
+ userOpHash: HexString;
981
+ /** The EntryPoint nonce and nonce key the op was signed with, for a later `getNonce` check. */
982
+ nonce: bigint;
983
+ nonceKey: bigint;
984
+ /**
985
+ * Whether the paymaster attached a validity deadline. A Permit2-mode op does, so once its
986
+ * permit deadline has passed it can no longer land; a PERMIT bootstrap op does not, so it can
987
+ * land any time until its EntryPoint nonce is consumed.
988
+ */
989
+ expires: boolean;
990
+ /** When the bundler accepted the op, in ms. */
991
+ submittedAt: number;
992
+ }
993
+ /** A native transaction the node accepted but that got no receipt within the wait. */
994
+ interface SubmittedTx {
995
+ kind: "tx";
996
+ txHash: HexString;
997
+ /**
998
+ * The wallet nonce the tx was sent with. A node or mempool that no longer lists the tx proves
999
+ * nothing; the wallet's nonce moving past this one does.
1000
+ */
1001
+ nonce: number;
1002
+ /** When the transaction was sent, in ms. */
1003
+ submittedAt: number;
1004
+ }
1005
+
1006
+ /**
1007
+ * Raw EIP-7702 authorization, as produced by the delegation flow. Attached to the
1008
+ * bundler UserOp so a not-yet-delegated EOA can be delegated in the same op.
1009
+ */
1010
+ interface Eip7702Authorization {
1011
+ chainId: number;
1012
+ address: HexString;
1013
+ nonce: number;
1014
+ r: HexString;
1015
+ s: HexString;
1016
+ yParity: number;
1017
+ }
1018
+ interface UserOpGasLimits {
1019
+ verificationGasLimit: bigint;
1020
+ callGasLimit: bigint;
1021
+ preVerificationGas: bigint;
1022
+ }
1023
+ interface SponsoredUserOpRequest {
1024
+ chain: string;
1025
+ /** ERC-7821 batch (or "0x" for a no-op, e.g. delegation). */
1026
+ callData: HexString;
1027
+ /**
1028
+ * Attach when the EOA still needs delegating in this op. Pass a factory rather
1029
+ * than a pre-signed tuple: building paymaster data can send an approve tx from
1030
+ * the authority EOA (the Simplex bootstrap approve to Permit2), and an authorization signed before
1031
+ * that tx embeds a stale nonce the bundler will reject. The factory runs only
1032
+ * after paymaster data is built.
1033
+ */
1034
+ eip7702Auth?: Eip7702Authorization | (() => Promise<Eip7702Authorization>);
1035
+ /** EntryPoint nonce key. Defaults to 0. */
1036
+ nonceKey?: bigint;
1037
+ /**
1038
+ * Explicit gas limits. Provide them to skip bundler estimation — required for
1039
+ * the not-yet-delegated EIP-7702 case, where the account has no code to
1040
+ * simulate so estimation is unreliable. When omitted, limits are estimated.
1041
+ */
1042
+ gas?: UserOpGasLimits;
1043
+ /**
1044
+ * Lets the paymaster fall back to an EIP-2612 permit when the fee token has no
1045
+ * Permit2 allowance yet. Only a first-time delegation sets this — it carries the
1046
+ * `approve(Permit2, max)` in its own callData, so the permit buys the one op that
1047
+ * makes every later Permit2 op possible without native.
1048
+ */
1049
+ permitBootstrap?: boolean;
1050
+ }
1051
+ /**
1052
+ * Submits self-initiated, paymaster-sponsored UserOperations through the bundler,
1053
+ * so the solver pays gas in stablecoins rather than native token. Shared by the
1054
+ * delegation setup and the vault sweep/redeem paths.
1055
+ *
1056
+ * Submission contract (so callers can safely fall back to a native tx without
1057
+ * risking a double-execution):
1058
+ * - Returns `null` when the op was **never submitted** — paymaster/bundler not
1059
+ * configured, insufficient USDC, preparation failed (approve tx or signing), the
1060
+ * bundler rejected `eth_sendUserOperation` outright, the connection could not be
1061
+ * established, or a post-failure lookup proved the op never entered the pool. The
1062
+ * caller may fall back to native.
1063
+ * - Returns `{ txHash, userOp }` once a receipt is observed.
1064
+ * - **Throws** {@link SubmittedUnconfirmedError} when the op **was submitted** but no
1065
+ * receipt arrived, or when its submission could not be determined at all (the send
1066
+ * response was lost and the lookup could not ask). The caller must NOT fall back (the
1067
+ * op may still land) — retry on the next cycle, and resolve the op's fate later with
1068
+ * {@link lookupUserOpReceipt}.
1069
+ * - **Throws** {@link PendingOpOnNonceError} when the bundler refuses the op because an
1070
+ * earlier op from this sender already holds its EntryPoint nonce ("replacement
1071
+ * underpriced", "already known"). Not a rejection: that earlier op may still land, so
1072
+ * the caller must NOT fall back — retry later.
1073
+ */
1074
+ declare class UserOpSender {
1075
+ private readonly clientManager;
1076
+ private readonly configService;
1077
+ private readonly signer;
1078
+ private logger;
1079
+ constructor(clientManager: ChainClientManager, configService: FillerConfigService, signer: Signer);
1080
+ /** True when a sponsored UserOp is even possible on this chain (paymaster + bundler configured). */
1081
+ canSponsor(chain: string): boolean;
1082
+ trySendSponsored(req: SponsoredUserOpRequest): Promise<{
1083
+ txHash: HexString;
1084
+ userOp: SubmittedUserOp;
1085
+ } | null>;
1086
+ /**
1087
+ * One `eth_getUserOperationReceipt` for an op this filler submitted. Null when the bundler
1088
+ * does not know it — the op has not been indexed, which is not proof it never landed. Throws
1089
+ * when the bundler could not be asked, so a caller can tell "not found" apart from "couldn't ask".
1090
+ */
1091
+ lookupUserOpReceipt(chain: string, userOpHash: HexString): Promise<{
1092
+ txHash: HexString;
1093
+ success: boolean;
1094
+ } | null>;
1095
+ /**
1096
+ * Whether the bundler still knows an op this filler submitted. Rundler's
1097
+ * `eth_getUserOperationByHash` checks its mempool and then the chain, so `false` is a definite
1098
+ * `null` answer: the op is neither pooled nor landed. Throws when the bundler could not be
1099
+ * asked or answered ambiguously, so a caller can tell "dropped" apart from "couldn't ask".
1100
+ */
1101
+ isUserOpKnown(chain: string, userOpHash: HexString): Promise<boolean>;
1102
+ /**
1103
+ * Estimates account gas limits via the bundler. The op is signed first so the
1104
+ * estimation simulation passes the account's ECDSA validation. Falls back to
1105
+ * generous constants when the bundler estimate is unavailable.
1106
+ */
1107
+ private estimateGas;
1108
+ private buildSignedUserOp;
1109
+ /**
1110
+ * Prices the op for the rundler bundler, as the fill path does: its suggested fees, or the
1111
+ * chain's gas price raised to the priority fee it requires where it suggests none.
1112
+ */
1113
+ private getGasPrice;
1114
+ /**
1115
+ * One bundler JSON-RPC call, used by every request in this class. `timeoutMs` bounds the
1116
+ * request; a failure is thrown as a {@link BundlerCallError} whose `outcome` says whether it
1117
+ * is safe to treat the call as never having reached the bundler — the distinction the send
1118
+ * path relies on to avoid a native resend of an op that may already be submitted.
1119
+ */
1120
+ private sendBundlerRpc;
1121
+ /**
1122
+ * After an ambiguous `eth_sendUserOperation`, asks the bundler whether it actually holds the
1123
+ * op. Rundler's `eth_getUserOperationByHash` checks its mempool and then the chain, so a
1124
+ * non-null result means the op was accepted; a definite `null` on every attempt means it
1125
+ * never entered the pool.
1126
+ *
1127
+ * `lookupDelaysMs` are inter-attempt waits, so the default `[2_000, 5_000, 10_000]` looks up
1128
+ * at about 2 s, 7 s and 17 s after the failed send.
1129
+ *
1130
+ * Returns `"unknown"` when any attempt failed, because that is not proof of absence: a
1131
+ * bundler still validating the op after our request timed out could add it after the last
1132
+ * attempt, and the widening delays exist to shrink that window. Only `"absent"` — a `null`
1133
+ * from every attempt — lets the caller fall back.
1134
+ */
1135
+ private findSubmittedOp;
1136
+ /**
1137
+ * Polls for the op's receipt until `deadlineMs` has elapsed, 2 s apart. Time-based so the
1138
+ * wait cannot stretch with the per-poll timeout; `deadlineMs` and `intervalMs` stay
1139
+ * overridable for tests.
1140
+ */
1141
+ private waitForUserOpReceipt;
948
1142
  }
949
1143
 
950
1144
  /** `[simplex.tunnel]` in the config file. */
@@ -1186,8 +1380,13 @@ interface FillerTomlConfig {
1186
1380
  queue?: QueueConfig;
1187
1381
  logging?: string;
1188
1382
  watchOnly?: boolean | Record<string, boolean>;
1189
- substratePrivateKey: string;
1190
- hyperbridgeWsUrl: string;
1383
+ /**
1384
+ * The Hyperbridge account that signs bid extrinsics and holds BRIDGE for their deposits.
1385
+ * Optional: without it the solver bids on the HyperFX orderbook alone.
1386
+ */
1387
+ substratePrivateKey?: string;
1388
+ /** The Hyperbridge WebSocket endpoint bids go to. Required when a key is set. */
1389
+ hyperbridgeWsUrl?: string;
1191
1390
  /**
1192
1391
  * Hyperbridge indexer GraphQL endpoint, used to backfill order details on
1193
1392
  * activity rows recorded before they were captured. Defaults per network
@@ -1214,16 +1413,14 @@ interface FillerTomlConfig {
1214
1413
  maxFeePerGasBumpPercent?: number;
1215
1414
  };
1216
1415
  /**
1217
- * Overfill protection knobs. Defaults: maxOverfillBps=500, maxConsecutiveClamps=3.
1218
- * `maxOverfillBps` is warn-only: FXFiller logs a limit order whose offer exceeds
1219
- * the swapper's ask by more than this, and clamps nothing. `maxConsecutiveClamps`
1220
- * is accepted but dormant: the clamp that fed it was for Uniswap V4 venue pricing,
1221
- * which is gone, so FXFiller never halts.
1416
+ * Removed. `[simplex.overfillProtection]` was dropped when the overfill clamp
1417
+ * and the self-halt were taken out. It is no longer read: boot warns when a
1418
+ * config still carries it, and `simplex init` drops it. Not rejected, because
1419
+ * `simplex init` wrote the section uncommented for existing operators, and
1420
+ * refusing it would crash-loop their Docker deployments. Typed `unknown` so
1421
+ * whatever an old file holds still parses.
1222
1422
  */
1223
- overfillProtection?: {
1224
- maxOverfillBps?: number;
1225
- maxConsecutiveClamps?: number;
1226
- };
1423
+ overfillProtection?: unknown;
1227
1424
  /**
1228
1425
  * How long a signed bid stays executable, in seconds. Defaults to 300 (5 minutes).
1229
1426
  *
@@ -1246,6 +1443,18 @@ interface FillerTomlConfig {
1246
1443
  * order nothing can put a dollar figure on is treated as below it.
1247
1444
  */
1248
1445
  minOrderSizeUsd?: number;
1446
+ /**
1447
+ * The smallest payout, in USD, a partial fill may bid. Defaults to 20.
1448
+ *
1449
+ * A partial fill collects none of the order's fees, and is deliberately exempt from
1450
+ * the fee check and the profit floor: its gas is paid by the margin in the limit
1451
+ * order that prices it. That leaves it with no size floor of its own, so a
1452
+ * near-exhausted limit order, or a wallet just above its gas reserve, used to bid
1453
+ * dust on every matching order — each bid paying fill gas and the relayer fee.
1454
+ * Bids worth less than this are skipped. Set to 0 to bid whatever can be filled.
1455
+ * Full fills are unaffected.
1456
+ */
1457
+ minPartialFillUsd?: number;
1249
1458
  /**
1250
1459
  * Remote access: an outbound SSH tunnel to a rendezvous relay so a phone's
1251
1460
  * SSH client can reach the local web UI. Off unless `enabled = true`; the
@@ -1356,13 +1565,34 @@ declare class TokenSender {
1356
1565
  private readonly userOpSender?;
1357
1566
  /** Only needed to size the paymaster's gas reserve; without it a send reserves nothing. */
1358
1567
  private readonly configService?;
1568
+ /**
1569
+ * Whether the filler's account is EIP-7702-delegated on a chain. A native multi-call
1570
+ * batch is addressed to the account itself, so an undelegated EOA would accept the
1571
+ * transaction and do nothing; without this check the send is reported as done.
1572
+ */
1573
+ private readonly isDelegated?;
1359
1574
  private readonly logger;
1360
1575
  constructor(clientManager: ChainClientManager, solver: HexString,
1361
1576
  /** Live view of the configured vaults so runtime vault edits are honored. */
1362
1577
  getVaults: () => VaultToml[], userOpSender?: UserOpSender | undefined,
1363
1578
  /** Only needed to size the paymaster's gas reserve; without it a send reserves nothing. */
1364
- configService?: FillerConfigService | undefined);
1579
+ configService?: FillerConfigService | undefined,
1580
+ /**
1581
+ * Whether the filler's account is EIP-7702-delegated on a chain. A native multi-call
1582
+ * batch is addressed to the account itself, so an undelegated EOA would accept the
1583
+ * transaction and do nothing; without this check the send is reported as done.
1584
+ */
1585
+ isDelegated?: ((chain: string) => Promise<boolean>) | undefined);
1365
1586
  send(params: SendTokenParams): Promise<SendTokenResult>;
1587
+ /**
1588
+ * Refuses recipients a transfer can never usefully reach. Each is a well-formed address, so
1589
+ * a mistyped or pasted value would otherwise go out: the zero address and a token's own
1590
+ * contract burn or strand the funds, a vault would take the tokens as a donation to its
1591
+ * share holders, and a native or ERC-20 send to the solver itself only spends gas to move
1592
+ * nothing. Vault shares are the exception to the last: they leave as `redeem(shares, to,
1593
+ * solver)`, so sending them to the solver is how an exact amount is withdrawn into the wallet.
1594
+ */
1595
+ private assertRecipient;
1366
1596
  /**
1367
1597
  * A `withdraw(shortfall, solver, solver)` call against a configured vault on
1368
1598
  * this chain whose underlying is the token being sent and that can cover the
@@ -1381,13 +1611,33 @@ declare class TokenSender {
1381
1611
  * reason to refuse a transfer the operator asked for.
1382
1612
  */
1383
1613
  private vaultWithdrawalCall;
1614
+ /**
1615
+ * One bundler lookup for an op this sender submitted, for a caller that has to settle whether
1616
+ * a placement landed. Null when the bundler does not know the op; throws when it could not be
1617
+ * asked. See {@link UserOpSender.lookupUserOpReceipt}.
1618
+ */
1619
+ userOpReceipt(chain: string, userOpHash: HexString): Promise<{
1620
+ txHash: HexString;
1621
+ success: boolean;
1622
+ } | null>;
1384
1623
  /**
1385
1624
  * Executes a batch from the filler wallet: sponsored UserOp first, native tx
1386
1625
  * when no sponsor is available. Shared by every operator-initiated outbound flow.
1626
+ *
1627
+ * `nonceKey` puts the sponsored op on its own EntryPoint nonce lane (default 0). Two ops on one
1628
+ * key read the same `getNonce`, so a caller that can run alongside another key-0 sender passes
1629
+ * its own. It has no effect on the native fallback.
1630
+ *
1631
+ * A `PendingOpOnNonceError` from the sponsored path is not caught: an earlier op from
1632
+ * this wallet is still pending on the nonce and may land, so a native send of the same calls
1633
+ * could pay twice. It reaches the caller, which waits and retries.
1387
1634
  */
1388
- submitCalls(chain: string, calls: ERC7821Call[]): Promise<{
1635
+ submitCalls(chain: string, calls: ERC7821Call[], opts?: {
1636
+ nonceKey?: bigint;
1637
+ }): Promise<{
1389
1638
  txHash: HexString;
1390
1639
  sponsored: boolean;
1640
+ submission: SubmittedUserOp | SubmittedTx;
1391
1641
  }>;
1392
1642
  /**
1393
1643
  * The `approve(Permit2, max)` to run first when the wallet has never approved Permit2 for its fee
@@ -1470,6 +1720,8 @@ interface BridgeTopUpDeps {
1470
1720
  substratePublicKey: HexString;
1471
1721
  /** Coprocessor the order's bids are read from. */
1472
1722
  hyperbridge?: Promise<IntentsCoprocessor>;
1723
+ /** Re-reads the filler's BRIDGE balance the moment a delivery lands, for the dashboard. */
1724
+ refreshBridgeBalance?: () => Promise<void>;
1473
1725
  loggers?: Parameters<typeof moduleLogger>[0];
1474
1726
  }
1475
1727
  /**
@@ -1498,6 +1750,8 @@ declare class BridgeTopUp {
1498
1750
  * reading its last statuses when the operator starts the next one, which must not wait.
1499
1751
  */
1500
1752
  private driving;
1753
+ /** Consecutive failed recovery attempts; reset by recorded progress, an operator restart, a long attempt, and a fresh process. */
1754
+ private reclaimFailures;
1501
1755
  constructor(deps: BridgeTopUpDeps);
1502
1756
  get bridgeToken(): HexString;
1503
1757
  /** Loads the stored top-up and resumes driving it when it was left open. Never rejects. */
@@ -1510,6 +1764,14 @@ declare class BridgeTopUp {
1510
1764
  quote(params: BridgeTopUpQuoteParams): Promise<BridgeTopUpQuote>;
1511
1765
  /** Re-quotes, then places and drives the order in the background. Returns its state. */
1512
1766
  start(params: BridgeTopUpQuoteParams): Promise<BridgeTopUpState>;
1767
+ /**
1768
+ * Throws unless the wallet covers the input and the solver fee, net of the paymaster reserve.
1769
+ * The order goes out with `fees: 0n` and the SDK prices the fee only as it places, in the
1770
+ * host's fee token, which the placement batch then approves alongside the input. A wallet that
1771
+ * covers the input alone would revert inside a sponsored op the paymaster still charges for.
1772
+ * The quote here is for this check only; the SDK still prices the fee it places.
1773
+ */
1774
+ private assertCanPay;
1513
1775
  /** Cancels an unfilled order and refunds its escrowed input to the filler wallet. */
1514
1776
  reclaim(): Promise<BridgeTopUpState>;
1515
1777
  /**
@@ -1520,12 +1782,94 @@ declare class BridgeTopUp {
1520
1782
  */
1521
1783
  private place;
1522
1784
  /**
1523
- * Reads the placement receipt and stores the order as the gateway committed it. Throws
1524
- * when the transaction placed no order, so the top-up is marked failed.
1785
+ * Reads the placement receipt and stores the order as the gateway committed it, from the
1786
+ * `OrderPlaced` log that names this top-up's session key. A UserOp placement's receipt is a
1787
+ * bundle that can carry other users' placements, so the first log is not necessarily ours.
1788
+ *
1789
+ * A mined receipt with no such log, or one that reverted, is settled: the placement is final
1790
+ * and nothing was escrowed, so it is written `failed` and false is returned. A receipt that
1791
+ * cannot be read throws, so the caller retries or falls back to the chain scan.
1525
1792
  */
1526
1793
  private recordPlacement;
1527
- /** Continues an order whose placement landed but was not recorded. */
1794
+ /**
1795
+ * Continues a placement whose outcome was never recorded, using every piece of evidence the
1796
+ * chain offers: the tx receipt if there is one, the bundler's receipt for a UserOp, and the
1797
+ * paying chain's own `OrderPlaced` log for this session. It settles the record as failed only
1798
+ * once the batch can no longer land; otherwise it throws so the caller retries.
1799
+ */
1528
1800
  private recoverPlacement;
1801
+ /**
1802
+ * The transaction that placed this order, found on the paying chain rather than from a
1803
+ * receipt: the `OrderPlaced` log whose `session` is this top-up's session key, from the scan
1804
+ * cursor (or the block stored before submission), each an evidence margin lower, up to the latest.
1805
+ * Returns `undefined` when the record predates the scan; a read failure, or a node behind the
1806
+ * range that must be read, throws, so an unread range is never counted as "not found".
1807
+ * `scannedTo` is the height the scan reached, the reference for every later read of the chain.
1808
+ * See {@link scanGatewayEvent} for the margin and the cursor.
1809
+ */
1810
+ private findPlacementLog;
1811
+ /**
1812
+ * The transaction whose `OrderCancelled` log on the paying chain's gateway names this order,
1813
+ * from the cancel's saved cursor (or a margin below `fromBlock`, the height read before the
1814
+ * cancel was sent) up to the latest block. `cancelOrder` emits it on every cancel that succeeds
1815
+ * and the gateway itself is the emitter, however the cancel was submitted; a cancel that
1816
+ * reverted leaves none. Throws on a read failure, so an unread range is never "not found".
1817
+ */
1818
+ private findCancelLog;
1819
+ /**
1820
+ * Scans the paying chain's IntentGateway for an event this top-up emitted, in chunks, and
1821
+ * returns the transaction of the first log `isOurs` accepts. A scan starts an evidence margin
1822
+ * below its saved cursor, not at it, so a page a lagging backend served empty is read again;
1823
+ * the first scan starts that margin below the height read before the send, since that height
1824
+ * came from one backend of a load-balanced endpoint that can be ahead of the one that took
1825
+ * the broadcast. The cursor is saved per chunk, so a scan that fails late resumes where it
1826
+ * got to. It trails the tip by the margin and never decides anything on its own: the evidence
1827
+ * was read up to `scannedTo`, the latest block, the reference for every later read of the chain.
1828
+ * A read failure, or a node behind the range that must be read, throws.
1829
+ */
1830
+ private scanGatewayEvent;
1831
+ /**
1832
+ * Scans a block range in the small chunks public endpoints accept, handing each page to `read`
1833
+ * and stopping at the first page that resolves a value. A failure propagates, so a caller
1834
+ * retries rather than treating an unread range as empty.
1835
+ */
1836
+ private scanLogs;
1837
+ /**
1838
+ * The paying-chain scan (placement and cancel), in chunks wider than BSC's fill search. A chunk a public endpoint
1839
+ * refuses is halved and retried, down to a floor, before the attempt gives up and the caller
1840
+ * retries. `onChunk` runs after each chunk read without a match. Kept separate from
1841
+ * {@link scanLogs} so the BSC fill search is unchanged.
1842
+ */
1843
+ private scanPlacementLogs;
1844
+ /**
1845
+ * Settles a placement with no order on chain. "Nothing was escrowed" is written only on
1846
+ * positive evidence that the batch can no longer land, read an evidence margin (see
1847
+ * {@link evidenceMarginBlocks}) below the height the scan covered, so it is asserted against state every backend agrees on:
1848
+ *
1849
+ * - a native tx whose nonce the wallet has moved past: some other tx took that nonce, and had
1850
+ * it been ours the scan would have found its `OrderPlaced`. A node that no longer lists the
1851
+ * tx proves nothing, since one backend or mempool can lack a tx another still holds, so a
1852
+ * tx this record has a nonce for keeps waiting. A legacy record has none: it takes the
1853
+ * nonce of a tx the node still lists, and is settled `failed`, unverified, when the node
1854
+ * does not know the tx, because waiting would block every new top-up for good;
1855
+ * - a UserOp whose EntryPoint nonce was consumed, or whose Permit2 permit expired by the
1856
+ * timestamp of the block that nonce is read at, not by this host's clock.
1857
+ *
1858
+ * A tx hash that came from the bundler's receipt is never settled as a native tx: a bundle
1859
+ * reorged out can be re-bundled under a different hash, so it falls to the UserOp rules (the
1860
+ * scan would find a re-bundled placement). A tx the node reports with a block number has been
1861
+ * mined, so its receipt will be readable. A bootstrap UserOp has no expiry and stays pending
1862
+ * until its nonce moves or its log appears: it could still land. Inconclusive cases throw, so
1863
+ * the caller retries.
1864
+ */
1865
+ private settleUnplaceable;
1866
+ /**
1867
+ * Whether the order's deadline has passed. The deadline is a block height on the order's
1868
+ * destination (BSC), so it is read there; the gateway rejects a fill only once the height is
1869
+ * strictly past it. An unreadable height is treated as not passed: an order must not be
1870
+ * settled from a read that failed.
1871
+ */
1872
+ private deadlinePassed;
1529
1873
  private resumeDelivery;
1530
1874
  private resumeOrder;
1531
1875
  /** Follows a placed order through bids to a fill, or to its deadline. */
@@ -1547,9 +1891,14 @@ declare class BridgeTopUp {
1547
1891
  private syncDelivery;
1548
1892
  private readDelivery;
1549
1893
  /**
1550
- * The HyperFungibleToken request the fill dispatched to Hyperbridge. The indexer finds it by
1551
- * the fill's transaction, as the explorer's search does; the fill's own `Sent` log is the
1552
- * fallback while the indexer catches up.
1894
+ * The HyperFungibleToken request the fill dispatched to this filler's Hyperbridge account.
1895
+ *
1896
+ * The fill's own receipt is read first and the `Sent` log it carries is taken, because it is
1897
+ * the transaction this order's output call ran in. A bundled fill can carry several HFT sends,
1898
+ * so only logs from the BRIDGE token addressed to this filler's substrate key count; when more
1899
+ * than one matches, the amount the order's output call sends picks the right one. The indexer
1900
+ * finds the request by the fill's transaction too, as the explorer's search does, and is the
1901
+ * fallback only while the receipt cannot be read — and only when it is unambiguous.
1553
1902
  */
1554
1903
  private deliveryRequest;
1555
1904
  /**
@@ -1560,7 +1909,14 @@ declare class BridgeTopUp {
1560
1909
  /**
1561
1910
  * The transaction that filled the order. The executor reports it only for a fill this
1562
1911
  * process selected, so it comes from the indexer, or, while the indexer has yet to reach
1563
- * BSC's latest blocks, from the gateway's `OrderFilled` log around when the fill was seen.
1912
+ * BSC's latest blocks, from the gateway's `OrderFilled` log.
1913
+ *
1914
+ * The log is searched over the whole range a fill can be in, not around when it was seen: a
1915
+ * fill found late (another filler's, after a restart) landed any time before the deadline. The
1916
+ * range starts where the order became fillable, which placement fixed as the deadline less
1917
+ * {@link ORDER_WINDOW_SECONDS} of BSC blocks (less an evidence margin, since the block time
1918
+ * is measured now and the order was built at an earlier one), and ends at the deadline or the
1919
+ * head. A failed read throws, so the caller retries; it never reads as "no fill".
1564
1920
  */
1565
1921
  private findFill;
1566
1922
  /** The order's statuses as the indexer has them: placed, filled, redeemed or refunded. */
@@ -1572,6 +1928,7 @@ declare class BridgeTopUp {
1572
1928
  */
1573
1929
  sync(): Promise<void>;
1574
1930
  private reconcile;
1931
+ private reconcileRecord;
1575
1932
  /**
1576
1933
  * Submits the request to Hyperbridge with a proof from BSC state. Public BSC endpoints
1577
1934
  * differ in whether they serve `eth_getProof` for recent blocks, so each is tried in turn.
@@ -1586,27 +1943,108 @@ declare class BridgeTopUp {
1586
1943
  * cancel flow from the paying chain (BSC's expiry height finalized, the cancel sent, the
1587
1944
  * cancellation finalized on the source, verified and finalized on Hyperbridge), then the
1588
1945
  * refund. A relayer normally delivers that refund; if none has within a few minutes of
1589
- * Hyperbridge finalizing, the filler submits Hyperbridge's response itself. Each step is
1590
- * recorded as it lands, and a restart resumes from the SDK's persisted progress.
1946
+ * Hyperbridge finalizing, the filler submits Hyperbridge's response itself. The cancel pays
1947
+ * the relayer fee in the source host's fee token, and repeated failures, retried on a
1948
+ * backoff, stop the recovery and return the top-up to `unfilled`, where the operator restarts
1949
+ * it from the SDK's saved progress. The refund claim is rebuilt when its calldata is missing or
1950
+ * a claim reverted, since the SDK reports it only once.
1591
1951
  */
1592
1952
  private driveReclaim;
1953
+ /**
1954
+ * The calls that cancel an unfilled order's escrow from its source chain. The cancel carries
1955
+ * no value: the source host pulls the relayer fee from the filler in its fee token, and the
1956
+ * filler wallet holds stablecoins, not the native token the SDK's quote would spend. The fee
1957
+ * is decoded from the SDK's own calldata so the approval matches what the gateway pulls.
1958
+ */
1959
+ private cancelCalls;
1960
+ /**
1961
+ * Whether a submitted cancel landed. Returns its transaction hash when it did, and undefined
1962
+ * when it can no longer land (it reverted, or its nonce was taken by another transaction), so a
1963
+ * new cancel is safe to send. Throws while it could still land, or while the evidence cannot be
1964
+ * read, which keeps the recovery waiting and retrying.
1965
+ *
1966
+ * A duplicate cross-chain cancel does not revert: `_cancelFromSource` checks only the creator
1967
+ * and the height, so a second one dispatches another GET request and pulls the relayer fee
1968
+ * again. A cancel is therefore resent only on positive evidence that it cannot land. The
1969
+ * evidence, strongest first:
1970
+ *
1971
+ * 1. The receipt: a tx's by hash, a UserOp's from the bundler if it answers. A bundler that
1972
+ * cannot be asked (it lost the op, is down, or its URL was removed) is not fatal.
1973
+ * 2. The paying chain's own `OrderCancelled` log for this order, scanned from the height read
1974
+ * before the send, which backs the cancel whatever the bundler says. Its transaction is the
1975
+ * cancel.
1976
+ * 3. With no log up to `scannedTo`, the nonce rules, read an evidence margin below it: the
1977
+ * wallet's nonce is past a tx's, or the EntryPoint's is past the op's, so some other
1978
+ * transaction took it; or a Permit2 op's deadline has passed by the chain's own clock.
1979
+ * 4. Anything else waits.
1980
+ */
1981
+ private settleCancel;
1982
+ /** How the fee token reads in an error: USDC/USDT when configured, else its raw address in raw units. */
1983
+ private feeTokenLabel;
1593
1984
  /**
1594
1985
  * Submits Hyperbridge's finalized response to the source chain's ISMP handler, which
1595
1986
  * refunds the escrow, as the Hyperbridge app's "Claim funds" does.
1596
1987
  */
1597
1988
  private claimRefund;
1598
1989
  /**
1599
- * Whether the escrow is back with the filler, from the source gateway or the indexer's
1600
- * REFUNDED status; records the refund as the recovery's last step when it is.
1990
+ * Builds Hyperbridge's finalized response for the cancel's GET request again, from the SDK's
1991
+ * own snapshot of it. The SDK reports the calldata once, proven at the height known then;
1992
+ * this is what replaces calldata that reverted or was never saved.
1993
+ */
1994
+ private rebuildClaim;
1995
+ /** The cancel's GET request: as recorded, else read back from the cancel's receipt. */
1996
+ private cancelCommitment;
1997
+ /** The GET request the IntentGateway on `chain` dispatched through its host, among a cancel receipt's logs. */
1998
+ private cancelRequestCommitment;
1999
+ /**
2000
+ * Whether there is nothing left to reclaim: the escrow is back with the filler, as the source
2001
+ * gateway reports it, which is recorded as the recovery's last step. The indexer's REFUNDED
2002
+ * status only supplies that step's tx hash and time: it is not evidence on its own.
2003
+ * `isOrderRefunded` reads the escrow and is true for an empty one, including an order that was
2004
+ * never placed, so it only counts for a record whose placement was seen (`commitment`).
2005
+ *
2006
+ * An empty escrow is also what a fill leaves: `IntentsBase._withdraw` releases it for a redeem
2007
+ * too. So before calling it a refund the order's fill is checked on BSC ({@link filledByOther}),
2008
+ * and an order that filled moves to `delivering` instead (also true, since the reclaim has
2009
+ * nothing to do).
2010
+ *
2011
+ * An escrow read that fails reads as "not refunded" so the reclaim goes on to the cancel; a
2012
+ * caller that records an outcome from the answer passes `strict` to have it throw instead.
1601
2013
  */
1602
2014
  private refunded;
2015
+ /**
2016
+ * Whether someone other than the order's creator took the order on BSC. The gateway's
2017
+ * `_filled[commitment]` cannot tell a fill from a refund by itself: a fill sets it to the
2018
+ * filler, but `IntentsBase._withdraw` sets it to the beneficiary on every finalising
2019
+ * withdrawal, and a destination-side cancel sets it to `order.user`. A same-chain top-up's own
2020
+ * cancel, or a third party's, therefore leaves it non-zero, so only an address that is not the
2021
+ * creator counts as a fill (`isOrderFilled` in the SDK would count both). A read that fails
2022
+ * throws: neither `reclaimed` nor `delivering` is recorded from a value that was not read.
2023
+ */
2024
+ private filledByOther;
1603
2025
  private hasRecoveryStep;
1604
- /** Records a recovery step once, at the time it landed (or now). */
2026
+ /**
2027
+ * Records a recovery step once, at the time it landed (or now). `also` is written in the same
2028
+ * update, for what a restart must never see without the step.
2029
+ */
1605
2030
  private recordRecoveryStep;
1606
- /** Runs one background flow for the record; a failure is recorded rather than thrown. */
2031
+ /**
2032
+ * Schedules a retry in `delayMs` ({@link DELIVERY_RETRY_MS} unless given), but only while the
2033
+ * record it was scheduled for is still the current one. A timer from a finished top-up must
2034
+ * never drive the next one: a top-up the operator started after this record was replaced has
2035
+ * its own state to protect.
2036
+ */
2037
+ private scheduleRetry;
2038
+ /**
2039
+ * Runs one background flow for the record; a failure is recorded rather than thrown. Every
2040
+ * write the flow makes, its failure handling included, is bound to this record.
2041
+ */
1607
2042
  private drive;
2043
+ private driveRecord;
1608
2044
  /** Keeps what the executor reported, for the timeline's offers and its links. */
1609
2045
  private recordEvent;
2046
+ /** Whether the calling flow was started for a record that has since been replaced. */
2047
+ private superseded;
1610
2048
  private update;
1611
2049
  private persist;
1612
2050
  private buildOrder;
@@ -1684,30 +2122,36 @@ interface StoredBid {
1684
2122
  /** The order was seen filled on-chain, so this bid can never win — reclaim its deposit now. */
1685
2123
  dead: boolean;
1686
2124
  /**
1687
- * What this bid holds against the operator's limit orders, at 1e18, in the
1688
- * order the payout draws on them. Empty for a bid placed before limit orders
1689
- * priced anything, and empty again once the hold has been settled, whether it
1690
- * was released because the bid lost or converted because the bid filled.
2125
+ * The HyperFX orderbook took this bid, so a swapper can execute it whatever Hyperbridge said.
2126
+ * The orderbook serves a bid for its TTL and nothing withdraws it, so this never changes; the
2127
+ * bid is live there until its op's `validUntil`. False for a bid the orderbook refused or was
2128
+ * not offered, and for rows from before bids went to the orderbook.
2129
+ */
2130
+ onOrderbook: boolean;
2131
+ /**
2132
+ * The limit order that priced this bid and the terms it signed, written when the bid is stored
2133
+ * and never changed. Null for a bid no limit order priced.
1691
2134
  *
1692
- * More than one when a swap drew on several levels: the orderbook quotes a
1693
- * same-chain swapper across every level that can fill the trade together, so a
1694
- * bid may be meeting several of the operator's own orders at once.
2135
+ * Provenance only: nothing is held against the order. The order's on-chain budget refuses a
2136
+ * fill past its cap, and settlement re-reads that budget rather than doing arithmetic on this.
1695
2137
  */
1696
- reservations: LimitOrderHold[];
2138
+ pricedBy: BidPricing | null;
1697
2139
  }
1698
- /** One limit order and what a bid holds against it, at 1e18. */
1699
- interface LimitOrderHold {
2140
+ /** The limit order a bid drew on and what the bid signed against it. */
2141
+ interface BidPricing {
1700
2142
  limitOrderId: string;
1701
- amount: string;
2143
+ /** The output the bid offered to pay, at 1e18. */
2144
+ payout: string;
1702
2145
  /**
1703
- * The take the bid signed beside `amount`, in the input token's raw units. With it, settlement
1704
- * works out what the gateway charged: the escrow it released at `amount / take`. Holds recorded
1705
- * before bids carried their own rate have none.
2146
+ * The take the bid signed beside `payout`, in the input token's raw units. With it, settlement
2147
+ * works out what the gateway charged: the escrow it released at `payout / take`, and which of
2148
+ * several bids on one order a fill executed. Bids recorded before bids carried their own rate
2149
+ * have none.
1706
2150
  */
1707
2151
  take?: string;
1708
2152
  /**
1709
2153
  * The input token's decimals on the order's source chain, which is where `take` and the escrow
1710
- * a fill releases are counted. With it, settlement records what a fill took in at 1e18. Holds
2154
+ * a fill releases are counted. With it, settlement records what a fill took in at 1e18. Bids
1711
2155
  * recorded before fills kept their input have none.
1712
2156
  */
1713
2157
  takeDecimals?: number;
@@ -1722,18 +2166,22 @@ interface BidInsert {
1722
2166
  * from the same account, lands after it and reclaims its deposit all the same.
1723
2167
  */
1724
2168
  bid?: string;
1725
- /** What this bid holds against the limit orders that priced it, best first. */
1726
- reservations?: LimitOrderHold[];
2169
+ /** The limit order that priced this bid; see {@link StoredBid.pricedBy}. */
2170
+ pricedBy?: BidPricing;
1727
2171
  extrinsicHash?: string;
1728
2172
  blockHash?: string;
1729
2173
  success: boolean;
1730
2174
  /** Submission is still in the pool; see {@link StoredBid.pending}. */
1731
2175
  pending?: boolean;
1732
2176
  error?: string;
2177
+ /** The orderbook holds this bid; see {@link StoredBid.onOrderbook}. */
2178
+ onOrderbook?: boolean;
1733
2179
  }
1734
2180
  interface BidStats {
1735
2181
  total: number;
2182
+ /** Bids a venue took: Hyperbridge, or the orderbook alone. */
1736
2183
  successful: number;
2184
+ /** Bids no venue took. */
1737
2185
  failed: number;
1738
2186
  retracted: number;
1739
2187
  /** Deposits still locked: successful or pending, and not yet retracted. */
@@ -1772,35 +2220,29 @@ interface BidStore {
1772
2220
  *
1773
2221
  * Resolves false when no unretracted bid matched (already retracted, or never
1774
2222
  * stored) — the caller treats that as success, not an error.
1775
- */
1776
- markRetracted(commitment: string, retractExtrinsicHash: string | null): Promise<boolean>;
1777
- /** Flags a bid dead (its order was filled on-chain). False when nothing matched. */
1778
- markDead(commitment: string): Promise<boolean>;
1779
- /**
1780
- * Takes what this bid holds, exactly once, and returns it.
1781
2223
  *
1782
- * A losing bid gives its holds back and a winning one converts them into
1783
- * draw-downs, and both routes end at the same bid row — a bid that won is still
1784
- * retracted eventually, by the stale sweep, so an unguarded release would undo
1785
- * a conversion that already happened. Whichever settles first claims them here;
1786
- * the other gets an empty list and does nothing.
2224
+ * With `rows` (the {@link StoredBid.id}s) only those bids are marked: a retraction
2225
+ * closes the bids it sent retractions for, not one stored on the commitment while it
2226
+ * was in flight. Without, every unretracted bid on the commitment is marked. An empty
2227
+ * `rows` marks nothing.
1787
2228
  */
2229
+ markRetracted(commitment: string, retractExtrinsicHash: string | null, rows?: readonly number[]): Promise<boolean>;
1788
2230
  /**
1789
- * Takes the holds off a bid, exactly once, and hands them to the caller.
1790
- *
1791
- * With a `bid` it claims that one bid; without, every outstanding hold on the
1792
- * commitment, which is what a filled or dead order needs so no bid's hold is
1793
- * left behind.
2231
+ * Flags a bid dead, so the sweep retries its retraction next cycle rather than after
2232
+ * the TTL: its order was filled on-chain, or a retraction selected it and could not
2233
+ * close it. With `rows` (the {@link StoredBid.id}s) only those bids are flagged;
2234
+ * without, every unretracted bid on the commitment. An empty `rows` flags nothing.
2235
+ * False when nothing matched.
1794
2236
  */
1795
- claimReservation(commitment: string, bid?: string): Promise<LimitOrderHold[]>;
2237
+ markDead(commitment: string, rows?: readonly number[]): Promise<boolean>;
1796
2238
  /**
1797
- * Every bid that drew on a limit order, newest first. What makes a `remaining`
1798
- * explicable to the operator: which bids took the difference.
2239
+ * Every bid a limit order priced, newest first, from each bid's `pricedBy`. What
2240
+ * makes a `remaining` explicable to the operator: which bids drew on the order.
1799
2241
  */
1800
2242
  byLimitOrder(limitOrderId: string, limit?: number): Promise<StoredBid[]>;
1801
2243
  /** Newest first. Implementations should cap `limit` at a few hundred. */
1802
2244
  recent(limit?: number): Promise<StoredBid[]>;
1803
- /** Failed bids, newest first — for debugging. */
2245
+ /** Bids no venue took (neither Hyperbridge nor the orderbook), newest first — for debugging. */
1804
2246
  failed(limit?: number): Promise<StoredBid[]>;
1805
2247
  byDateRange(from: Date, to: Date): Promise<StoredBid[]>;
1806
2248
  stats(): Promise<BidStats>;
@@ -1965,8 +2407,6 @@ interface LimitOrder {
1965
2407
  size: string;
1966
2408
  /** Output not yet delivered. */
1967
2409
  remaining: string;
1968
- /** Output promised to bids that have neither filled nor been retracted. */
1969
- reserved: string;
1970
2410
  /** Source chains this order accepts swaps from. Never empty. */
1971
2411
  acceptedSources: string[];
1972
2412
  /** TTL written into each posting. */
@@ -2026,15 +2466,8 @@ interface LimitOrderPosting {
2026
2466
  lastError: string | null;
2027
2467
  }
2028
2468
  /**
2029
- * Persistent record of the operator's limit orders.
2030
- *
2031
- * This is inventory, not a cache: `remaining` and `reserved` are what stop two
2032
- * chains from paying out the same liability twice, so a store that loses writes
2033
- * overcommits real money.
2034
- */
2035
- /**
2036
- * One fill that drew a limit order down: kept apart from the bid that priced it, whose
2037
- * holds are cleared on settlement, so an order keeps its history across every resize.
2469
+ * One fill of a limit order, kept apart from the bid row so an order keeps its history
2470
+ * across every resize and repost.
2038
2471
  */
2039
2472
  interface LimitOrderFill {
2040
2473
  id: number;
@@ -2052,6 +2485,12 @@ interface LimitOrderFill {
2052
2485
  amountIn: string | null;
2053
2486
  /** The fill's transaction on the order's fill chain, when the event carried it. */
2054
2487
  transactionHash: string | null;
2488
+ /**
2489
+ * Which log of that transaction the fill is. One transaction can carry several of our
2490
+ * fills, so the hash alone does not name one. Null for a fill recorded before this was
2491
+ * kept, and for one whose event carried none.
2492
+ */
2493
+ logIndex: number | null;
2055
2494
  /** SQLite-style "YYYY-MM-DD HH:MM:SS" in UTC. */
2056
2495
  filledAt: string;
2057
2496
  }
@@ -2062,6 +2501,7 @@ interface LimitOrderFillInsert {
2062
2501
  amount: string;
2063
2502
  amountIn?: string | null;
2064
2503
  transactionHash?: string | null;
2504
+ logIndex?: number | null;
2065
2505
  }
2066
2506
  /**
2067
2507
  * A fill with the terms of the order it drew on: what profitability is worked out from. The
@@ -2079,6 +2519,13 @@ interface LimitOrderFillRecord {
2079
2519
  amountIn: string | null;
2080
2520
  filledAt: string;
2081
2521
  }
2522
+ /**
2523
+ * Persistent record of the operator's limit orders.
2524
+ *
2525
+ * `remaining` follows the order's on-chain budget, which is what actually refuses a fill
2526
+ * past the order's size: it is lowered to that budget after each fill and by the periodic
2527
+ * tally reconciliation, and never raised.
2528
+ */
2082
2529
  interface LimitOrderStore {
2083
2530
  create(order: LimitOrderInsert): Promise<LimitOrder>;
2084
2531
  get(id: string): Promise<LimitOrder | null>;
@@ -2096,51 +2543,30 @@ interface LimitOrderStore {
2096
2543
  setPosting(id: string, posting: LimitOrderPosting, only?: readonly LimitOrderStatus[]): Promise<LimitOrder | null>;
2097
2544
  setStatus(id: string, status: LimitOrderStatus, lastError?: string | null, only?: readonly LimitOrderStatus[]): Promise<LimitOrder | null>;
2098
2545
  /**
2099
- * Adds `amount` to `reserved`, but only while the order is `open` and
2100
- * `remaining` covers this one hold. Resolves false when it does not.
2546
+ * Lowers an `open` or `resizing` order's `remaining` to `room`, what the solver's
2547
+ * account on chain will still pay for this order, at 1e18. Never raises it.
2548
+ * Returns the order when it was lowered, null otherwise, including for an order in
2549
+ * any other status.
2101
2550
  *
2102
- * Other bids' holds do not count against it: a pending bid must not stop the
2103
- * next one going out, so the limit order bounds each bid and what fills draw
2104
- * down, not the sum of bids still waiting. The hold is bookkeeping, turned into
2105
- * a draw-down if the bid wins and given back if it loses. The write is still
2106
- * guarded on the `reserved` it read, so two holds landing together both count.
2107
- */
2108
- reserve(id: string, amount: string): Promise<boolean>;
2109
- /** Gives a reservation back, after a bid was retracted, lost or found dead. */
2110
- release(id: string, amount: string): Promise<void>;
2111
- /**
2112
- * Works the order down by output that has actually been delivered, floored at
2113
- * zero. Returns the order as it now stands, or null when there is none.
2114
- */
2115
- drawDown(id: string, amount: string): Promise<LimitOrder | null>;
2116
- /**
2117
- * Lowers an `open` order's `remaining` to `room + reserved`, where `room` is
2118
- * what the solver's account on chain will still pay for this order, at 1e18.
2119
- * Never raises it. Returns the order when it was lowered, null otherwise.
2551
+ * `only` narrows the statuses it may act on, like `setStatus` and `setPosting` take;
2552
+ * it never widens them, so a status other than `open` or `resizing` is never clamped.
2553
+ * Both callers pass it, because the two statuses mean different things. A repost
2554
+ * holds a row in `resizing` and lowers it to the tally before it posts, so that call
2555
+ * passes `["resizing"]`: a store that refused `resizing` would have the repost
2556
+ * advertise the pre-fill size. A fill's sync starts a repost of its own after it
2557
+ * lowers the row, so it passes `["open"]`: a row a repost already holds is left to
2558
+ * it, and two reposts of one row would orphan a book entry.
2120
2559
  *
2121
- * `reserved` is added back because a fill the chain has already counted, but
2122
- * that has not been drawn down here yet, still holds its amount there until it
2123
- * settles. Clamping to `room` alone would take that fill off twice.
2560
+ * A custom store must apply the status check and the write atomically: a row that
2561
+ * moved to another status after the caller read it is left as it is.
2124
2562
  */
2125
- clampRemaining(id: string, room: string): Promise<LimitOrder | null>;
2126
- /** Records a fill against its limit order. Called alongside the draw-down it explains. */
2563
+ clampRemaining(id: string, room: string, only?: readonly LimitOrderStatus[]): Promise<LimitOrder | null>;
2564
+ /** Records a fill against its limit order, for its history and profit. */
2127
2565
  recordFill(fill: LimitOrderFillInsert): Promise<void>;
2128
2566
  /** Every fill of every limit order, oldest first, each with its order's terms. */
2129
2567
  fillHistory(): Promise<LimitOrderFillRecord[]>;
2130
2568
  /** A limit order's fills, newest first. */
2131
2569
  fills(limitOrderId: string, limit?: number): Promise<LimitOrderFill[]>;
2132
- /**
2133
- * Runs `settle` as one unit where the backend can.
2134
- *
2135
- * A fill claims what its bid held, works the orders down by what went out and
2136
- * gives the rest back, and a crash between those leaves the hold released
2137
- * against an order that was never drawn down. The bid rows live in the same
2138
- * database as the limit orders, which is what lets one transaction cover both.
2139
- *
2140
- * Only store calls belong inside: they are synchronous underneath, so nothing
2141
- * else interleaves on the connection, which would not hold for a network call.
2142
- */
2143
- transaction<T>(settle: () => Promise<T>): Promise<T>;
2144
2570
  }
2145
2571
  /** Operator state that must survive a restart. */
2146
2572
  interface RuntimeState {
@@ -2167,8 +2593,59 @@ interface StoredBridgeTopUp {
2167
2593
  sessionPrivateKey?: HexString;
2168
2594
  commitment?: HexString;
2169
2595
  placeTxHash?: HexString;
2596
+ /**
2597
+ * The wallet nonce a native placement tx was sent with. Only the wallet's nonce moving past it
2598
+ * shows the tx can no longer be mined; a node that forgot the tx shows nothing.
2599
+ */
2600
+ placeTxNonce?: number;
2601
+ /**
2602
+ * The placement UserOp the bundler accepted when its receipt never arrived. The batch may have
2603
+ * been mined, so the record stays pending and the op is looked up again; without it a restart
2604
+ * would declare that nothing was escrowed while the order could still be live.
2605
+ */
2606
+ placeUserOpHash?: HexString;
2607
+ /** The EntryPoint `nonce` the op was signed with, as a decimal string (the record is JSON-persisted). */
2608
+ placeUserOpNonce?: string;
2609
+ /** The EntryPoint `nonceKey` the op was signed with, as a decimal string. */
2610
+ placeUserOpNonceKey?: string;
2611
+ /**
2612
+ * Whether a UserOp placement's paymaster attached a validity deadline (Permit2 mode). A
2613
+ * bootstrap op has none, so it can still land; without this a restart cannot tell them apart.
2614
+ */
2615
+ placeUserOpExpires?: boolean;
2616
+ /**
2617
+ * When the placement batch was submitted, in ms. Dates a UserOp's permit window. Records from
2618
+ * before this was recorded are dated by `stageTimes.placing`, then `createdAt`; `updatedAt` is
2619
+ * rewritten by every save, so it never ages.
2620
+ */
2621
+ placeSubmittedAt?: number;
2622
+ /**
2623
+ * The order's session-key address, matched against `OrderPlaced.session`. A placement receipt
2624
+ * can carry other users' placements (a UserOp is a bundle), so only the log naming this address
2625
+ * is this top-up's.
2626
+ */
2627
+ placeSession?: HexString;
2628
+ /** Block the paying chain was at before the placement was submitted, as a decimal string; the scan starts here. */
2629
+ placeFromBlock?: string;
2630
+ /**
2631
+ * The next block a recovery scan reads, as a decimal string. Saved after each chunk and trailing
2632
+ * the tip by the evidence margin; the next scan starts a margin below it, so a page a lagging
2633
+ * backend served empty is read again.
2634
+ */
2635
+ placeScannedTo?: string;
2170
2636
  fillTxHash?: HexString;
2637
+ /**
2638
+ * The cancel's transaction. With no `reclaimSubmission` it is a cancel whose send was confirmed
2639
+ * (the only way it was ever written before submissions were kept), and is handed to the SDK as is.
2640
+ */
2171
2641
  reclaimTxHash?: HexString;
2642
+ /**
2643
+ * The cancel as submitted, kept until the `ORDER_CANCELED` step is recorded. It is settled from
2644
+ * on-chain evidence before the SDK is handed a hash or a new cancel is sent: a duplicate
2645
+ * cross-chain cancel does not revert, it dispatches another GET request and pays the relayer fee
2646
+ * again. See {@link StoredSubmission}.
2647
+ */
2648
+ reclaimSubmission?: StoredSubmission;
2172
2649
  /** The HyperFungibleToken request that carries the BRIDGE to Hyperbridge. */
2173
2650
  deliveryCommitment?: HexString;
2174
2651
  /** The Hyperbridge extrinsic that delivered it, when this filler relayed it. */
@@ -2185,12 +2662,37 @@ interface StoredBridgeTopUp {
2185
2662
  deliveryStatuses?: DeliveryStatus[];
2186
2663
  /** The unfilled order's recovery, step by step, as the SDK's cancel flow reported it. */
2187
2664
  recoverySteps?: RecoveryStepRecord[];
2665
+ /** The GET request a cross-chain cancel dispatched; Hyperbridge answers it with the refund response. */
2666
+ getCommitment?: HexString;
2188
2667
  /** Hyperbridge's finalized response, which refunds the escrow when submitted on the source. */
2189
2668
  claimCalldata?: HexString;
2190
2669
  /** The filler's own refund claim, when no relayer delivered it in time. */
2191
2670
  claimTxHash?: HexString;
2192
2671
  error?: string;
2193
2672
  }
2673
+ /**
2674
+ * A submission as kept in the JSON state: bigints as decimal strings, plus the evidence window of
2675
+ * the chain scan that settles it.
2676
+ */
2677
+ type StoredSubmission = ({
2678
+ kind: "tx";
2679
+ txHash: HexString;
2680
+ nonce: number;
2681
+ submittedAt: number;
2682
+ } | {
2683
+ kind: "userOp";
2684
+ userOpHash: HexString;
2685
+ nonce: string;
2686
+ nonceKey: string;
2687
+ /** Whether the paymaster attached a validity deadline; see {@link StoredBridgeTopUp.placeUserOpExpires}. */
2688
+ expires: boolean;
2689
+ submittedAt: number;
2690
+ }) & {
2691
+ /** The paying chain's height, read before the send, as a decimal string; the evidence scan starts a margin below it. */
2692
+ fromBlock: string;
2693
+ /** The next block the scan reads, as a decimal string; see {@link StoredBridgeTopUp.placeScannedTo}. */
2694
+ scannedTo?: string;
2695
+ };
2194
2696
  interface RecoveryStepRecord {
2195
2697
  step: "DESTINATION_FINALIZED" | "ORDER_CANCELED" | "SOURCE_FINALIZED" | "HYPERBRIDGE_DELIVERED" | "HYPERBRIDGE_FINALIZED" | "FUNDS_CLAIMED";
2196
2698
  /** When the step completed, in ms. */
@@ -2294,4 +2796,4 @@ interface InventoryStore {
2294
2796
  since(from: Date): Promise<InventorySnapshot[]>;
2295
2797
  }
2296
2798
 
2297
- export { type LimitOrderPosting as $, type ActivityStore as A, type BidStore as B, ChainClientManager as C, type DerivingSigner as D, type AuthorizationRequest as E, FillerConfigService as F, type BidInsert as G, type BinanceConfig as H, type InventoryStore as I, type CurveConfig as J, type CurvePoint as K, LoggerContext as L, type MpcVaultSignerConfig as M, type Eip7702Authorization$1 as N, type OrderHistoryPage as O, type FillerConfigFile as P, type InventorySnapshot as Q, type ResolvedChainConfig as R, type SignerConfig as S, type TurnkeySignerConfig as T, UserOpSender as U, type VaultToml as V, type WalletTx as W, type LimitOrderFillInsert as X, type LimitOrderFillRecord as Y, type LimitOrderHold as Z, type LimitOrderInsert as _, type Signer as a, type LimitOrderSide as a0, type LimitOrderStatus as a1, type Logger as a2, type OperatorNotification as a3, type PrivateKeySignerConfig as a4, type QueueConfig as a5, type RuntimeState as a6, type SignerTransaction as a7, SignerType as a8, type TypedDataPayload as a9, USD_STABLE_SYMBOLS as aa, type UserProvidedChainConfig as ab, type VaultTomlConfig as ac, type WalletTxKind as ad, addLogSink as ae, assertConfirmationCoverage as af, configureLogger as ag, formatChainKey as ah, getLogger as ai, isRegistrySymbol as aj, normalizeSymbol as ak, parseChainKey as al, registrySymbols as am, validateAssetDefinitions as an, validateConfig as ao, validateVaultToml as ap, type OrderSummary as aq, type Signature as b, type SecretPhraseSignerConfig as c, type ActivityInsert as d, type ActivityEvent as e, type LimitOrderStore as f, AssetRegistry as g, DelegationService as h, type LimitOrder as i, type LimitOrderFilter as j, type SimplexDataStore as k, ConfirmationPolicy as l, type FillerTomlConfig as m, TokenSender as n, BridgeTopUp as o, type AssetDefinition as p, type ChainConfirmationPolicy as q, type LimitOrderFill as r, type StoredBid as s, type RebalancingConfig as t, type LogSink as u, type BidStats as v, type AllowlistConfig as w, type LogLevel as x, type StateStore as y, type ActivityType as z };
2799
+ export { type LimitOrderPosting as $, type ActivityStore as A, type BidStore as B, ChainClientManager as C, type DerivingSigner as D, type AuthorizationRequest as E, FillerConfigService as F, type BidInsert as G, type BidPricing as H, type InventoryStore as I, type BinanceConfig as J, type CurveConfig as K, LoggerContext as L, type MpcVaultSignerConfig as M, type CurvePoint as N, type OrderHistoryPage as O, type Eip7702Authorization$1 as P, type FillerConfigFile as Q, type ResolvedChainConfig as R, type SignerConfig as S, type TurnkeySignerConfig as T, UserOpSender as U, type VaultToml as V, type WalletTx as W, type InventorySnapshot as X, type LimitOrderFillInsert as Y, type LimitOrderFillRecord as Z, type LimitOrderInsert as _, type Signer as a, type LimitOrderSide as a0, type LimitOrderStatus as a1, type Logger as a2, type OperatorNotification as a3, type PrivateKeySignerConfig as a4, type QueueConfig as a5, type RuntimeState as a6, type SignerTransaction as a7, SignerType as a8, type TypedDataPayload as a9, USD_STABLE_SYMBOLS as aa, type UserProvidedChainConfig as ab, type VaultTomlConfig as ac, type WalletTxKind as ad, addLogSink as ae, assertConfirmationCoverage as af, configureLogger as ag, formatChainKey as ah, getLogger as ai, isRegistrySymbol as aj, normalizeSymbol as ak, parseChainKey as al, registrySymbols as am, validateAssetDefinitions as an, validateConfig as ao, validateVaultToml as ap, type OrderSummary as aq, type Signature as b, type SecretPhraseSignerConfig as c, DelegationService as d, type ActivityInsert as e, type ActivityEvent as f, type LimitOrderStore as g, AssetRegistry as h, type LimitOrder as i, type LimitOrderFilter as j, type SimplexDataStore as k, ConfirmationPolicy as l, type FillerTomlConfig as m, TokenSender as n, BridgeTopUp as o, type AssetDefinition as p, type ChainConfirmationPolicy as q, type LimitOrderFill as r, type StoredBid as s, type RebalancingConfig as t, type LogSink as u, type BidStats as v, type AllowlistConfig as w, type LogLevel as x, type StateStore as y, type ActivityType as z };