Tests. Autocomplete. Few Fixes. Mocks for Electrum Service. Template-to-Json parser. Fix global paths. Use IO Dependency injection for logging from cli. Additional commands in CLI.
This commit is contained in:
164
tests/cli/mocks/engine.ts
Normal file
164
tests/cli/mocks/engine.ts
Normal file
@@ -0,0 +1,164 @@
|
||||
import { BlockchainMonitor, Engine } from "@xo-cash/engine";
|
||||
|
||||
import { createStorageAdapter, State, StorageType, type UnspentOutputData } from "@xo-cash/state";
|
||||
import { InMemoryBlockchainProvider } from "@xo-cash/engine";
|
||||
import { convertMnemonicToSeedBytes } from "@xo-cash/crypto";
|
||||
|
||||
import { binToHex, sha256 } from "@bitauth/libauth";
|
||||
import { AppService } from "../../../src/services/app";
|
||||
import { InMemoryStorage } from "../../../src/services/storage";
|
||||
import { MockElectrumService } from "./electrum-service";
|
||||
|
||||
export const DEFAULT_SEED = "page pencil stock planet limb cluster assault speak off joke private pioneer";
|
||||
|
||||
/**
|
||||
* Options for creating a fake resource (UTXO) in tests.
|
||||
*/
|
||||
export type FakeResourceOptions = {
|
||||
/** Transaction hash of the outpoint. Auto-generated if not provided. */
|
||||
outpointTransactionHash?: string;
|
||||
/** Index of the outpoint in the transaction. Defaults to 0. */
|
||||
outpointIndex?: number;
|
||||
/** Value in satoshis. Defaults to 10000. */
|
||||
valueSatoshis?: number;
|
||||
/** Template identifier. Defaults to "test-template". */
|
||||
templateIdentifier?: string;
|
||||
/** Output identifier from the template. Defaults to "receiveOutput". */
|
||||
outputIdentifier?: string;
|
||||
/** Locking bytecode for this output. Defaults to a placeholder. */
|
||||
lockingBytecode?: string;
|
||||
/** Block height where the UTXO was mined. Defaults to 800000. */
|
||||
minedAtHeight?: number;
|
||||
/** Invitation identifier that reserves this output. Undefined means unreserved. */
|
||||
reservedBy?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Generates a random 64-character hex string representing a transaction hash.
|
||||
*/
|
||||
export const randomTxHash = (): string => {
|
||||
const bytes = new Uint8Array(32);
|
||||
crypto.getRandomValues(bytes);
|
||||
return Array.from(bytes).map(b => b.toString(16).padStart(2, "0")).join("");
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds a fake resource (UTXO) to the engine's state for testing purposes.
|
||||
* @param engine - The engine instance to add the resource to.
|
||||
* @param options - Options for the fake resource. All fields have sensible defaults.
|
||||
* @returns The created UnspentOutputData object.
|
||||
*/
|
||||
export const addFakeResource = async (
|
||||
engine: Engine,
|
||||
options: FakeResourceOptions = {},
|
||||
): Promise<UnspentOutputData> => {
|
||||
const resource: UnspentOutputData = {
|
||||
status: "confirmed",
|
||||
selectable: true,
|
||||
privacy: false,
|
||||
templateIdentifier: options.templateIdentifier ?? "test-template",
|
||||
outputIdentifier: options.outputIdentifier ?? "receiveOutput",
|
||||
outpointIndex: options.outpointIndex ?? 0,
|
||||
outpointTransactionHash: options.outpointTransactionHash ?? randomTxHash(),
|
||||
minedAtHeight: options.minedAtHeight ?? 800000,
|
||||
valueSatoshis: options.valueSatoshis ?? 10000,
|
||||
lockingBytecode: options.lockingBytecode ?? "76a914000000000000000000000000000000000000000088ac",
|
||||
reservedBy: options.reservedBy,
|
||||
};
|
||||
|
||||
await engine.state.storeUnspentOutputData(resource);
|
||||
return resource;
|
||||
};
|
||||
|
||||
/**
|
||||
* Reserves a resource for a specific invitation.
|
||||
* @param engine - The engine instance.
|
||||
* @param outpointTransactionHash - The transaction hash of the UTXO to reserve.
|
||||
* @param outpointIndex - The output index of the UTXO to reserve.
|
||||
* @param invitationIdentifier - The invitation identifier to reserve for.
|
||||
*/
|
||||
export const reserveResource = async (
|
||||
engine: Engine,
|
||||
outpointTransactionHash: string,
|
||||
outpointIndex: number,
|
||||
invitationIdentifier: string,
|
||||
): Promise<void> => {
|
||||
await engine.state.executeBulkUnspentOutputReservation(
|
||||
[{ outpointTransactionHash, outpointIndex }],
|
||||
true,
|
||||
invitationIdentifier,
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Unreserves a resource from a specific invitation.
|
||||
* @param engine - The engine instance.
|
||||
* @param outpointTransactionHash - The transaction hash of the UTXO to unreserve.
|
||||
* @param outpointIndex - The output index of the UTXO to unreserve.
|
||||
* @param invitationIdentifier - The invitation identifier to unreserve from.
|
||||
*/
|
||||
export const unreserveResource = async (
|
||||
engine: Engine,
|
||||
outpointTransactionHash: string,
|
||||
outpointIndex: number,
|
||||
invitationIdentifier: string,
|
||||
): Promise<void> => {
|
||||
await engine.state.executeBulkUnspentOutputReservation(
|
||||
[{ outpointTransactionHash, outpointIndex }],
|
||||
false,
|
||||
invitationIdentifier,
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a mock engine instance with a given seed. Uses the in-memory storage and blockchain provider.
|
||||
* @param seed - The seed to use for the engine.
|
||||
* @returns A mock engine instance.
|
||||
*/
|
||||
export const createMockEngine = async (seed: string) => {
|
||||
// Create the in-memory storage adapter.
|
||||
const storage = await createStorageAdapter({
|
||||
storageType: StorageType.INMEMORY,
|
||||
accountHash: binToHex(sha256.hash(convertMnemonicToSeedBytes(seed))),
|
||||
});
|
||||
|
||||
// Initialize the storage adapter.
|
||||
await storage.initialize();
|
||||
|
||||
// Create the state instance.
|
||||
const state = new State(storage);
|
||||
|
||||
// Create the in-memory blockchain provider.
|
||||
const blockchainProvider = new InMemoryBlockchainProvider();
|
||||
await blockchainProvider.initialize({
|
||||
applicationIdentifier: "xo-cli-tests",
|
||||
electrumOptions: {},
|
||||
});
|
||||
|
||||
// Create the blockchain monitor instance.
|
||||
const blockchainMonitor = new BlockchainMonitor(state, blockchainProvider);
|
||||
await blockchainMonitor.initializeEventListeners();
|
||||
|
||||
// Create the engine instance.
|
||||
const engine = new Engine(seed, state, blockchainMonitor, blockchainProvider);
|
||||
await engine.initializeStateSync();
|
||||
|
||||
return engine;
|
||||
};
|
||||
|
||||
export const createMockAppService = async (engine: Engine) => {
|
||||
const storage = await InMemoryStorage.create();
|
||||
|
||||
const electrum = new MockElectrumService();
|
||||
|
||||
const config = {
|
||||
syncServerUrl: "http://localhost:3000",
|
||||
engineConfig: {
|
||||
databasePath: "test-data",
|
||||
databaseFilename: "xo-wallet.db",
|
||||
},
|
||||
invitationStoragePath: "test-invitations.db",
|
||||
};
|
||||
|
||||
return new AppService(engine, storage, config, electrum);
|
||||
};
|
||||
Reference in New Issue
Block a user