unrip/test/intent-request-outcomes.test.mjs
philipp 430c8b3521
All checks were successful
deploy / deploy (push) Successful in 32s
Prevent own request self-matching
Proof: Live dashboard-triggered request settled at the relay without the expected EURe decrease and BTC increase, exposing self-matching between our taker preflight and our maker responder. This change suppresses maker quote responses while an own-request preflight is collecting solver quotes, refreshes relay status before outcome derivation, and records relay SETTLED without expected durable inventory delta as failed rather than completed or not_filled.

Assumptions: Suppressing maker responses during the short quote RPC window prevents our own quote from being selected for our own taker request. Relay SETTLED remains insufficient for success unless durable inventory shows the expected source decrease and destination increase.

Still fake: Venue-native fill id parsing and fee-complete realized PnL for request-created trades are still not modeled; completed still depends on durable inventory delta attribution.
2026-04-12 19:02:21 +02:00

181 lines
5.5 KiB
JavaScript

import test from 'node:test';
import assert from 'node:assert/strict';
import { deriveIntentRequestOutcomeRecords } from '../src/core/intent-request-outcomes.mjs';
const BTC = {
assetId: 'nep141:btc.omft.near',
symbol: 'BTC',
decimals: 8,
};
const EURE = {
assetId: 'nep141:eure.omft.near',
symbol: 'EURe',
decimals: 18,
};
function preflight(overrides = {}) {
return {
request_id: 'request-1',
idempotency_key: 'idem-1',
state: 'draft',
reason_code: 'quote_available',
source_asset_id: EURE.assetId,
destination_asset_id: BTC.assetId,
source_amount_units: '5000000000000000000',
min_destination_amount_units: '9800',
quoted_destination_amount_units: '10000',
selected_quote: {
quote_hash: 'quote-hash-1',
amount_out: '10000',
},
min_deadline_ms: 60000,
deadline_at: '2026-04-12T10:01:00.000Z',
created_at: '2026-04-12T10:00:00.000Z',
...overrides,
};
}
function submission(overrides = {}) {
return {
request_id: 'request-1',
idempotency_key: 'idem-1',
submission_id: 'submission-1',
status: 'accepted_by_relay',
result_code: 'publish_intent_accepted',
quote_hash: 'quote-hash-1',
intent_hash: 'intent-hash-1',
destination_amount_units: '10000',
submitted_at: '2026-04-12T10:00:10.000Z',
relay_status: 'PENDING',
...overrides,
};
}
function outcomes({ preflights = [preflight()], submissions = [], inventorySnapshots = [], now = '2026-04-12T10:00:30.000Z' } = {}) {
return deriveIntentRequestOutcomeRecords({
preflights,
submissions,
inventorySnapshots,
btcAsset: BTC,
eureAsset: EURE,
now: Date.parse(now),
});
}
test('relay settled without expected inventory delta is failed, not completed', () => {
const [record] = outcomes({
submissions: [submission({ relay_status: 'SETTLED' })],
inventorySnapshots: [
{
observed_at: '2026-04-12T10:00:00.000Z',
spendable: {
[EURE.assetId]: '5000000000000000000',
[BTC.assetId]: '0',
},
},
{
observed_at: '2026-04-12T10:00:20.000Z',
spendable: {
[EURE.assetId]: '5000000000000000000',
[BTC.assetId]: '0',
},
},
],
});
assert.equal(record.submission_status, 'accepted_by_relay');
assert.equal(record.relay_status, 'SETTLED');
assert.equal(record.outcome_status, 'failed');
assert.equal(record.outcome_reason, 'relay_settled_without_expected_inventory_delta');
assert.equal(record.attribution_status, 'unattributed');
assert.equal(record.attributed_inventory_delta, null);
assert.notEqual(record.outcome_status, 'completed');
assert.notEqual(record.outcome_status, 'not_filled');
});
test('accepted pending request without inventory delta remains awaiting settlement', () => {
const [record] = outcomes({
submissions: [submission({ relay_status: 'PENDING' })],
inventorySnapshots: [
{
observed_at: '2026-04-12T10:00:20.000Z',
spendable: {
[EURE.assetId]: '5000000000000000000',
[BTC.assetId]: '0',
},
},
],
});
assert.equal(record.outcome_status, 'awaiting_settlement');
assert.equal(record.outcome_reason, 'accepted_by_relay_without_settlement');
assert.equal(record.attributed_inventory_delta, null);
});
test('completed request requires exact EURe decrease and BTC increase after submission', () => {
const [record] = outcomes({
submissions: [submission()],
inventorySnapshots: [
{
inventory_id: 'inventory-before',
observed_at: '2026-04-12T10:00:00.000Z',
spendable: {
[EURE.assetId]: '5000000000000000000',
[BTC.assetId]: '0',
},
},
{
inventory_id: 'inventory-after',
observed_at: '2026-04-12T10:00:15.000Z',
spendable: {
[EURE.assetId]: '0',
[BTC.assetId]: '10000',
},
},
],
});
assert.equal(record.outcome_status, 'completed');
assert.equal(record.outcome_source, 'intent_inventory_spendable_delta');
assert.equal(record.outcome_reason, 'matched_inventory_delta');
assert.equal(record.attribution_status, 'heuristic_match');
assert.equal(record.attributed_inventory_delta.inventory_id, 'inventory-after');
assert.deepEqual(record.attributed_inventory_delta.delta_units, {
[BTC.assetId]: '10000',
[EURE.assetId]: '-5000000000000000000',
});
});
test('accepted request becomes not filled only after deadline grace and fresh inventory evidence', () => {
const [record] = outcomes({
submissions: [submission()],
inventorySnapshots: [
{
observed_at: '2026-04-12T10:02:01.000Z',
spendable: {
[EURE.assetId]: '5000000000000000000',
[BTC.assetId]: '0',
},
},
],
now: '2026-04-12T10:02:01.000Z',
});
assert.equal(record.outcome_status, 'not_filled');
assert.equal(record.outcome_reason, 'deadline_elapsed_without_settlement');
assert.equal(record.attribution_status, 'unattributed');
assert.equal(record.attributed_inventory_delta, null);
});
test('blocked preflight remains blocked and is distinct from request rejection or completion', () => {
const [record] = outcomes({
preflights: [preflight({ state: 'blocked', reason_code: 'insufficient_spendable_eure' })],
});
assert.equal(record.outcome_status, 'blocked');
assert.equal(record.outcome_reason, 'insufficient_spendable_eure');
assert.equal(record.submission_status, null);
assert.notEqual(record.outcome_status, 'completed');
assert.notEqual(record.outcome_status, 'rejected');
});