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
solverIdand the process for registering your first public authentication key with its positive integerkid. - The environment’s SolverHub HTTP origin and full WSS URL, including
/connect. The HTTP origin has neither a/v1nor a/connectsuffix. - Supported source/destination routes:
Order.senderChain,Order.recipientChain,Order.tokenInandOrder.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_VERSIONconfirmed 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/solverand 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.
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 value | Required replacement or confirmation |
|---|---|
123 | Your assigned solver ID, matching the registered public key. |
wss://solverhub.example.com/connect | The full WSS URL assigned for your test environment. |
eip155:84532 | Confirm Base Sepolia is provisioned for your test route; use matching deployment, RPC, token, and wallet settings. |
https://base-sepolia-rpc.example.com | Your reachable Base Sepolia RPC endpoint. |
0x1111…1111 | The environment’s deployed source deposit account contract address (evmChains[].depositAccountAddress). |
0x2222…2222 | The environment’s deployed destination delivery account contract address (evmChains[].deliveryAccountAddress), not the signing wallet or payout recipient. |
0x3333…3333 | Your source-chain receiving address (evmChains[].solverAddress), submitted as OrderAssignAck.payload.solverAddress and recorded as Order.solverAddress; not a supplied contract address. |
0x4444…4444 | A supported token contract address (evmChains[].supportedTokens[]) confirmed for this deployment. Add only configured tokens. |
directDeposit: false | Confirm 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 toOrder.solverAddress. - Indirect EVM receipts (
false): the source deposit contract creditssolverBalancesforOrder.solverAddressandOrder.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:
- Receive
NewOrder.payload.order(anOrder) and submit aBidbeforeNewOrder.payload.biddingDeadline. - Receive
OrderAssignedif selected, validate itswinnerIdandorder, and sendOrderAssignAckwithin the acceptance window with the intendedsolverAddressanddirectDeposit. A bid does not guarantee selection. - Observe
OrderDeposit.payload.depositTxonOrderDeposit.payload.chainand verify the sender’s deposit, including the required finality; sendingOrderDepositAckonly acknowledges the notification. - Execute the payout to
Order.recipientAddronOrder.recipientChainand persist its transaction identity/hash so reconnects or restarts cannot duplicate payment. - Observe
OrderDelivery.payload.deliverTxonOrderDelivery.payload.chain, reconcile it with your recorded payout, and sendOrderDeliveryAck. 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.
