Files
Matt Hess 733ecd2681 Migrate all JS tests to Rust: 9-crate workspace, 703 tests, 0 JS remaining
Add root Cargo workspace with 9 crates: salvium-crypto (extended),
  salvium-types, salvium-consensus, salvium-wallet, salvium-tx,
  salvium-rpc, salvium-miner (extended), salvium-cli, salvium-multisig.

  New modules: chain_state, block_weight, alt_chain, validation,
  offline signing, stake lifecycle, wallet sync/query/encryption/utxo,
  randomx utilities, and full multisig crate with CARROT support.

  Delete 188 JS test/helper/debug files; archive integration test
  scripts to test/legacy-js/ for live testnet use. Testnet integration
  tests (transfer, stake, burn, convert, sweep) remain as #[ignore]-
  gated Rust tests runnable with --ignored against a live daemon.
2026-02-17 23:09:35 +00:00

79 lines
2.5 KiB
JavaScript

/**
* Shared test helpers for Salvium-JS integration tests.
*
* Extracts common utilities used across sweep, sync, stress, and burn-in tests.
*/
import { Wallet } from '../src/wallet.js';
/**
* Get current blockchain height from daemon.
* @param {Object} daemon - DaemonRPC instance
* @returns {Promise<number>}
*/
export async function getHeight(daemon) {
const info = await daemon.getInfo();
return info.result?.height || info.data?.height || 0;
}
/**
* Poll daemon until target height is reached.
* @param {Object} daemon - DaemonRPC instance
* @param {number} target - Target block height
* @param {string} [label] - Label for progress display
* @returns {Promise<number>} Final height
*/
export async function waitForHeight(daemon, target, label = '') {
let h = await getHeight(daemon);
if (h >= target) return h;
const tag = label ? ` [${label}]` : '';
process.stdout.write(` Waiting for height ${target}${tag}... (at ${h})`);
while (h < target) {
await new Promise(r => setTimeout(r, 3000));
h = await getHeight(daemon);
process.stdout.write(`\r Waiting for height ${target}${tag}... (at ${h}) `);
}
process.stdout.write('\n');
return h;
}
/**
* Format atomic units as "X.XXXXXXXX SAL".
* @param {bigint|number} atomic
* @param {string} [label='SAL'] - Asset label (e.g. 'SAL', 'SAL1')
* @returns {string}
*/
export function fmt(atomic, label = 'SAL') {
return `${(Number(atomic) / 1e8).toFixed(8)} ${label}`;
}
/**
* Truncate an address for display.
* @param {string} addr
* @returns {string}
*/
export function short(addr) {
return addr ? addr.slice(0, 20) + '...' : 'N/A';
}
/**
* Load a wallet from a JSON file on disk.
* Supports both plain and encrypted wallet files.
* For encrypted files, reads the PIN from a sibling .pin file
* (e.g. wallet-a.json → wallet-a.pin) or accepts an explicit password.
* @param {string} path - Absolute path to wallet JSON file
* @param {string} [network='testnet'] - Network override
* @param {string} [password] - Explicit password (if omitted, reads .pin file)
* @returns {Promise<Wallet>}
*/
export async function loadWalletFromFile(path, network = 'testnet', password) {
const data = JSON.parse(await Bun.file(path).text());
if (Wallet.isEncrypted(data)) {
if (!password) {
const pinPath = path.replace(/\.json$/, '.pin');
password = (await Bun.file(pinPath).text()).trim();
}
return Wallet.fromEncryptedJSON(data, password, { network });
}
return Wallet.fromJSON(data, { network });
}