Some checks failed
deploy / deploy (push) Failing after 1m35s
Proof: first non-mocked tradeable loop for one pair using funded NEAR Intents inventory, Kafka, and PostgreSQL. Assumptions: solver-side execution is performed by signed token_diff quote responses over the Solver Relay; EURe is treated as 1:1 with EUR; k3s runtime uses unrip-dev.near as the named signer account. Still fake: signer key is not yet registered on intents.near, strategy and executor remain disarmed by default, and no live mainnet quote response has been submitted from this repo yet.
153 lines
4.2 KiB
JavaScript
153 lines
4.2 KiB
JavaScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
|
|
import { evaluateTradeOpportunity } from '../src/core/strategy.mjs';
|
|
|
|
function makeConfig() {
|
|
const tradingBtc = {
|
|
assetId: 'nep141:btc.omft.near',
|
|
symbol: 'BTC',
|
|
decimals: 8,
|
|
chain: 'btc:mainnet',
|
|
};
|
|
const tradingEure = {
|
|
assetId: 'nep141:eure.omft.near',
|
|
symbol: 'EURe',
|
|
decimals: 18,
|
|
chain: 'eth:100',
|
|
};
|
|
|
|
return {
|
|
tradingBtc,
|
|
tradingEure,
|
|
activePair: `${tradingBtc.assetId}->${tradingEure.assetId}`,
|
|
assetRegistry: new Map([
|
|
[tradingBtc.assetId, tradingBtc],
|
|
[tradingEure.assetId, tradingEure],
|
|
]),
|
|
strategyGrossThresholdPct: 2,
|
|
strategyMaxNotionalEure: 5,
|
|
strategyPriceMaxAgeMs: 30_000,
|
|
strategyInventoryMaxAgeMs: 30_000,
|
|
};
|
|
}
|
|
|
|
function makePriceEvent(overrides = {}) {
|
|
return {
|
|
ingested_at: new Date('2026-04-02T10:00:00.000Z').toISOString(),
|
|
payload: {
|
|
price_id: 'price-1',
|
|
pair: 'nep141:btc.omft.near->nep141:eure.omft.near',
|
|
eur_per_btc: '100000.00000000',
|
|
eure_per_btc: '100000.00000000',
|
|
btc_per_eur: '0.000010000000',
|
|
btc_per_eure: '0.000010000000',
|
|
...overrides,
|
|
},
|
|
};
|
|
}
|
|
|
|
function makeInventoryEvent(overrides = {}) {
|
|
return {
|
|
ingested_at: new Date('2026-04-02T10:00:00.000Z').toISOString(),
|
|
payload: {
|
|
inventory_id: 'inventory-1',
|
|
spendable: {
|
|
'nep141:btc.omft.near': '1000000',
|
|
'nep141:eure.omft.near': '10000000000000000000',
|
|
},
|
|
pending_inbound: {
|
|
'nep141:btc.omft.near': '0',
|
|
'nep141:eure.omft.near': '0',
|
|
},
|
|
...overrides,
|
|
},
|
|
};
|
|
}
|
|
|
|
test('strategy emits actionable exact-in BTC -> EURe command when armed and inventory is fresh', () => {
|
|
const config = makeConfig();
|
|
const result = evaluateTradeOpportunity({
|
|
demandEvent: {
|
|
payload: {
|
|
quote_id: 'quote-1',
|
|
pair: config.activePair,
|
|
asset_in: config.tradingBtc.assetId,
|
|
asset_out: config.tradingEure.assetId,
|
|
request_kind: 'exact_in',
|
|
amount_in: '5000',
|
|
min_deadline_ms: '60000',
|
|
},
|
|
},
|
|
priceEvent: makePriceEvent(),
|
|
inventoryEvent: makeInventoryEvent(),
|
|
config,
|
|
armed: true,
|
|
now: Date.parse('2026-04-02T10:00:05.000Z'),
|
|
});
|
|
|
|
assert.equal(result.decision.decision, 'actionable');
|
|
assert.equal(result.decision.decision_reason, 'actionable');
|
|
assert.ok(result.command);
|
|
assert.equal(result.command.quote_output.amount_out, '4900000000000000000');
|
|
});
|
|
|
|
test('strategy blocks when pending deposit exists but credited inventory is insufficient', () => {
|
|
const config = makeConfig();
|
|
const result = evaluateTradeOpportunity({
|
|
demandEvent: {
|
|
payload: {
|
|
quote_id: 'quote-2',
|
|
pair: config.activePair,
|
|
asset_in: config.tradingBtc.assetId,
|
|
asset_out: config.tradingEure.assetId,
|
|
request_kind: 'exact_in',
|
|
amount_in: '5000',
|
|
min_deadline_ms: '60000',
|
|
},
|
|
},
|
|
priceEvent: makePriceEvent(),
|
|
inventoryEvent: makeInventoryEvent({
|
|
spendable: {
|
|
'nep141:btc.omft.near': '1000000',
|
|
'nep141:eure.omft.near': '1000000000000000000',
|
|
},
|
|
pending_inbound: {
|
|
'nep141:btc.omft.near': '0',
|
|
'nep141:eure.omft.near': '5000000000000000000',
|
|
},
|
|
}),
|
|
config,
|
|
armed: true,
|
|
now: Date.parse('2026-04-02T10:00:05.000Z'),
|
|
});
|
|
|
|
assert.equal(result.decision.decision, 'rejected');
|
|
assert.equal(result.decision.decision_reason, 'pending_deposit_not_credited');
|
|
assert.equal(result.command, undefined);
|
|
});
|
|
|
|
test('strategy blocks stale prices before command emission', () => {
|
|
const config = makeConfig();
|
|
const result = evaluateTradeOpportunity({
|
|
demandEvent: {
|
|
payload: {
|
|
quote_id: 'quote-3',
|
|
pair: config.activePair,
|
|
asset_in: config.tradingEure.assetId,
|
|
asset_out: config.tradingBtc.assetId,
|
|
request_kind: 'exact_out',
|
|
amount_out: '10000',
|
|
min_deadline_ms: '60000',
|
|
},
|
|
},
|
|
priceEvent: makePriceEvent(),
|
|
inventoryEvent: makeInventoryEvent(),
|
|
config,
|
|
armed: true,
|
|
now: Date.parse('2026-04-02T10:00:45.000Z'),
|
|
});
|
|
|
|
assert.equal(result.decision.decision_reason, 'stale_reference_price');
|
|
assert.equal(result.command, undefined);
|
|
});
|