Files
monero_c/tests/utils.ts
cyan fcc2924f31 initial zano commit (#83)
* initial zano commit

* update checksum, fix zano patches on CI

* fix monero builds

* fix cmake command

* fix: devcontainer on x64
ffigen: add zano
zano: add missing free
dart: implement zano

* update boost filenames

* unboost the cmakelists

* fix zano boost issues

* added patch into proper location

* fix various build issues

* [skip ci] update tor-connect

* fix zano builds for ios

* fix apply patches and don't fail-fast

* uncomment build depends for monero

* build_single.sh fix for macos native builds

* disable qemu on arm64 builders from buildjet

* fix boost, fix missing symbols (maybe)

* fix ordering of crypto and ssl libraries

* fix wownero mingw

* fetch zano releases to release-bulk

* build things 'the zano way'

* proper cmake config

* Zano.. yeah...

* Update zano release to 2.0.1.367

* update zano patches

* update zano builds

* update zano build

* fix zano build

* move zlibstatic to the top (this shouldn't matter anyway)

* fix patch location, update tor-connect

* update ci runner

* fix zano build on the CI

* enable zano for other targets

* nvm

* don't use darwin in single release file

* Increase max password length

* build contrib/depends offline

* zano support for macos

* Update dependencies to work on multithread via rosetta2

* different way of adding .patch-applied

* Improve performance of incremental builds

* remove unnecessary patches

* update coin-control patch

* fix test

* remove contrib/depends patches in wownero

* chore: support fallback names in the download_deps util

---------

Co-authored-by: Im-Beast <franik.mateusz@gmail.com>
2025-01-04 09:02:44 +01:00

206 lines
6.0 KiB
TypeScript
Executable File

import { build$, CommandBuilder } from "jsr:@david/dax";
import { dirname, join } from "jsr:@std/path";
import {
downloadDependencies,
dylibInfos,
getFileInfo,
moneroCliInfo,
Target,
wowneroCliInfo,
} from "./download_deps.ts";
import { loadMoneroDylib, loadWowneroDylib, moneroSymbols, wowneroSymbols } from "../impls/monero.ts/mod.ts";
export type Coin = "monero" | "wownero";
const target = `${Deno.build.os}_${Deno.build.arch}` as const;
export const $ = build$({
commandBuilder: new CommandBuilder()
.printCommand(true)
.stdin("inherit")
.stdout("inherit")
.stderr("inherit"),
});
export const dylibNames = (coin: Coin, version: MoneroCVersion) => ({
linux_x86_64: `${coin}_x86_64-linux-gnu_libwallet2_api_c.so`,
darwin_aarch64: version === "next"
? `${coin}_aarch64-apple-darwin_libwallet2_api_c.dylib`
: `${coin}_aarch64-apple-darwin11_libwallet2_api_c.dylib`,
windows_x86_64: `${coin}_x86_64-w64-mingw32_libwallet2_api_c.dll`,
} as Partial<Record<Target, string>>);
export const moneroTsDylibNames = (coin: Coin) => ({
linux_x86_64: `${coin}_libwallet2_api_c.so`,
darwin_aarch64: `${coin}_aarch64-apple-darwin11_libwallet2_api_c.dylib`,
windows_x86_64: `${coin}_libwallet2_api_c.dll`,
} as Partial<Record<Target, string>>);
export function loadDylib(coin: Coin, version: MoneroCVersion) {
const dylibName = moneroTsDylibNames(coin)[target]!;
if (coin === "monero") {
const dylib = Deno.dlopen(`tests/dependencies/libs/${version}/${dylibName}`, moneroSymbols);
loadMoneroDylib(dylib);
return dylib;
} else {
const dylib = Deno.dlopen(`tests/dependencies/libs/${version}/${dylibName}`, wowneroSymbols);
loadWowneroDylib(dylib);
return dylib;
}
}
async function exists(path: string): Promise<boolean> {
try {
await Deno.stat(path);
return true;
} catch (error) {
if (error instanceof Deno.errors.NotFound) {
return false;
}
throw error;
}
}
export async function extract(path: string, out: string) {
const outDir = out.endsWith("/") ? out : dirname(out);
await Deno.mkdir(outDir, { recursive: true });
if (path.endsWith(".tar.bz2")) {
let args = `-C ${dirname(out)}`;
if (outDir === out) {
args = `-C ${out} --strip-components=1`;
}
await $.raw`tar -xf ${path} ${args}`;
} else if (path.endsWith(".zip")) {
await $.raw`unzip ${path} -nu -d ${outDir}`;
} else if (path.endsWith(".xz")) {
await $.raw`xz -kd ${path}`;
await Deno.rename(path.slice(0, -3), out);
} else {
throw new Error("Unsupported archive file for:" + path);
}
}
export async function prepareMoneroCli() {
await downloadDependencies(moneroCliInfo);
const path = join("./tests/dependencies", moneroCliInfo.outDir ?? "", getFileInfo(moneroCliInfo).names[0]);
await extract(path, "./tests/dependencies/monero-cli/");
}
export async function prepareWowneroCli() {
await downloadDependencies(wowneroCliInfo);
const path = join("./tests/dependencies", wowneroCliInfo.outDir ?? "", getFileInfo(wowneroCliInfo).names[0]);
await extract(path, "./tests/dependencies/wownero-cli/");
}
export function prepareCli(coin: Coin) {
if (coin === "wownero") {
return prepareWowneroCli();
}
return prepareMoneroCli();
}
interface WalletInfo {
path: string;
password: string;
address: string;
secretSpendKey: string;
publicSpendKey: string;
secretViewKey: string;
publicViewKey: string;
}
export async function createWalletViaCli(
coin: Coin,
name: string,
password: string,
): Promise<WalletInfo> {
const path = `./tests/wallets/${name}`;
const cliPath = `./tests/dependencies/${coin}-cli/${coin}-wallet-cli`;
await $
.raw`${cliPath} --generate-new-wallet ${path} --password ${password} --mnemonic-language English --command exit`
.stdout("null");
const address = (await $.raw`${cliPath} --wallet-file ${path} --password ${password} --command address`
.stdinText(`${password}\n`)
.lines())
.at(-1)!
.split(/\s+/)[1];
const retrieveKeys = (lines: string[]) =>
lines.slice(-2)
.map((line) => line.split(": ")[1]);
const [secretSpendKey, publicSpendKey] = retrieveKeys(
await $.raw`${cliPath} --wallet-file ${path} --password ${password} --command spendkey`
.stdinText(`${password}\n`)
.lines(),
);
const [secretViewKey, publicViewKey] = retrieveKeys(
await $.raw`${cliPath} --wallet-file ${path} --password ${password} --command viewkey`
.stdinText(`${password}\n`)
.lines(),
);
return {
path,
password,
address,
secretSpendKey,
publicSpendKey,
secretViewKey,
publicViewKey,
};
}
// deno-lint-ignore ban-types
export type MoneroCVersion = "next" | (string & {});
export async function getMoneroCTags(): Promise<string[]> {
const response = await fetch("https://static.mrcyjanek.net/monero_c/release.php");
if (!response.ok) {
throw new Error(`Could not receive monero_c release tags: ${await response.text()}`);
}
const json = await response.json() as { tag_name: string }[];
return json.map(({ tag_name }) => tag_name);
}
export async function prepareMoneroC(coin: Coin, version: MoneroCVersion) {
const dylibName = dylibNames(coin, version)[target];
const moneroTsDylibName = moneroTsDylibNames(coin)[target];
if (!dylibName || !moneroTsDylibName) {
throw new Error(`Missing dylib name value for target: ${target}`);
}
const releaseDylibName = dylibName.slice(`${coin}_`.length);
if (version === "next") {
const outFileDir = `./tests/dependencies/libs/${version}/${moneroTsDylibName}`;
if (await exists(outFileDir)) {
return;
}
await extract(`./release/${coin}/${releaseDylibName}.xz`, outFileDir);
} else {
const outFileDir = `./tests/dependencies/libs/${version}/${moneroTsDylibName}`;
if (await exists(outFileDir)) {
return;
}
const downloadInfo = dylibInfos[coin].find((info) => info.outDir?.endsWith(version));
if (downloadInfo) {
await downloadDependencies(downloadInfo);
}
await extract(`./tests/dependencies/libs/${version}/${dylibName}.xz`, outFileDir);
}
}