Proof: Preserve the completed first live BTC/EURe trade loop and establish the next approved implementation proof around pre-credit funding visibility and operator alerts. Assumptions: The live-trade loop is sufficiently proven by the recorded deposits, withdrawals, durable command/result chain, and successful mainnet quote responses; the next highest-value slice is operational visibility rather than new execution breadth. Still fake: The newly opened funding-visibility and alert turn is planning only; no pre-credit watcher or durable alert evaluator is implemented yet.
356 lines
13 KiB
Markdown
356 lines
13 KiB
Markdown
# Implementation Proof: first non-mocked tradeable loop for one pair
|
|
|
|
Status: open
|
|
Opened: 2026-04-01
|
|
|
|
## Target outcome
|
|
The active turn is not complete when the repo merely observes demand or emits placeholder commands. It is complete only when the deployed system can make a real Near Intents trade attempt for the active BTC/Gnosis EURe pair using pre-funded inventory already credited inside NEAR Intents, with the full chain stored durably for later analytics and backtesting.
|
|
|
|
## Hypothesis
|
|
`unrip` becomes materially more real once one live NEAR swap-demand event can move through this full chain without mocks:
|
|
|
|
1. real quote and demand ingestion
|
|
2. live external reference pricing
|
|
3. synchronized spendable inventory state from NEAR Intents
|
|
4. auditable strategy decision
|
|
5. inventory and safety gating
|
|
6. real Near Intents execution attempt using credited internal inventory
|
|
7. durable storage of the full event chain
|
|
|
|
If any of those links is still dummy, manual-only, or opaque after the fact, the proof is not achieved.
|
|
|
|
## Active pair and trading rule
|
|
- Active pair:
|
|
- `nep141:btc.omft.near`
|
|
- `nep141:gnosis-0x420ca0f9b9b604ce0fd9c18ef134c705e5fa3430.omft.near`
|
|
- Both directions must be implemented in the same decision and execution pipeline:
|
|
- BTC -> EURe
|
|
- EURe -> BTC
|
|
- Runtime spendable inventory inside NEAR Intents decides which direction can actually fire.
|
|
- External Gnosis and BTC wallets are treasury and funding inputs, not the per-trade spend path.
|
|
- Pending deposits or withdrawals must not be treated as spendable inventory.
|
|
- Initial decision rule:
|
|
- use Kraken plus CoinGecko reference prices
|
|
- make the EURe/EUR pricing assumption explicit in code and decision records
|
|
- require a gross edge of at least 2%
|
|
- require fresh reference pricing
|
|
- require fresh internal inventory state
|
|
- require sufficient spendable source-asset inventory already credited inside NEAR Intents
|
|
- keep strategy and executor disarmed by default on deploy
|
|
- start with a very small max notional for the first live attempt
|
|
|
|
## Required services
|
|
|
|
### `near-intents-ingest`
|
|
Responsibilities:
|
|
- connect to the live NEAR Intents quote feed
|
|
- maintain the active pair filter
|
|
- publish raw venue quotes
|
|
- publish normalized swap-demand events
|
|
- expose current ingest state
|
|
|
|
Must not:
|
|
- make trading decisions
|
|
- execute trades
|
|
|
|
### `market-reference-ingest`
|
|
Responsibilities:
|
|
- maintain current reference pricing for BTC/EUR and mapped BTC/EURe fair value
|
|
- use Kraken as the primary fast path
|
|
- use CoinGecko as fallback or cross-check
|
|
- publish reference-price events
|
|
- expose latest price state, freshness, and source health
|
|
|
|
Must not:
|
|
- emit trade commands
|
|
|
|
### `inventory-sync`
|
|
Responsibilities:
|
|
- read current spendable inventory from the NEAR Intents internal ledger or equivalent supported inventory surface
|
|
- distinguish credited inventory from pending deposits and withdrawals
|
|
- publish or serve current internal inventory state
|
|
- expose freshness, last successful sync time, and reconciliation status
|
|
|
|
Must not:
|
|
- initiate treasury movements
|
|
- make trading decisions
|
|
|
|
### `liquidity-manager`
|
|
Responsibilities:
|
|
- request or manage deposit addresses for supported treasury assets and chains
|
|
- track funding actions from external treasury wallets into NEAR Intents
|
|
- track pending deposits, credited deposits, withdrawals, and rebalance actions
|
|
- expose the current funding and treasury state
|
|
- publish or record liquidity actions so they are auditable
|
|
|
|
Must not:
|
|
- execute trading strategy
|
|
- spend inventory on the trade hot path
|
|
|
|
### `history-writer`
|
|
Responsibilities:
|
|
- consume the core Kafka topics
|
|
- write append-only records into PostgreSQL
|
|
- preserve enough IDs and timestamps to reconstruct causality
|
|
- expose writer lag, last committed offsets, and write health
|
|
|
|
Must not:
|
|
- serve as the message bus
|
|
- make trading decisions
|
|
|
|
### `strategy-engine`
|
|
Responsibilities:
|
|
- consume normalized demand plus fresh reference prices
|
|
- consume fresh spendable inventory state
|
|
- compute implied rate from the quote
|
|
- compare quote rate against external reference pricing
|
|
- apply the initial 2% gross edge threshold
|
|
- apply freshness, arming, and notional checks
|
|
- apply inventory-aware direction gating
|
|
- emit auditable decision events
|
|
- emit `cmd.execute_trade` only when a decision is actionable
|
|
|
|
Must not:
|
|
- hold private keys
|
|
- execute venue actions directly
|
|
|
|
### `trade-executor`
|
|
Responsibilities:
|
|
- consume `cmd.execute_trade`
|
|
- load the correct Near Intents signing authority at runtime
|
|
- perform the actual Near Intents submission against pre-funded internal inventory
|
|
- preserve idempotency and duplicate suppression
|
|
- publish `exec.trade_result`
|
|
- expose current arm state, recent attempts, and last venue error
|
|
|
|
Must not:
|
|
- invent trading logic
|
|
- bypass Kafka and manual safety gates
|
|
- perform ad hoc bridging or treasury funding on the trade hot path
|
|
|
|
## Required durable storage
|
|
PostgreSQL is the first durable analytics and audit store.
|
|
|
|
It must store at least:
|
|
- raw quotes
|
|
- normalized demand
|
|
- reference-price snapshots
|
|
- internal inventory snapshots
|
|
- liquidity and funding actions
|
|
- strategy decisions
|
|
- trade commands
|
|
- execution results
|
|
- treasury status and reconciliation metadata
|
|
|
|
Why PostgreSQL first:
|
|
- fast enough for the current streaming volume
|
|
- queryable for inspection and analytics
|
|
- simple to operate in the current cluster
|
|
- good fit for append-only audit plus current-state views
|
|
|
|
Kafka remains the streaming backbone. PostgreSQL is not the hot transport path.
|
|
|
|
## Required control surface
|
|
Every long-running service in this turn must expose a small HTTP control surface. The point is not a polished UI. The point is operability.
|
|
|
|
At minimum every service must expose:
|
|
- `GET /healthz`
|
|
- `GET /state`
|
|
|
|
Services with runtime controls must also expose the relevant action endpoints:
|
|
|
|
### `near-intents-ingest`
|
|
- inspect:
|
|
- pair filter
|
|
- connection state
|
|
- frames received
|
|
- published counts
|
|
- control:
|
|
- update pair filter
|
|
- disable or reset pair filter
|
|
|
|
### `market-reference-ingest`
|
|
- inspect:
|
|
- latest Kraken price
|
|
- latest CoinGecko price
|
|
- derived fair price
|
|
- freshness age
|
|
- source health
|
|
- control:
|
|
- pause or resume polling or streaming
|
|
- trigger ad hoc refresh
|
|
|
|
### `inventory-sync`
|
|
- inspect:
|
|
- latest spendable balances by asset
|
|
- pending deposits and withdrawals
|
|
- last sync time
|
|
- reconciliation status
|
|
- control:
|
|
- trigger sync
|
|
- pause or resume sync
|
|
|
|
### `liquidity-manager`
|
|
- inspect:
|
|
- active deposit addresses
|
|
- recent funding actions
|
|
- pending deposits
|
|
- credited deposits
|
|
- recent withdrawals
|
|
- control:
|
|
- request or rotate deposit address where supported
|
|
- refresh treasury status
|
|
- pause or resume funding trackers
|
|
- disable withdrawals or rebalance actions
|
|
|
|
### `history-writer`
|
|
- inspect:
|
|
- last persisted offsets by topic
|
|
- last write time
|
|
- error count
|
|
- database connectivity
|
|
- control:
|
|
- pause writes
|
|
- resume writes
|
|
- drain and stop cleanly
|
|
|
|
### `strategy-engine`
|
|
- inspect:
|
|
- arm state
|
|
- active threshold
|
|
- latest reference snapshot used
|
|
- latest inventory snapshot used
|
|
- latest decisions and reasons
|
|
- skipped counts by reason
|
|
- control:
|
|
- arm or disarm
|
|
- pause or resume decisions
|
|
- change threshold
|
|
- set notional cap
|
|
|
|
### `trade-executor`
|
|
- inspect:
|
|
- arm state
|
|
- last command received
|
|
- last venue response
|
|
- last error
|
|
- in-flight and completed command counts
|
|
- control:
|
|
- arm or disarm execution
|
|
- pause consumption
|
|
- drain and stop cleanly
|
|
|
|
Stopping a service must mean a graceful stop or drain, not “kill the pod and hope.”
|
|
|
|
## Logging and observability requirements
|
|
All services must emit structured JSON logs with stable fields.
|
|
|
|
Stable fields:
|
|
- `level`
|
|
- `service`
|
|
- `component`
|
|
- `event`
|
|
- `namespace`
|
|
- `venue`
|
|
- `topic`
|
|
- `pair`
|
|
|
|
High-cardinality IDs belong in the body, not labels:
|
|
- `quote_id`
|
|
- `command_id`
|
|
- `decision_id`
|
|
- `execution_id`
|
|
|
|
What must be logged:
|
|
- connection loss and recovery
|
|
- source stale state
|
|
- inventory-sync stale state
|
|
- treasury funding action requested, credited, failed, or stuck
|
|
- invalid messages
|
|
- decision accepted and decision rejected with reason
|
|
- arm and disarm actions
|
|
- execution submitted, rejected, failed, recovered, completed
|
|
- PostgreSQL disconnect and recovery
|
|
- control API failures
|
|
|
|
What should not be logged:
|
|
- per-message noise without state change
|
|
- full payload spam by default
|
|
|
|
## Required edge cases and failure handling
|
|
- stale reference prices must block decisions
|
|
- stale or missing internal inventory state must block execution
|
|
- insufficient credited inventory must block the affected direction only
|
|
- pending deposits must not be counted as spendable inventory
|
|
- deposit address created but never funded must not be mistaken for liquidity
|
|
- external transfer observed but not yet credited in NEAR Intents must stay non-spendable
|
|
- credited inventory drift between inventory-sync and executor must hard-fail the command and publish a result
|
|
- Kraken down but CoinGecko healthy should degrade, not crash, if policy allows fallback
|
|
- both reference sources stale must block decisions
|
|
- PostgreSQL down must surface a hard health failure and stop claiming the system is trade-ready
|
|
- liquidity-manager failure must block new funding operations but must not silently stop already funded trading
|
|
- duplicate `cmd.execute_trade` must not cause duplicate venue submission
|
|
- executor restart after a partial submission must preserve idempotency behavior
|
|
- Near Intents API or RPC failures must become explicit `trade_result` failure records
|
|
- pair inactivity must not be mistaken for pipeline breakage
|
|
|
|
## Definition of done
|
|
- The deployed cluster is running all required services for this loop.
|
|
- Live Kraken and CoinGecko reference prices are flowing and inspectable.
|
|
- Spendable inventory inside NEAR Intents is flowing and inspectable.
|
|
- At least one treasury funding path is documented and verified:
|
|
- deposit address or supported funding path created
|
|
- funding action observed
|
|
- credited inventory visible in internal state
|
|
- PostgreSQL contains the full event chain for at least one real quote path.
|
|
- Strategy decisions are non-dummy and include explicit reason fields with edge, freshness, and inventory context.
|
|
- Both trade directions are implemented in the same decision and execution path.
|
|
- At least one direction can be armed based on available credited inventory.
|
|
- A real Near Intents execution attempt can be triggered through the repo-controlled path.
|
|
- The resulting venue response is captured durably and inspectably.
|
|
- Each service exposes the required health and state endpoints, and controlled pause or arm semantics where appropriate.
|
|
- Fresh deploys start disarmed by default and require explicit operator arming before side effects.
|
|
- Validation includes not only happy path but blocked-path evidence:
|
|
- stale reference blocked
|
|
- insufficient inventory blocked
|
|
- pending-deposit-not-spendable blocked
|
|
- disarmed executor blocked
|
|
|
|
## Current real
|
|
- Real NEAR Intents quote data is flowing into the cluster.
|
|
- The pair filter can be configured and changed at runtime.
|
|
- Raw and normalized events already exist in Redpanda topics.
|
|
- The app is deployable and observable in Kubernetes.
|
|
- Kafka already provides the event backbone.
|
|
|
|
## Current fake or incomplete
|
|
- Reference pricing does not exist yet.
|
|
- Spendable internal inventory sync does not exist yet.
|
|
- Treasury funding or deposit management does not exist yet.
|
|
- Strategy decisions are still dummy placeholders.
|
|
- Execution is still dummy.
|
|
- The current executor is not a real Near Intents adapter.
|
|
- PostgreSQL is not yet part of the loop.
|
|
- Most services do not yet have their own control surfaces.
|
|
- Real signing and treasury secret handling is not yet wired.
|
|
|
|
## Failure conditions
|
|
This proof fails if any of the following is true:
|
|
- a trade can only happen via manual shell steps or out-of-band operator intervention
|
|
- the system depends on ad hoc bridging or external-wallet spending on the trade hot path
|
|
- decision logic is still embedded in a dummy or placeholder service
|
|
- executor logic is still simulated
|
|
- a service cannot be inspected or paused cleanly at runtime
|
|
- the system cannot explain why a quote did or did not become a trade
|
|
- the stored history cannot reconstruct quote, pricing, decision, command, and result
|
|
- both directions are not implemented
|
|
- the system attempts to execute without credited internal source inventory
|
|
|
|
## Expected validation evidence
|
|
- live `ref.market_price` events and current state from the pricing control API
|
|
- live internal inventory state from the inventory-sync control API
|
|
- PostgreSQL rows linking quote, reference, inventory snapshot, decision, command, and execution result
|
|
- a blocked decision caused by stale price or insufficient inventory
|
|
- a funding action that becomes credited inventory
|
|
- a successful command emission from the strategy service with a recorded edge above 2%
|
|
- one real Near Intents execution attempt with stored request and response metadata
|