Fix intent request terminal reason text
All checks were successful
deploy / deploy (push) Successful in 32s
All checks were successful
deploy / deploy (push) Successful in 32s
Proof: Live request validation showed a not_filled own-request row still displayed the earlier relay-accepted text; the normalizer now prefers terminal outcome reason text and has a regression test for deadline_elapsed_without_settlement. Assumptions: Terminal request outcome rows are more decisive than submission result text for operator-facing reason copy. Still fake: Venue-native fill ids and fee-complete realized PnL remain unavailable; completed still depends on durable inventory delta attribution.
This commit is contained in:
parent
f34f27065a
commit
1a7bb89f36
2 changed files with 91 additions and 2 deletions
|
|
@ -1211,7 +1211,7 @@ function normalizeEventPayloadRow(row) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function normalizeIntentRequestRow(row) {
|
export function normalizeIntentRequestRow(row) {
|
||||||
const preflight = row.preflight_payload || {};
|
const preflight = row.preflight_payload || {};
|
||||||
const submission = row.submission_payload || null;
|
const submission = row.submission_payload || null;
|
||||||
const outcome = row.outcome_payload || null;
|
const outcome = row.outcome_payload || null;
|
||||||
|
|
@ -1223,7 +1223,9 @@ function normalizeIntentRequestRow(row) {
|
||||||
|| submission?.result_code
|
|| submission?.result_code
|
||||||
|| preflight.reason_code
|
|| preflight.reason_code
|
||||||
|| 'reason_unknown';
|
|| 'reason_unknown';
|
||||||
const reasonText = submission?.result_text
|
const reasonText = outcome?.reason_text
|
||||||
|
|| (outcome?.outcome_reason ? humanizeIntentRequestReason(outcome.outcome_reason) : null)
|
||||||
|
|| submission?.result_text
|
||||||
|| preflight.reason_text
|
|| preflight.reason_text
|
||||||
|| reasonCode.replaceAll('_', ' ');
|
|| reasonCode.replaceAll('_', ' ');
|
||||||
|
|
||||||
|
|
@ -1287,6 +1289,25 @@ function normalizeIntentRequestRow(row) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function humanizeIntentRequestReason(reason) {
|
||||||
|
const normalized = String(reason || '').trim();
|
||||||
|
const labels = {
|
||||||
|
accepted_by_relay_without_settlement:
|
||||||
|
'Relay accepted the signed request; waiting for durable EURe decrease and BTC increase evidence.',
|
||||||
|
relay_settled_but_inventory_delta_missing:
|
||||||
|
'Relay reported settlement, but no matching durable inventory movement is linked yet.',
|
||||||
|
deadline_elapsed_without_settlement:
|
||||||
|
'Deadline and grace window elapsed without matching EURe decrease and BTC increase evidence.',
|
||||||
|
matched_inventory_delta:
|
||||||
|
'Matched durable EURe decrease and BTC increase evidence.',
|
||||||
|
ambiguous_inventory_delta_match:
|
||||||
|
'More than one inventory movement could match this request; no completion is assigned.',
|
||||||
|
relay_not_found_or_not_valid:
|
||||||
|
'Relay reported the intent as not found or not valid.',
|
||||||
|
};
|
||||||
|
return labels[normalized] || normalized.replaceAll('_', ' ');
|
||||||
|
}
|
||||||
|
|
||||||
function mapSubmissionStatusToRequestState(status) {
|
function mapSubmissionStatusToRequestState(status) {
|
||||||
if (status === 'accepted_by_relay') return 'awaiting_settlement';
|
if (status === 'accepted_by_relay') return 'awaiting_settlement';
|
||||||
if (status === 'submit_requested') return 'submitted';
|
if (status === 'submit_requested') return 'submitted';
|
||||||
|
|
|
||||||
68
test/postgres-intent-requests.test.mjs
Normal file
68
test/postgres-intent-requests.test.mjs
Normal file
|
|
@ -0,0 +1,68 @@
|
||||||
|
import test from 'node:test';
|
||||||
|
import assert from 'node:assert/strict';
|
||||||
|
|
||||||
|
import { normalizeIntentRequestRow } from '../src/lib/postgres.mjs';
|
||||||
|
|
||||||
|
test('intent request normalization prefers terminal outcome reason text over relay acceptance text', () => {
|
||||||
|
const row = normalizeIntentRequestRow({
|
||||||
|
preflight_observed_at: '2026-04-12T16:45:30.000Z',
|
||||||
|
preflight_ingested_at: '2026-04-12T16:45:30.000Z',
|
||||||
|
preflight_payload: {
|
||||||
|
request_id: 'request-1',
|
||||||
|
idempotency_key: 'intent-request:request-1',
|
||||||
|
state: 'draft',
|
||||||
|
reason_code: 'quote_available',
|
||||||
|
reason_text: 'Solver quote meets the explicit slippage/minimum receive policy.',
|
||||||
|
source_asset_id: 'nep141:eure.omft.near',
|
||||||
|
source_symbol: 'EURe',
|
||||||
|
source_decimals: 18,
|
||||||
|
destination_asset_id: 'nep141:btc.omft.near',
|
||||||
|
destination_symbol: 'BTC',
|
||||||
|
destination_decimals: 8,
|
||||||
|
source_amount_units: '5000000000000000000',
|
||||||
|
min_destination_amount_units: '8090',
|
||||||
|
selected_quote: { quote_hash: 'quote-hash-1', amount_out: '8214' },
|
||||||
|
created_at: '2026-04-12T16:45:30.000Z',
|
||||||
|
deadline_at: '2026-04-12T16:46:28.790Z',
|
||||||
|
},
|
||||||
|
submission_observed_at: '2026-04-12T16:45:43.133Z',
|
||||||
|
submission_ingested_at: '2026-04-12T16:45:43.133Z',
|
||||||
|
submission_payload: {
|
||||||
|
request_id: 'request-1',
|
||||||
|
idempotency_key: 'intent-request:request-1',
|
||||||
|
submission_id: 'submission-1',
|
||||||
|
status: 'accepted_by_relay',
|
||||||
|
result_code: 'publish_intent_accepted',
|
||||||
|
result_text: 'Relay accepted the signed request. This is not settlement.',
|
||||||
|
submitted_at: '2026-04-12T16:45:43.133Z',
|
||||||
|
intent_hash: 'intent-hash-1',
|
||||||
|
quote_hash: 'quote-hash-1',
|
||||||
|
relay_status: 'PENDING',
|
||||||
|
destination_amount_units: '8214',
|
||||||
|
},
|
||||||
|
outcome_observed_at: '2026-04-12T16:47:32.958Z',
|
||||||
|
outcome_payload: {
|
||||||
|
request_id: 'request-1',
|
||||||
|
idempotency_key: 'intent-request:request-1',
|
||||||
|
submission_id: 'submission-1',
|
||||||
|
intent_hash: 'intent-hash-1',
|
||||||
|
submission_status: 'accepted_by_relay',
|
||||||
|
relay_status: 'PENDING',
|
||||||
|
submitted_at: '2026-04-12T16:45:43.133Z',
|
||||||
|
outcome_status: 'not_filled',
|
||||||
|
outcome_observed_at: '2026-04-12T16:47:32.958Z',
|
||||||
|
outcome_source: 'request_deadline_and_inventory_snapshots',
|
||||||
|
outcome_reason: 'deadline_elapsed_without_settlement',
|
||||||
|
attribution_status: 'unattributed',
|
||||||
|
attribution_method: null,
|
||||||
|
attributed_inventory_delta: null,
|
||||||
|
evidence: {},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(row.state, 'not_filled');
|
||||||
|
assert.equal(row.reason_code, 'deadline_elapsed_without_settlement');
|
||||||
|
assert.match(row.reason_text, /Deadline and grace window elapsed/i);
|
||||||
|
assert.doesNotMatch(row.reason_text, /Relay accepted the signed request/i);
|
||||||
|
assert.equal(row.has_settlement_evidence, false);
|
||||||
|
});
|
||||||
Loading…
Add table
Reference in a new issue