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.
156 lines
9.1 KiB
Markdown
156 lines
9.1 KiB
Markdown
# Implementation Turn: NEAR Intents request creation and EURe-to-BTC taker flow
|
|
|
|
Status: open
|
|
Opened: 2026-04-12
|
|
|
|
## 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.
|