Operators

Solver integration quick start

Join the Solver network, prepare credentials and liquidity, and verify your first payment in a provisioned test environment.

Arrange participation

Complete liquidity-provider, legal, and compliance onboarding with Anyflo as described in the liquidity-provider overview. Anyflo provisions an active solver identity and registers your first public authentication key.

During onboarding you will receive:

  • Your solverId and the process for registering your first public authentication key with its positive integer kid.
  • The environment’s SolverHub HTTP origin and full WSS URL, including /connect. The HTTP origin has neither a /v1 nor a /connect suffix.
  • Supported source/destination routes: Order.senderChain, Order.recipientChain, Order.tokenIn and Order.tokenOut, plus deployed contract/package/registry settings for that environment. Token identifiers are addresses or coin types, not display symbols.
  • If using the supplied software, authenticated package-registry access and an exact released SOLVER_VERSION confirmed by Anyflo. A source manifest version is not evidence of a published package.

There is no anonymous self-registration step. Hosted Gateway administrator routes are not LP self-service endpoints. Do not substitute customer anyflo_sk_ API keys for SolverHub authentication credentials.

Choose an implementation

Choose one of the three operating modes:

  • Reference Solver directly: use the supplied standalone application for the operator workflow below. Follow installation and scoped registry setup; it requires Bun 1.4.4 or newer and access to both @anyflo/solver and its dependencies.
  • Custom implementation: listen for new orders and implement the SolverHub API, including JWT authentication, the WebSocket protocol and recovery, and active-order catch-up. Your software must also implement verification, payout execution, persistence and recovery. Bun and the reference application’s configuration are not requirements for a custom client.
  • Reference Solver as an adapter: customize the supplied application to integrate your LP systems with SolverHub. This requires development in the Reference Solver; the package is an application, not an embeddable Solver SDK or a ready-made connector. The reference application instructions below are a starting point, not a complete guide to your custom integration.

All approaches need registered credentials, provisioned routes and funded wallets before handling orders.

Order lifecycle

An Order specifies the source and destination chains, tokens and payout recipient. For fixed input (Order.typ: 1), solvers quote the output amount; for fixed output (Order.typ: 2), they quote the required input amount.

sequenceDiagram participant A as Anyflo participant S as Solver participant U as Sender participant C as Source chain participant D as Destination chain A->>S: Broadcast payment order S->>A: Submit bid A->>S: Select and assign order S->>A: Accept with solverAddress and directDeposit A->>U: Provide deposit instructions U->>C: Deposit source funds C-->>A: Indexed deposit A->>S: Notify deposit S->>C: Verify deposit and required finality S->>D: Fund recipient payout D-->>A: Indexed payout confirmation A->>S: Notify delivery confirmation

The default bidding and acceptance windows are each 1,500 milliseconds. Rejection or failure to accept in time can cause reassignment; the best quote does not necessarily win. Acknowledging a notification does not replace deposit verification or on-chain payout confirmation. Reassignment, cancellation and reorganizations require reconciliation, not blindly continuing payment. See Verify an order for the operator checks and the SolverHub API for exact messages and recovery.

Pricing is the LP’s responsibility. Account for the payment outcome, inventory, gas, rebalancing and operating costs for both fixed-input and fixed-output orders. The Reference Solver pricing rules are not mandatory for custom implementations.

Prepare credentials and routes

Initialize the reference application

First complete the Reference Solver installation. Then set SOLVER_ID to your assigned positive integer solverId; 123 below is illustrative and must match the Reference Solver’s solverId configuration and registered identity.

export SOLVER_ID=123
mkdir -p solver-operator
cd solver-operator
anyflo-solver init
anyflo-solver gen-auth-key --solver-id "$SOLVER_ID" --keyrecord

Keep this working directory persistent: initialization creates missing configuration files without overwriting existing files, and the running process stores its state here.

Key-generator stdout contains a private JWK. Run it in a private terminal, not shared logs or recorded CI output. Securely retain the printed SOLVER_AUTH_PRIVATE_KEY assignment; do not redirect output over an existing wallet .env. Send only the generated public solver-registerkey-<solverId>-<kid>.json record to Anyflo, and wait for registration confirmation. Never send private JWK fields. Authentication keys and wallet signing keys are separate.

For custom software, generate a compatible Ed25519 identity using the authentication contract, retain the private key securely, and arrange registration of its public key and positive numeric key ID with Anyflo. The reference CLI is not mandatory for that path.

