Open NEAR Intents request creation turn
All checks were successful
deploy / deploy (push) Successful in 34s

Proof: Archive index, implementation proof, and implementation plan now define the approved NEAR Intents EURe-to-BTC request-creation turn with explicit lifecycle, settlement, and safety invariants.

Assumptions: The next turn is approved by the operator and will verify the NEAR Intents request API before any live fund movement; all live submission remains behind repo-owned preflight and explicit operator action.

Still fake: Request API shape is not yet verified, repo-owned request submission is not implemented, and no EURe-to-BTC live request has been created by this planning commit.
This commit is contained in:
philipp 2026-04-12 17:39:21 +02:00
parent 52505a4257
commit 55ece8f5f0
3 changed files with 286 additions and 6 deletions

View file

@ -30,3 +30,4 @@ Legacy note:
- 2026-04-08: opened implementation turn `quote-lifecycle-truth-and-execution-explanation` from backlog items I021. - 2026-04-08: opened implementation turn `quote-lifecycle-truth-and-execution-explanation` from backlog items I021.
- 2026-04-09: opened implementation turn `execution-outcome-truth-and-settled-attribution` from backlog items I017, I018. - 2026-04-09: opened implementation turn `execution-outcome-truth-and-settled-attribution` from backlog items I017, I018.
- 2026-04-10: opened implementation turn `settlement-aware-strategy-and-inventory-skew-controls` from backlog items I015. - 2026-04-10: opened implementation turn `settlement-aware-strategy-and-inventory-skew-controls` from backlog items I015.
- 2026-04-12: opened implementation turn `near-intents-request-creation-and-eure-to-btc-taker-flow` from backlog items I017.

View file

