iuna

iuna

iuna - experimental mainnet-candidate protocol
git clone https://getiuna.org/git/iuna.git
Log | Files | Refs | README | LICENSE

quantum-migration.test.cjs (4167B)


      1 const { test } = require('node:test');
      2 const assert = require('node:assert/strict');
      3 const { readFileSync } = require('node:fs');
      4 const vm = require('node:vm');
      5 
      6 function app() {
      7   const context = {
      8     window: {},
      9     localStorage: { getItem: () => null },
     10     setTimeout,
     11     clearTimeout,
     12     URLSearchParams,
     13   };
     14   vm.runInNewContext(readFileSync(require.resolve('../www/assets/iuna-ui.js'), 'utf8'), context);
     15   const ui = context.window.iunaApp();
     16   ui.status = {
     17     wallet_locked: false,
     18     quantum_migration: { active: true, legacy_balance: 1_000_000, hybrid_balance: 0 },
     19   };
     20   ui.refresh = async () => {};
     21   ui.showFlash = () => {};
     22   return ui;
     23 }
     24 
     25 test('migration preview does not submit funds', async () => {
     26   const ui = app();
     27   const paths = [];
     28   ui.submitForm = async (path, fields) => {
     29     paths.push(path);
     30     assert.equal(fields.fee_per_byte, 1);
     31     return {
     32       preview: {
     33         transaction_id: 'ab'.repeat(32),
     34         input_count: 2,
     35         remaining_legacy_utxos: 3,
     36         bytes: 500,
     37         fee: 500,
     38         amount: 999_500,
     39       },
     40     };
     41   };
     42 
     43   await ui.previewQuantumMigration();
     44 
     45   assert.deepEqual(paths, ['/api/wallet/quantum-migration/preview']);
     46   assert.equal(ui.quantumMigrationPreview.remaining_legacy_utxos, 3);
     47 });
     48 
     49 test('confirmed migration submits the exact preview once', async () => {
     50   const ui = app();
     51   ui.quantumMigrationPreview = {
     52     transaction_id: 'cd'.repeat(32),
     53     rate: 2,
     54     fee: 1_000,
     55     remaining_legacy_utxos: 4,
     56   };
     57   let submissions = 0;
     58   ui.submitForm = async (path, fields) => {
     59     submissions += 1;
     60     assert.equal(path, '/api/wallet/quantum-migration/submit');
     61     assert.equal(fields.transaction_id, 'cd'.repeat(32));
     62     assert.equal(fields.max_fee, 1_000);
     63     return { transaction_id: fields.transaction_id, remaining_legacy_utxos: 4 };
     64   };
     65 
     66   await ui.submitQuantumMigration();
     67   await ui.submitQuantumMigration();
     68 
     69   assert.equal(submissions, 1);
     70   assert.equal(ui.quantumMigrationPreview, null);
     71 });
     72 
     73 test('uncertain migration submission requires a fresh preview', async () => {
     74   const ui = app();
     75   ui.quantumMigrationPreview = {
     76     transaction_id: 'ef'.repeat(32),
     77     rate: 1,
     78     fee: 500,
     79   };
     80   ui.submitForm = async () => { throw new Error('timeout'); };
     81 
     82   await ui.submitQuantumMigration();
     83 
     84   assert.equal(ui.quantumMigrationPreview, null);
     85   assert.match(ui.quantumMigrationError, /Check wallet activity/);
     86 });
     87 
     88 test('durability failure warns without inviting a duplicate migration', async () => {
     89   const ui = app();
     90   ui.quantumMigrationPreview = {
     91     transaction_id: '34'.repeat(32),
     92     rate: 1,
     93     fee: 500,
     94   };
     95   ui.submitForm = async () => ({
     96     transaction_id: '34'.repeat(32),
     97     remaining_legacy_utxos: 0,
     98     persistence_error: 'disk full',
     99   });
    100 
    101   await ui.submitQuantumMigration();
    102 
    103   assert.equal(ui.quantumMigrationPreview, null);
    104   assert.match(ui.quantumMigrationError, /durable recovery failed/);
    105 });
    106 
    107 test('broadcast failure explains that the saved migration will retry', async () => {
    108   const ui = app();
    109   ui.quantumMigrationPreview = {
    110     transaction_id: '56'.repeat(32),
    111     rate: 1,
    112     fee: 500,
    113   };
    114   ui.submitForm = async () => ({
    115     transaction_id: '56'.repeat(32),
    116     remaining_legacy_utxos: 0,
    117     broadcast_error: 'no peers',
    118   });
    119 
    120   await ui.submitQuantumMigration();
    121 
    122   assert.match(ui.quantumMigrationError, /rebroadcast automatically/);
    123 });
    124 
    125 test('hybrid recipients never reuse selected legacy UTXOs', () => {
    126   const ui = app();
    127   ui.transferTo = `iuna1p${'q'.repeat(58)}`;
    128   ui.selectedTransferUtxos = ['legacy:0'];
    129   ui.selectedTransferUtxoAmounts = { 'legacy:0': 10 };
    130   ui.showSendAdvanced = true;
    131 
    132   ui.transferRecipientChanged();
    133 
    134   assert.equal(ui.hybridTransferRecipient(), true);
    135   assert.equal(ui.selectedTransferUtxos.length, 0);
    136   assert.equal(ui.showSendAdvanced, false);
    137 });
    138 
    139 test('migration status can identify the exact pending v2 transaction', () => {
    140   const ui = app();
    141   ui.status.quantum_migration.migration_pending = true;
    142   ui.status.quantum_migration.pending_transaction_id = '12'.repeat(32);
    143 
    144   assert.equal(ui.status.quantum_migration.pending_transaction_id, '12'.repeat(32));
    145 });