Configure the reference application

Replace the initialized solver.config.json with the following minimal structure, substituting all deployment-specific values before running it. This is a Base Sepolia (eip155:84532) illustration, not an existing Anyflo deployment or a usable collection of addresses.

{
  "solverId": 123,
  "solverHubWsUrl": "wss://solverhub.example.com/connect",
  "verifyTxs": true,
  "runApproveTxs": false,
  "retryPendingIntervalMs": 30000,
  "dbPath": "solver-state.db",
  "evmChains": [
    {
      "chain": "eip155:84532",
      "rpcUrl": "https://base-sepolia-rpc.example.com",
      "depositAccountAddress": "0x1111111111111111111111111111111111111111",
      "deliveryAccountAddress": "0x2222222222222222222222222222222222222222",
      "solverAddress": "0x3333333333333333333333333333333333333333",
      "directDeposit": false,
      "supportedTokens": [
        "0x4444444444444444444444444444444444444444"
      ]
    }
  ]
}
Example valueRequired replacement or confirmation
123Your assigned solver ID, matching the registered public key.
wss://solverhub.example.com/connectThe full WSS URL assigned for your test environment.
eip155:84532Confirm Base Sepolia is provisioned for your test route; use matching deployment, RPC, token, and wallet settings.
https://base-sepolia-rpc.example.comYour reachable Base Sepolia RPC endpoint.
0x1111…1111The environment’s deployed source deposit account contract address (evmChains[].depositAccountAddress).
0x2222…2222The environment’s deployed destination delivery account contract address (evmChains[].deliveryAccountAddress), not the signing wallet or payout recipient.
0x3333…3333Your source-chain receiving address (evmChains[].solverAddress), submitted as OrderAssignAck.payload.solverAddress and recorded as Order.solverAddress; not a supplied contract address.
0x4444…4444A supported token contract address (evmChains[].supportedTokens[]) confirmed for this deployment. Add only configured tokens.
directDeposit: falseConfirm the route supports indirect deposits; evmChains[].directDeposit supplies OrderAssignAck.payload.directDeposit, recorded as Order.directDeposit. Configure direct receipts only as agreed for the deployment.

The destination signing wallet’s address comes from its configured private key (EVM_84532_PRIVATE_KEY in this example), not evmChains[].deliveryAccountAddress. It is not a property of Order: Order.recipientAddr is the payout recipient, and Order.solverAddress receives source-chain value. With Order.directDeposit: false, source value is credited for Order.solverAddress; it does not automatically replenish the destination signing wallet. See the assignment message contract.

Remove every unconfigured template chain and the Sui configuration. This single-chain example does not provide cross-chain coverage: configure both chains, their wallets, and their deployment settings before quoting a cross-chain route. See the complete configuration schema and wallets and approvals.

Replace bidding-price.jsonc with this complete minimal pricing file:

{
  "minFee": 500,
  "defaults": {
    "sameCurrencySameChain": { "type": "rational", "value": 20 },
    "sameCurrencyDiffChain": { "type": "rational", "value": 20 },
    "diffCurrencySameChain": { "type": "rational", "value": 20 },
    "diffCurrencyDiffChain": { "type": "rational", "value": 20 }
  }
}

These values illustrate syntax, not recommended prices. Here 20 is 20 basis points and 500 is a floor in raw token base units, not USD. Review token decimals, inventory, gas, and rebalancing costs before setting prices. The full pricing rules and route overrides define how these amounts affect fixed-input and fixed-output quotes.

Fund and authorize your routes

For any implementation, prepare the source receiving address submitted in OrderAssignAck.payload.solverAddress (recorded as Order.solverAddress) and the destination signing wallet that funds Order.amountOut of Order.tokenOut to Order.recipientAddr on Order.recipientChain. The signing wallet is not an Order property. Configure supported routes/tokens and reliable RPCs. Fund destination signing wallets with payout inventory and each signing wallet with native gas. Authorize the destination EVM delivery contract to spend the required tokens before connecting; the Reference Solver example sets runApproveTxs: false. Check allowances and balances for every configured token and chain, not only one sample route.

Source receipts depend on the deployed contracts and Order.directDeposit:

  • Direct receipts (true): source funds transfer to Order.solverAddress.
  • Indirect EVM receipts (false): the source deposit contract credits solverBalances for Order.solverAddress and Order.tokenIn; that address must authorize withdrawal.