@ -1,5 +1,156 @@
# Implementation Turn # Implementation Turn: NEAR Intents request creation and EURe-to-BTC taker flow
Status: idle Status: open
Opened: 2026-04-12
No approved implementation turn is active yet. ## Goal
Build a repo-owned path to create our own NEAR Intents EURe-to-BTC swap request from credited internal inventory, submit it only behind explicit gates, and show truthful request-to-settlement evidence in the dashboard.
## Selected backlog items
- [I017] Repo-owned NEAR Intents request creation and EURe-to-BTC taker flow: create, sign, submit, and settle our own swap requests from credited inventory with truthful dashboard evidence. tags=intents,taker,execution,inventory,settlement
## Design rules
- Treat request creation as a new taker lifecycle, not as an incoming quote-response decision.
- Preflight must be safe and side-effect-free.
- Live submission must be explicit, idempotent, and durably recorded before the relay call.
- Use only spendable credited EURe.
- Keep all ids copyable: request id, idempotency key, intent hash or relay request id, submission id.
- Submitted or relay-accepted does not mean completed.
- Completed requires inventory delta attribution.
## Problem statement
The current system watches the NEAR Intents market and responds to other users' quotes. That is not enough to intentionally convert our EURe inventory to BTC. The operator wants a repo-owned way to create our own request on the intents market and eventually move EURe into BTC, with the same truth standard as the incoming quote lifecycle.
The existing code can sign verifier token_diff payloads for quote responses and can submit quote_response over the solver relay websocket. It does not yet know how to publish a taker request, quote request, or swap intent that asks the market to fill our EURe-to-BTC order.
## Backend changes
### 1. Verify request protocol
- Identify the supported NEAR Intents method for creating our own request using primary code/docs or live non-mutating behavior.
- Determine whether the method uses the existing solver relay websocket, a JSON-RPC HTTP endpoint, or a verifier contract call.
- Determine exact payload fields for EURe-to-BTC exact-in requests.
- Verify signed intent semantics: outgoing EURe, incoming BTC, deadline, nonce, verifier contract, signer.
- Record a hard blocker if the protocol cannot be verified.
### 2. Add request model and schemas
- Add a canonical repo-owned request lifecycle model.
- Add event schemas for at least intent_request_preflight, intent_request_submit_command, intent_request_submission_result, and intent_request_outcome.
- Persist request id, idempotency key, source/destination assets, requested spend, min receive, reference price, slippage, signer account, verifier contract, deadline, nonce, and created/submitted timestamps.
- Keep this model separate from incoming swap_demand, trade_decision, execute_trade, and trade_result events.
### 3. Build preflight service logic
- Load latest spendable EURe inventory from current inventory state or durable snapshot.
- Compute request amount from all spendable EURe minus an explicit reserve if configured, while allowing a smaller operator-specified amount for testing.
- Compute expected BTC from reference price.
- Compute minimum BTC receive from explicit slippage basis points.
- Reject if reference price is stale, inventory is stale, amount is zero, amount exceeds spendable EURe, or signer is not registered.
- Return a draft request object without signing or submitting.
### 4. Build signing/envelope helpers
- Add a helper for taker request signing/envelope construction once the verified protocol is known.
- Reuse buildIntentNonce only if nonce semantics match the request protocol.
- Add deterministic signer tests for the exact signed payload.
- Keep quote-response signing tests unchanged.
### 5. Build gated submit path
- Add a narrow request-executor or extend trade-executor only if responsibilities stay clear.
- Require explicit submit command with preflight id or idempotency key.
- Mark request as submit_requested before the relay/API call.
- Submit with timeout and reconnect-safe client behavior.
- Persist result as submitted, accepted_by_relay, failed, or protocol-specific status.
- Enforce idempotency so duplicate commands cannot submit twice.
### 6. Settlement attribution
- Extend outcome attribution to handle repo-created requests.
- Match settlement from inventory deltas: EURe decrease and BTC increase consistent with submitted request terms.
- Mark unresolved as awaiting_settlement before deadline/grace expires.
- Mark not_filled only after deadline/grace and fresh inventory evidence.
- Mark completed only with durable inventory movement evidence.
### 7. Dashboard and controls
- Add a Funds or Strategy panel for Create BTC request with preflight amount, slippage/minimum BTC receive, dry-run/preflight action, and live submit only after a valid preflight.
- Add a repo-created requests table with request id, created/submitted time, source spend, min receive, state, decisive reason, relay/API response, settlement result, and expandable lifecycle.
- Make request ids and returned intent/relay ids copyable.
- Label live fund movement clearly; no green success label without settlement.
## Data and persistence
- Prefer adding narrow tables or durable event routes for request preflight, submit commands, submission results, and outcomes.
- Preserve raw relay/API responses alongside normalized lifecycle state.
- Include enough fields to replay the request and reason about slippage, deadline, and settlement.
- Do not reuse incoming quote ids as request ids.
## Edge cases
- Missing request API evidence: stop with blocker.
- Signer not registered: block before signing/submission.
- EURe inventory stale or unavailable: block.
- Requested amount exceeds spendable EURe: block.
- Reference price stale: block.
- Slippage missing: block.
- Duplicate idempotency key: return original result, do not submit again.
- Relay timeout: failed or unknown state with durable reason, not completed.
- Relay accepted but no inventory movement: awaiting outcome, then not filled after evidence window.
- Partial fill, if supported: represent explicitly; otherwise block or mark ambiguous until semantics are known.
## Concrete implementation order
### Phase 1. Protocol verification and model
- Inspect primary NEAR Intents request API evidence and current repo clients.
- Decide endpoint/method and payload shape.
- Add request lifecycle constants and schemas.
- Add tests for semantic invariants independent of live API.
### Phase 2. Preflight path
- Implement pure preflight helper for EURe-to-BTC exact-in requests.
- Wire inventory, reference price, signer registration, amount, slippage, and deadline checks.
- Add tests for success, insufficient inventory, stale price, stale inventory, zero amount, and missing signer.
### Phase 3. Signing and submit client
- Implement taker request envelope/signing helper.
- Implement relay/API client method with timeout and error normalization.
- Add deterministic signing tests and mocked client submission tests.
### Phase 4. Durable execution path
- Add request submit command/result event routes and persistence.
- Add idempotency guard.
- Add submission failure and duplicate-submit tests.
### Phase 5. Outcome truth
- Extend request outcome attribution using inventory deltas.
- Add tests for submitted-not-completed, accepted-not-completed, completed with exact settlement, not-filled after deadline, and ambiguous movement.
### Phase 6. Operator UI
- Add preflight/submit controls and request lifecycle table.
- Add copy affordances for request and relay ids.
- Add dashboard tests proving no submitted-only request is labeled successful.
### Phase 7. Deploy and validate
- Run targeted tests plus full npm test.
- Build dashboard bundle.
- Commit with required proof body.
- Push to forgejo/main.
- Validate rollout image, service state, dashboard bootstrap, and live dry-run/preflight.
- If operator explicitly submits live, validate durable request row, submission result, and later settlement or no-fill.
## Test plan
- Request preflight unit tests.
- Request signing/envelope tests.
- Request client timeout/failure tests.
- Idempotency tests.
- Persistence routing tests.
- Outcome attribution tests.
- Dashboard semantic tests.
- Negative tests: submitted != completed; relay accepted != completed; pending EURe cannot be spent; dry-run cannot submit; duplicate submit does not call relay twice; request lifecycle cannot be confused with incoming quote response lifecycle.
## Validation checklist against the proof
- /state or dashboard shows request preflight capability and current spendable EURe.
- A dry-run EURe-to-BTC request can be produced without side effects.
- A live submit path exists only behind explicit operator action.
- Durable request lifecycle rows exist and are visible with copyable ids.
- Settlement outcome remains truthful after submission.
- All services deploy from repo push without manual cluster reconciliation.
## Known fakes allowed at start of this turn
- Request API method is not yet verified.
- Venue-native terminal fill events remain unavailable unless the request API exposes them.
- Fee-complete realized PnL remains unavailable.
- Automatic portfolio optimization remains unavailable.

