fix(builder): disarm remaining seed-vocab landmine, tighten tier-1 amount assertion

Opus review round 2 on Task 6:

- agent-network.ts: seedUtxo -> oneShotUtxo (5 occurrences). This is
  one-shot-minting-policy vocabulary that survives PR 7's keyless rewrite,
  but the boundary test's FORBIDDEN regex is an unanchored case-insensitive
  substring match on "seed" - left as-is it would have false-red PR 7's
  guard the moment agent-network.ts drops off the custodial allowlist. Only
  selectWallet.fromSeed (genuine key-material vocabulary, deleted by PR 7
  anyway) still matches `seed` in this file. File is @ts-nocheck, so this
  was verified mechanically, not just visually: line-match counts before
  (seedUtxo=5) and after (seedUtxo=0, oneShotUtxo=5) line up exactly, and a
  fresh `import()` of the module still loads error-free.
- keyless-build.test.ts: the first tier-1 test summed every output
  (`paid >= 3_000_000n`), but a self-send's change output lands at the same
  address as the payment, so the sum floor could never actually detect a
  dropped or wrong payment amount - change alone clears it. Added an
  exact-count check (outputs at exactly 3_000_000n lovelace, >=1) alongside
  the existing sum/fee/unsigned assertions, matching the pattern already
  used by the build_transaction test in the same file. Also added the
  missing assertBuildNotSubmitted check on the dry-run test's own build
  response.
- run.test.ts: deleted walletBalanceAda - write-only since the UTxO
  Consolidation block (its only reader) was removed earlier in this task.

Re-verified full gate plus one live re-run of the tightened tier-1 suite
(build-only, no funds spent, no E2E resubmission).
This commit is contained in:
FilipBl4gojevic
2026-07-29 13:56:33 +02:00
parent 9799cbd8ad
commit dde221fdba
3 changed files with 16 additions and 8 deletions

View File

@@ -45,11 +45,20 @@ describe('keyless build against live testnet', () => {
const tx = CML.Transaction.from_cbor_hex(cbor);
const outs = tx.body().outputs();
let paid = 0n;
// A self-send means the payment output and the change output land at the
// same address, so summing every output can't tell a correct 3 AP3X
// payment apart from a dropped/wrong one (change alone dwarfs the floor).
// Count outputs at exactly the requested lovelace amount instead - the
// same exact-count pattern the build_transaction test below uses.
let paymentOutputs = 0;
for (let i = 0; i < outs.len(); i++) {
const o = outs.get(i);
assert.equal(o.address().to_bech32(), OWN_ADDRESS, 'self-send must only pay the own address');
paid += BigInt(o.amount().coin().toString());
const lovelace = BigInt(o.amount().coin().toString());
paid += lovelace;
if (lovelace === 3_000_000n) paymentOutputs++;
}
assert.ok(paymentOutputs >= 1, `expected a 3 AP3X payment output, found ${paymentOutputs} (total paid: ${paid})`);
const fee = BigInt(tx.body().fee().toString());
assert.ok(fee >= 156_253n && fee <= 500_000n, `fee out of sane range: ${fee}`);
const vkeys = tx.witness_set().vkeywitnesses();
@@ -62,6 +71,7 @@ describe('keyless build against live testnet', () => {
const buildText = await callTool(ctx.client, 'vector_build_send_apex', {
changeAddress: OWN_ADDRESS, recipientAddress: OWN_ADDRESS, amount: 3,
});
assertBuildNotSubmitted(buildText);
const cbor = extractCbor(buildText);
const text = await callTool(ctx.client, 'vector_dry_run', { txCbor: cbor });
assert.match(text, /Valid: Yes/);

View File

@@ -10,7 +10,6 @@ let ctx: ServerContext;
let mnemonic: string;
let walletAddress: string;
let walletHasAda = false;
let walletBalanceAda = 0;
let agentDid: string | null = null;
before(async () => {
@@ -66,7 +65,6 @@ describe('Wallet Tools', () => {
const balanceMatch = text.match(/AP3X Balance:\s*([\d.]+)/);
if (balanceMatch && parseFloat(balanceMatch[1]) > 0) {
walletHasAda = true;
walletBalanceAda = parseFloat(balanceMatch[1]);
console.log(`Wallet funded: ${balanceMatch[1]} AP3X`);
} else {
console.log('Wallet has 0 AP3X - transaction tests will verify error handling');