degenbot.dispatch ================= .. py:module:: degenbot.dispatch .. autoapi-nested-parse:: Companion-layer surface over the Rust dispatch/sim/signer pyclasses. This package re-exports the Rust-owned dispatch, simulation, and transaction signing symbols under stable, seam-agnostic names. Driver code (bot operators, example bots) imports from here — never from the PyO3 wrapper module degenbot._ffi. The Py* prefix and *_py suffix on the FFI names are the seam naming itself: Py* marks a raw pyclass, *_py marks a pyfunction. Those conventions are for the FFI layer's own bookkeeping and should never leak into driver code. This package hides them. .. note:: Most of these are **direct alias re-exports** (from degenbot._ffi import PyX as X), not Python wrapper classes. The Rust engine constructs and consumes these pyclasses / pyfunctions directly — driver code constructs a SimulateContext / TxSigner in Python and passes it to a Rust pyfunction that expects the exact SimulateContext / TxSigner pyclass. A wrapper class would break type identity at the FFI boundary. dispatch_and_submit is the one deliberate exception: it is a thin async wrapper whose ONLY transformation is decoding the leaf's returned record dicts into the typed records of degenbot.dispatch.records (the single home for that wire format). Call-site arguments pass to the FFI pyfunction unchanged — pyclass identity for candidates/dispatcher/signer is preserved. Symbol map (FFI name → stable companion name): - CandidateAssembly → CandidateAssembly - DispatchCandidate → DispatchCandidate - DispatchOutcome → DispatchOutcome - Dispatcher → Dispatcher - SimulateContext → SimulateContext - TxSigner → TxSigner - assemble_dispatch_candidates_py → assemble_dispatch_candidates - build_batch_executor_py → build_batch_executor - dispatch_profitable_py → dispatch_profitable - merge_payload_results_py → merge_payload_results - dispatch_and_submit_py → dispatch_and_submit (wrapper: dict → typed records) - fetch_fee_history_py → fetch_fee_history Submodules ---------- .. toctree:: :maxdepth: 1 /autoapi/degenbot/dispatch/records/index Package Contents ---------------- .. py:class:: SkippedRecord The candidate was skipped — detail set for BROADCAST_FAILED. .. py:attribute:: path_id :type: int .. py:attribute:: reason :type: SubmitSkipReason .. py:attribute:: detail :type: str | None :value: None .. py:data:: SubmitRecord .. py:class:: SubmitSkipReason Bases: :py:obj:`enum.StrEnum` The typed SkipReason vocabulary of the Rust submit leaf. .. py:attribute:: POOLS_CLAIMED :value: 'pools_claimed' .. py:attribute:: DRY_RUN :value: 'dry_run' .. py:attribute:: INJECT_CODE :value: 'inject_code' .. py:attribute:: BROADCAST_FAILED :value: 'broadcast_failed' .. py:class:: SubmittedRecord The tx was broadcast — the resulting tx_hash + claimed nonce. .. py:attribute:: path_id :type: int .. py:attribute:: tx_hash :type: str .. py:attribute:: nonce :type: int .. py:function:: typed_submit_record(raw: collections.abc.Mapping[str, Any], /) -> SubmitRecord Decode one FFI submit-record dict into a typed record. :returns: The typed record. :raises DegenbotValueError: On an unrecognized or missing "kind", an unknown skip "reason", or missing payload keys — wire drift, loud. .. py:class:: SubmitContext Per-call parameters the companion submit seam carries to the FFI leaf. The Rust ``dispatch_and_submit_py`` pyfunction takes these as keyword arguments; grouping them here keeps the companion signature stable as the runner's submit knobs grow. ``broadcast_providers`` is the relay fan-out (one Rust provider pyclass per endpoint), or ``None`` for the public mempool. .. py:attribute:: signer :type: degenbot._ffi.submission.TxSigner .. py:attribute:: operator_nonce :type: int .. py:attribute:: current_block :type: int .. py:attribute:: dry_run :type: bool .. py:attribute:: inject_code :type: bool .. py:attribute:: broadcast_providers :type: list[degenbot._ffi.provider.AsyncAlloyProvider] | None :value: None .. py:function:: dispatch_and_submit(candidates: list[degenbot._ffi.submission.SubmitCandidate], dispatcher: degenbot._ffi.submission.Dispatcher, provider: degenbot._ffi.provider.AsyncAlloyProvider, *, context: SubmitContext, submit_leaf: collections.abc.Callable[..., Any] = _dispatch_and_submit_py) -> list[records.SubmitRecord] :async: Await the Rust submit leaf and decode its records to typed values. The FFI pyfunction returns raw dicts (a "kind" discriminator plus payloads); this companion wrapper is the single home for decoding them into SubmittedRecord / SkippedRecord — unknown wire values raise instead of dropping a submission event. ``context`` carries the per-call submit knobs through to the pyfunction unchanged; pyclass identity for candidates/dispatcher/provider/context.signer is preserved. ``submit_leaf`` is the FFI seam (tests inject a fake leaf returning raw dicts); the default is the production pyfunction. :returns: The typed per-candidate records, in submit order.