Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!: monero.ts rewrite, integration tests #80

Merged
merged 48 commits into from
Dec 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
6129937
feat: move spend/view key symbols to the monero.ts implementation
Im-Beast Oct 21, 2024
447d740
feat: add integration tests for `0001-polyseed.patch`
Im-Beast Oct 21, 2024
f0415bc
feat(monero.ts): add support for backgroundSync and closing the wallet
Im-Beast Oct 21, 2024
9cc6f71
feat: add integration tests for `0002-wallet-background-sync-with-jus…
Im-Beast Oct 21, 2024
d12e68f
feat!: require users to provide own node url
Im-Beast Oct 21, 2024
5df123b
feat: add background sync test for `0002-wallet-background-sync-with-…
Im-Beast Oct 21, 2024
31c31a5
ci: add integration tests step
Im-Beast Oct 21, 2024
d190d24
feat(monero.ts): support creating and recovering wallet from polyseed
Im-Beast Oct 21, 2024
572314b
feat: actually test polyseeds in the integration test
Im-Beast Oct 21, 2024
549c8d8
chore: remove legacy comments
Im-Beast Oct 21, 2024
77b2ece
fix: uncomment getting moneroC
Im-Beast Oct 21, 2024
8bbd1ae
feat(monero.ts): add support for reading wallet's seed
Im-Beast Oct 22, 2024
686bf98
feat: add seed test for `0009-Add-recoverDeterministicWalletFromSpend…
Im-Beast Oct 22, 2024
5089a0a
chore: slight refactor
Im-Beast Oct 22, 2024
23f64e8
feat(monero.ts): add bindings for `setOffline` and `isOffline`
Im-Beast Oct 22, 2024
f5daf66
feat: add integration tests for `0012-WIP-UR-functions.patch`
Im-Beast Oct 22, 2024
adadddb
fix: use correct node depending on the coin
Im-Beast Oct 22, 2024
d628b7c
fix: prevent segfaults on wownero
Im-Beast Oct 22, 2024
7e06cc8
feat(monero.ts): add partial bindings for `Coins` and `CoinsInfo`
Im-Beast Oct 25, 2024
14b348b
feat: add integration tests for `0004-coin-control.patch`
Im-Beast Oct 25, 2024
1079275
fix coin control
MrCyjaneK Oct 25, 2024
e9b3a5e
clean up console.logs
MrCyjaneK Oct 25, 2024
1a45c73
chore: comment out the entire block
Im-Beast Oct 25, 2024
2dc4bc1
dev: add devcontainer config for deno
MrCyjaneK Oct 26, 2024
b1392e7
fix(monero.ts): invalid PendingTransactionPtr brand
Im-Beast Oct 26, 2024
23f8aef
feat(monero.ts): add bindings for retrieving keys and managing transa…
Im-Beast Oct 26, 2024
74f0915
feat: improve `0012-WIP-UR-functions.patch` tests to follow the airga…
Im-Beast Oct 26, 2024
e39f98f
fix(monero.ts): make UR methods optional so wownero can load properly
Im-Beast Oct 27, 2024
bf06da7
remove flaky balance assertions
Im-Beast Oct 27, 2024
11970b2
tests: add a little bit of delay to make 0002 patch test less flake-y
Im-Beast Oct 27, 2024
bc7a6fc
tests: run wallet transaction tests on ci
Im-Beast Oct 28, 2024
2c91492
enable logging to determine why it segfaults on ci
Im-Beast Oct 28, 2024
350ec96
add delay to every syncBlockchain call
Im-Beast Oct 28, 2024
238a626
its console logging time
Im-Beast Oct 28, 2024
dba15b9
even more console.logs
Im-Beast Oct 28, 2024
392bbb9
eep
Im-Beast Oct 29, 2024
1e66a1a
eep more
Im-Beast Oct 29, 2024
7ec7f27
dont assert that its not frozen
Im-Beast Oct 29, 2024
0539f9b
remove console.logs
Im-Beast Oct 29, 2024
165733e
fix(monero.ts): type typo becoming a default value
Im-Beast Nov 20, 2024
5d5079f
feat(monero.ts): add bindings for `createTransactionMultDest`
Im-Beast Nov 20, 2024
0e888c1
Merge branch 'master' into integration-tests
Im-Beast Nov 20, 2024
07ed34e
feat(monero.ts): support returning multiple values whenever necessary
Im-Beast Nov 20, 2024
9496ab4
feat(monero.ts): add missing reexports
Im-Beast Nov 20, 2024
dccec0c
feat(monero.ts)!: rewrite bindings
Im-Beast Nov 30, 2024
3fdf414
tests: adapt tests to monero.ts changes
Im-Beast Nov 30, 2024
94439e8
Merge branch 'master' into integration-tests
Im-Beast Nov 30, 2024
05c4210
tests: reuse dylib in tests
Im-Beast Dec 1, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
FROM ghcr.io/cirruslabs/flutter:3.24.3
# FROM debian:bookworm
SHELL ["/bin/bash", "-c"]

# Install dependencies

Expand All @@ -15,11 +16,18 @@ RUN apt update \

RUN bash -c 'if [[ "$(uname -m)" == "aarch64" || "$(uname -m)" == "arm64" ]] then sudo rm -rf /opt/android-sdk-linux/platform-tools; fi'

# Install zsh and configure it

ENV DENO_VERSION=v2.0.3
RUN if [[ "$(uname -m)" == "aarch64" || "$(uname -m)" == "arm64" ]] then export DENO_ARCH=aarch64-unknown-linux-gnu; fi; \
if [[ "$(uname -m)" == "x86_64" || "$(uname -m)" == "amd64" ]] then export DENO_ARCH=x86_64-unknown-linux-gnu; fi; \
wget -O /tmp/deno.zip "https://github.com/denoland/deno/releases/download/${DENO_VERSION}/deno-${DENO_ARCH}.zip" && \
cd /tmp && \
unzip /tmp/deno.zip && \
mv deno /usr/local/bin && \
rm -rf deno deno.zip

USER ubuntu

RUN git config --global --add safe.directory '*'
RUN sh -c "$(wget -O- https://github.com/deluan/zsh-in-docker/releases/download/v1.2.0/zsh-in-docker.sh)" \
-t robbyrussell

RUN git config --global --add safe.directory '*'
3 changes: 2 additions & 1 deletion .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
},
"extensions": [
"dart-code.flutter",
"dart-code.dart-code"
"dart-code.dart-code",
"denoland.vscode-deno"
]
}
},
Expand Down
33 changes: 32 additions & 1 deletion .github/workflows/full_check.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -609,7 +609,38 @@ jobs:
path: release/${{ matrix.coin }}

- name: Run regression tests
run: COIN="${{ matrix.coin }}" deno test -A tests/
run: COIN="${{ matrix.coin }}" deno test -A tests/regression.test.ts

integration_check:
strategy:
matrix:
coin: [monero, wownero]
needs: [
lib_linux
]
runs-on: ubuntu-24.04
steps:
- uses: denoland/setup-deno@v2
with:
deno-version: v2.x

- uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: recursive

- uses: actions/download-artifact@v4
with:
name: linux ${{ matrix.coin }}
path: release/${{ matrix.coin }}

- name: Run integration tests
run: COIN="${{ matrix.coin }}" deno test -A tests/integration.test.ts
env:
SECRET_WALLET_PASSWORD: ${{ secrets.SECRET_WALLET_PASSWORD }}
SECRET_WALLET_MNEMONIC: ${{ secrets.SECRET_WALLET_MNEMONIC }}
SECRET_WALLET_RESTORE_HEIGHT: ${{ secrets.SECRET_WALLET_RESTORE_HEIGHT }}


comment_pr:
name: comment on pr
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
release/
build/
tests/monero-cli
tests/wownero-cli
tests/libs
tests/wallets
4 changes: 2 additions & 2 deletions impls/monero.ts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ There are at least two ways to do so:
loadMoneroDylib();

const wm = await WalletManager.new();
const wallet = await Wallet.create(wm, "./my_wallet", "password");
const wallet = await wm.createWallet("./my_wallet", "password");

console.log(await wallet.address());

Expand All @@ -41,7 +41,7 @@ There are at least two ways to do so:
loadMoneroDylib(lib);

const wm = await WalletManager.new();
const wallet = await Wallet.create(wm, "./my_wallet", "password");
const wallet = await wm.createWallet("./my_wallet", "password");

console.log(await wallet.address());

Expand Down
10 changes: 5 additions & 5 deletions impls/monero.ts/checksum.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { moneroChecksum } from "./checksum_monero.ts";
import { getSymbol, readCString } from "./src/utils.ts";
import { dylib, loadMoneroDylib } from "./src/bindings.ts";
import { readCString } from "./src/utils.ts";
import { fns, loadMoneroDylib } from "./src/bindings.ts";

loadMoneroDylib();

Expand All @@ -21,7 +21,7 @@ export class ChecksumError extends Error {
* @returns {ChecksumError} which contains information about why checksum failed
*/
export async function validateChecksum(): Promise<ChecksumError | null> {
const cppHeaderHash = await readCString(await getSymbol("checksum_wallet2_api_c_h")!(), false);
const cppHeaderHash = await readCString(await fns.checksum_wallet2_api_c_h!(), false);
const tsHeaderHash = moneroChecksum.wallet2_api_c_h_sha256;

const errors: string[] = [];
Expand All @@ -32,14 +32,14 @@ export async function validateChecksum(): Promise<ChecksumError | null> {
errorCode++;
}

const cppSourceHash = await readCString(await getSymbol("checksum_wallet2_api_c_cpp")!(), false);
const cppSourceHash = await readCString(await fns.checksum_wallet2_api_c_cpp!(), false);
const tsSourceHash = moneroChecksum.wallet2_api_c_cpp_sha256;
if (cppSourceHash !== tsSourceHash) {
errors.push(`ERR: CPP source file check mismatch ${cppSourceHash} == ${tsSourceHash}`);
errorCode++;
}

const cppExportHash = await readCString(await getSymbol("checksum_wallet2_api_c_exp")!(), false);
const cppExportHash = await readCString(await fns.checksum_wallet2_api_c_exp!(), false);
const tsExportHash = moneroChecksum.wallet2_api_c_exp_sha256;
if (cppExportHash !== tsExportHash) {
if (Deno.build.os !== "darwin") {
Expand Down
5 changes: 5 additions & 0 deletions impls/monero.ts/mod.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
export * from "./src/bindings.ts";
export * from "./src/coins.ts";
export * from "./src/coins_info.ts";
export * from "./src/pending_transaction.ts";
export * from "./src/symbols.ts";
export * from "./src/transaction_history.ts";
export * from "./src/transaction_info.ts";
export * from "./src/unsigned_transaction.ts";
export * from "./src/utils.ts";
export * from "./src/wallet.ts";
export * from "./src/wallet_manager.ts";
21 changes: 18 additions & 3 deletions impls/monero.ts/src/bindings.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,21 @@
import { type Dylib, moneroSymbols, type MoneroTsDylib, wowneroSymbols, type WowneroTsDylib } from "./symbols.ts";
import { type MoneroSymbols, moneroSymbols, type SymbolName, type WowneroSymbols, wowneroSymbols } from "./symbols.ts";

export type MoneroDylib = Deno.DynamicLibrary<MoneroSymbols>;
export type WowneroDylib = Deno.DynamicLibrary<WowneroSymbols>;
export type Dylib = MoneroDylib | WowneroDylib;

export let dylib: Dylib;

export function loadMoneroDylib(newDylib?: MoneroTsDylib) {
let dylibPrefix = "MONERO";
export const fns = new Proxy({} as { [K in SymbolName]: MoneroDylib["symbols"][`MONERO_${K}`] }, {
get(_, symbolName: SymbolName) {
return dylib.symbols[`${dylibPrefix}_${symbolName}` as keyof Dylib["symbols"]];
},
});

export function loadMoneroDylib(newDylib?: MoneroDylib) {
dylibPrefix = "MONERO";

if (newDylib) {
dylib = newDylib;
return;
Expand All @@ -27,7 +40,9 @@ export function loadMoneroDylib(newDylib?: MoneroTsDylib) {
dylib = Deno.dlopen(libPath, moneroSymbols);
}

export function loadWowneroDylib(newDylib?: WowneroTsDylib) {
export function loadWowneroDylib(newDylib?: WowneroDylib) {
dylibPrefix = "WOWNERO";

if (newDylib) {
dylib = newDylib;
return;
Expand Down
53 changes: 53 additions & 0 deletions impls/monero.ts/src/coins.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { CoinsInfo, type CoinsInfoPtr } from "./coins_info.ts";
import { fns } from "./bindings.ts";

export type CoinsPtr = Deno.PointerObject<"coins">;

export class Coins {
#ptr: CoinsPtr;

#coins: CoinsInfo[] = [];

constructor(ptr: CoinsPtr) {
this.#ptr = ptr;
}

async count(): Promise<number> {
return await fns.Coins_count(this.#ptr);
}

async coin(index: number): Promise<CoinsInfo | null> {
if (this.#coins[index]) {
return this.#coins[index];
}

const coinPtr = await fns.Coins_coin(this.#ptr, index);
if (!coinPtr) return null;

return CoinsInfo.new(coinPtr as CoinsInfoPtr);
}

async setFrozen(index: number) {
return await fns.Coins_setFrozen(this.#ptr, index);
}

async thaw(index: number) {
return await fns.Coins_thaw(this.#ptr, index);
}

async getAllSize(): Promise<number> {
return await fns.Coins_getAll_size(this.#ptr);
}

async getAllByIndex(index: number): Promise<unknown> {
return await fns.Coins_getAll_byIndex(this.#ptr, index);
}

async refresh(): Promise<void> {
await fns.Coins_refresh(this.#ptr);

for (const coin of this.#coins) {
coin.refresh();
}
}
}
85 changes: 85 additions & 0 deletions impls/monero.ts/src/coins_info.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { fns } from "./bindings.ts";
import { readCString } from "./utils.ts";

export type CoinsInfoPtr = Deno.PointerObject<"coinsInfo">;

export class CoinsInfo {
#ptr: CoinsInfoPtr;

#hash!: string | null;
#keyImage!: string | null;
#blockHeight!: bigint;
#amount!: bigint;
#spent!: boolean;
#spentHeight!: bigint;
#frozen!: boolean;
#unlocked!: boolean;

constructor(ptr: CoinsInfoPtr) {
this.#ptr = ptr;
}

getPointer(): CoinsInfoPtr {
return this.#ptr;
}

static async new(ptr: CoinsInfoPtr): Promise<CoinsInfo> {
const instance = new CoinsInfo(ptr);
await instance.refresh();
return instance;
}

async refresh() {
const [hash, keyImage, blockHeight, amount, spent, spentHeight, frozen, unlocked] = await Promise.all([
fns.CoinsInfo_hash(this.#ptr).then(readCString),
fns.CoinsInfo_keyImage(this.#ptr).then(readCString),
fns.CoinsInfo_blockHeight(this.#ptr),
fns.CoinsInfo_amount(this.#ptr),
fns.CoinsInfo_spent(this.#ptr),
fns.CoinsInfo_spentHeight(this.#ptr),
fns.CoinsInfo_frozen(this.#ptr),
fns.CoinsInfo_unlocked(this.#ptr),
]);

this.#hash = hash;
this.#keyImage = keyImage;
this.#blockHeight = blockHeight;
this.#amount = amount;
this.#spent = spent;
this.#spentHeight = spentHeight;
this.#frozen = frozen;
this.#unlocked = unlocked;
}

get hash(): string | null {
return this.#hash;
}

get keyImage(): string | null {
return this.#keyImage;
}

get blockHeight(): bigint {
return this.#blockHeight;
}

get amount(): bigint {
return this.#amount;
}

get spent(): boolean {
return this.#spent;
}

get spentHeight(): bigint {
return this.#spentHeight;
}

get frozen(): boolean {
return this.#frozen;
}

get unlocked(): boolean {
return this.#unlocked;
}
}
Loading
Loading