134
PROOF.md
View file

@ -1,5 +1,133 @@
# Implementation Proof # Implementation Proof: NEAR Intents request creation and EURe-to-BTC taker flow
Status: idle Status: open
Opened: 2026-04-12
No approved implementation proof is active yet. ## Target outcome
The repository must be able to create our own NEAR Intents EURe-to-BTC swap request from credited internal inventory, submit it through repo-owned code, and explain the full request lifecycle from preflight through settlement truth.
For each repo-created request the operator must be able to answer:
- which asset and amount we intended to spend
- which asset and minimum amount we expected to receive
- which signer, verifier contract, nonce, deadline, slippage, and idempotency key were used
- whether the request was drafted, blocked, submitted, accepted by relay, failed, awaiting settlement, not filled, or completed
- whether completed means durable inventory movement, not relay acceptance
- how much BTC was received and how much EURe was spent, if settlement is proven
## Why this is the next architecture test
The existing system can observe incoming NEAR Intents quote requests and respond as a solver or maker. That path has not produced fills at 1.49%, 0.99%, or 0.49% in recent live validation, and it cannot intentionally convert our EURe inventory into BTC.
The next false path would be manually moving funds or adding a button that submits opaque live requests without durable preflight, request, and settlement evidence. This turn is successful only if the system can create requests as a first-class, auditable repo-owned flow instead of treating live fund movement as an off-system action.
## Scope
- [I017] Repo-owned NEAR Intents request creation and EURe-to-BTC taker flow: create, sign, submit, and settle our own swap requests from credited inventory with truthful dashboard evidence. tags=intents,taker,execution,inventory,settlement
- Active venue only: NEAR Intents.
- Active direction: credited internal EURe to BTC.
- Use credited spendable internal inventory only. Pending funding remains non-spendable.
- Build the request path with dry-run/preflight first, then gated live submission.
- Actual live submission requires explicit operator control and must be recorded durably.
## Assumptions
- NEAR Intents exposes a supported request or quote publication method through the solver relay or another documented endpoint callable with our existing API key and verifier signer.
- The correct taker intent can be represented as a signed verifier token_diff payload or a documented request envelope whose semantics can be proven before live submission.
- Internal inventory snapshots are fresh enough to enforce spendable EURe and settlement deltas.
- BTC minimum receive can be derived from reference price plus explicit slippage or minimum-out policy.
- The user's intent is to build the capability to move EURe into BTC; live all-EURe execution remains behind an explicit final operator action in the repo-owned UI or API.
## Turn-shaping rules
- Do not manually move funds.
- Do not submit an all-EURe live request until repo-owned preflight, durable request logging, and settlement attribution are implemented and the operator explicitly triggers that live request.
- Do not use pending or uncredited EURe.
- Do not label relay acceptance as completed settlement.
- Do not hide slippage, minimum receive, deadline, nonce, signer, or request id.
- If the NEAR Intents request API cannot be verified from primary evidence or live dry-run behavior, stop and record the blocker instead of inventing a protocol.
- Keep maker quote-response logic intact unless the new taker flow proves it should be paused or separated.
## Non-goals
- No new venue.
- No external wallet or manual bridge action.
- No automatic recurring rebalancer.
- No realized net PnL claim without fee and cost attribution.
- No tax or accounting treatment.
- No broad multi-asset request builder beyond EURe-to-BTC.
## Required operator behavior
### Request preflight truth
Before submission, the operator must see:
- spendable EURe available
- requested EURe spend amount
- BTC reference price
- slippage or minimum-out rule
- expected BTC receive and minimum BTC receive
- deadline and nonce policy
- exact signer account and verifier contract
- whether this is dry-run only or live-submit capable
### Request lifecycle truth
For each repo-created request, the dashboard must show:
- request id, copyable
- idempotency key, copyable
- intent hash or relay request id if returned, copyable
- created_at, submitted_at, resolved_at if known
- state: draft, blocked, submitted, accepted_by_relay, failed, awaiting_settlement, not_filled, completed
- decisive reason for blocks, failures, or no-fill
- settlement evidence if completed
### Settlement truth
Completed requires durable asset movement evidence:
- EURe spend delta and BTC receive delta from inventory snapshots
- attribution method and caveat if heuristic
- submitted-only and relay-accepted rows remain separate from completed
- portfolio-vs-hold movement remains separate from realized trade PnL
## Semantic invariants
The implementation and tests must enforce at least:
- request submitted != completed
- relay accepted != settled inventory movement
- pending EURe cannot be spent
- insufficient spendable EURe blocks before signing or submission
- slippage and minimum-out must be explicit and persisted
- duplicate idempotency key cannot produce duplicate live submissions
- dry-run request cannot accidentally submit
- completed request rows require durable settlement evidence
- request-creation flow is distinct from incoming quote-response flow
## Definition of done
- The repo contains a verified NEAR Intents request-creation client or a recorded blocker proving the venue path is unavailable.
- A request preflight API computes amount, min-out, deadline, nonce policy, signer, verifier, and inventory checks from durable/current data.
- A gated live submission API exists only after preflight and records durable request, submission, and result events.
- The dashboard shows repo-created request rows separately from incoming quote-response rows, with copyable ids and lifecycle reasons.
- Settlement attribution handles repo-created requests without treating relay acceptance as completion.
- Regression tests cover request signing/envelope semantics, inventory blocks, dry-run safety, idempotency, submission failure, submitted-not-completed, and completed-only-with-settlement.
- The result is deployed through the repo workflow and validated against live service state.
## Validation evidence required
- Unit tests for request preflight and minimum-out/slippage math.
- Unit tests for signed request or request envelope construction using deterministic signer fixtures.
- Unit tests proving insufficient EURe blocks before signing/submission.
- Unit tests proving submitted/accepted requests do not count as completed without inventory deltas.
- Live dry-run/preflight evidence for current credited EURe inventory.
- If live submission is explicitly triggered, durable DB evidence for request, submission result, and later settlement or no-fill.
- Dashboard bootstrap evidence showing the new request lifecycle row with copyable ids and truthful state.
## Failure conditions
- Live funds are moved outside repo-owned code.
- A request is submitted without durable preflight and request records.
- The UI claims BTC was bought from relay acceptance alone.
- A dry-run path can submit.
- Pending funding is treated as spendable.
- The implementation cannot prove the NEAR Intents request API shape and still proceeds.
## Current real before this turn
- The repo has verifier signing for quote-response token_diff payloads.
- The repo has a solver relay websocket client and quote-response submission path.
- Credited internal BTC/EURe inventory is synced durably.
- Quote, decision, command, submission result, and outcome attribution records exist for incoming quote-response flow.
- The dashboard distinguishes submitted, not-filled, completed, rejected, and blocked rows for incoming quote responses.
## Deliberately not built by this proof
- General portfolio optimizer.
- Automatic all-in rebalancing loop.
- Fee-complete realized PnL.
- Venue-native terminal fill ingestion unless the request API provides it directly.