Source receipts and destination inventory are separate balances. Plan operator-managed withdrawals and rebalancing rather than assuming a completed payment restores liquidity on another chain. See wallets and approvals for the supplied application’s behavior.

Connect in a test environment

Reference application

Securely inject SOLVER_AUTH_PRIVATE_KEY as the generated JSON {kid,jwk} and only the wallet keys for configured chains. For the example above, supply EVM_84532_PRIVATE_KEY as the destination wallet’s 0x-prefixed private key. Do not include real secrets in shell examples, shared logs, or version control.

Bun can load a working-directory .env; restrict its permissions and never commit it. A secret manager may instead inject the environment. See secret formats and overrides.

From the persistent operator directory, after registration, funding, and approvals are confirmed:

NODE_ENV=development anyflo-solver run

In another terminal, query the default private loopback interface:

curl --fail http://127.0.0.1:2102/health

Expect status: "healthy", checks.solver: "running", and checks.solverHub: "connected". These checks show process/Hub connectivity, not chain RPC readiness, sufficient inventory, or valid allowances. Keep the unauthenticated local operator API private. See monitoring and troubleshooting if startup or connectivity fails.

Custom implementation

Connect to the assigned WSS /connect endpoint with a fresh short-lived Solver JWT and maintain protocol heartbeats. Fetch GET /v1/orders/active on initial connection and reconnect; reconcile each returned OrderDetails.order with durable local state, and recover safely before resuming payouts. Implement acceptance deadlines, deposit verification/finality, and delivery reconciliation as described in the WebSocket contract. The reference application’s /health route is not a hosted SolverHub endpoint or a required custom-client interface.

Verify an order

Arrange a funded test order with Anyflo or an authorized customer application for your configured route. Do not use privileged administrator order-creation endpoints. Confirm the expected observable sequence:

  1. Receive NewOrder.payload.order (an Order) and submit a Bid before NewOrder.payload.biddingDeadline.
  2. Receive OrderAssigned if selected, validate its winnerId and order, and send OrderAssignAck within the acceptance window with the intended solverAddress and directDeposit. A bid does not guarantee selection.
  3. Observe OrderDeposit.payload.depositTx on OrderDeposit.payload.chain and verify the sender’s deposit, including the required finality; sending OrderDepositAck only acknowledges the notification.
  4. Execute the payout to Order.recipientAddr on Order.recipientChain and persist its transaction identity/hash so reconnects or restarts cannot duplicate payment.
  5. Observe OrderDelivery.payload.deliverTx on OrderDelivery.payload.chain, reconcile it with your recorded payout, and send OrderDeliveryAck. Follow the message and recovery contract.

For the reference application, inspect completed orders using the read-only local query:

curl --fail \
  -H 'Accept: application/json' \
  http://127.0.0.1:2102/v1/admin/orders/executed

An empty array before completing orders is normal. This endpoint returns Order[]; use Order.id to correlate records and Order.depositTx / Order.deliverTx to inspect the source and destination transactions. Consult the complete local operator API for active orders, bids, failures, and response details. Confirm the deposit on Order.senderChain against the deposit instructions, and the payout on Order.recipientChain against Order.recipientAddr, Order.tokenOut and Order.amountOut, including required finality. A local order record alone is not proof of payment. Investigate missing confirmation or reorgs rather than blindly resubmitting a transaction.

Production readiness

Before accepting production traffic, confirm:

  • Anyflo has activated your production identity, registered the intended authentication key, and provisioned the production Hub, routes, tokens, and deployed contracts.
  • Pricing reflects token base units and your operating costs; inventory, native gas, and delivery allowances cover expected payments.
  • Secrets are protected, clock synchronization is reliable, and authentication-key rotation and escalation have been rehearsed.
  • Durable state and payout idempotency survive restarts/upgrades; pending payouts, reorgs, finality changes, and reconnection catch-up have safe recovery procedures.
  • A supervisor and monitoring cover process/Hub availability and RPCs, inventory, allowances, and payout confirmation.

For the reference application, preserve the working directory, SQLite database, and WAL state, and switch to NODE_ENV=production only with matching production deployment settings. Follow running and persistence, monitoring and alerts, and the recovery runbook. Custom implementations need equivalent operational safeguards, not reference-only flags or environment variables.

Use the SolverHub key-rotation procedure to add a new key, verify the switch, and only then revoke the old key. Keep an Anyflo escalation contact available before production operation.