#!/usr/bin/env node import assert from 'node:assert/strict'; import { readFile } from 'node:fs/promises'; import { dirname, resolve } from 'node:path'; import { fileURLToPath } from 'node:url'; import { ChangeOwnerPermission, Contract, Network, PrivateKey, RoleSimple, SplitJoinPermission, Topology, TransactionPack, unicryptoReady } from 'universa-core2'; const sourceDirectory = dirname(fileURLToPath(import.meta.url)); const topologyFile = resolve(sourceDirectory, 'universa.json'); const clientKeyFile = resolve(sourceDirectory, 'white.private.unikey'); const sleep = (milliseconds) => new Promise((resolvePromise) => { setTimeout(resolvePromise, milliseconds); }); async function waitForFinalState(network, connection, contractId) { const deadline = Date.now() + 60_000; while (Date.now() < deadline) { const { itemResult } = await network.getState( contractId.composite3, connection, { timeout: 5_000 } ); const state = itemResult?.state; if (state && state !== 'UNDEFINED' && !state.startsWith('PENDING') && !state.startsWith('LOCKED')) { return itemResult; } await sleep(250); } throw new Error('contract registration timed out'); } await unicryptoReady; const topologyData = JSON.parse(await readFile(topologyFile, 'utf8')); const topology = await Topology.load(topologyData); const clientKey = await PrivateKey.unpack(await readFile(clientKeyFile)); const network = new Network(clientKey, { topology, directConnection: true }); console.log(`Connecting to ${topology.size()} Universa nodes from ${topologyFile}`); await network.connect(); const response = await network.command('sping'); assert.equal(response?.sping, 'spong', 'unexpected network state response'); console.log(`Universa network is functioning: ${network.size()} nodes, sping=spong`); // This key owns and signs the sample token. The white key above is used only // to authenticate the client and authorize fee-free registration. const tokenKey = await PrivateKey.generate({ strength: 2048 }); const issuer = new RoleSimple('issuer', { addresses: [tokenKey.publicKey.shortAddress] }); const splitJoinPermission = SplitJoinPermission.create('owner', { field_name: 'amount', min_value: '0', min_unit: '0.01', join_match_fields: ['state.origin'] }); const token = Contract.create(issuer, { definitionData: { template_name: 'UNIT_CONTRACT', unit_name: 'Sample Token', unit_short_name: 'SAMPLE', description: 'A token created by the universa-core2 sample' }, stateData: { amount: '100' }, permissions: [ ChangeOwnerPermission.create('owner'), splitJoinPermission ], expiresAt: '3m', createdAt: new Date() }); await token.sign(tokenKey); const transactionPack = new TransactionPack(token.pack()); const packedTransaction = await transactionPack.pack(); const contractId = await token.hashId(); console.log(`Created and packed SAMPLE token (${packedTransaction.length} bytes)`); const connection = await network.getRandomConnection(); await network.command( 'approve', { packedItem: packedTransaction }, connection, { timeout: 10_000 } ); const itemResult = await waitForFinalState(network, connection, contractId); assert.equal( itemResult.state, 'APPROVED', `token registration failed: ${JSON.stringify(itemResult.errors ?? [])}` ); console.log(`SAMPLE token is ${itemResult.state}`);