From d7a38301ece1a166af7b230e34be6e950e0aeb3c Mon Sep 17 00:00:00 2001 From: cyan Date: Mon, 26 Aug 2024 06:57:16 +0200 Subject: Monero v0.18.3.4 (#38) * updated monero dependency * update patches for v0.18.3.4 * update generate checksum to include version of submodule as well --- impls/monero.dart/lib/src/checksum_monero.dart | 2 +- impls/monero.dart/lib/src/checksum_wownero.dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'impls') diff --git a/impls/monero.dart/lib/src/checksum_monero.dart b/impls/monero.dart/lib/src/checksum_monero.dart index 9e553f9..364e618 100644 --- a/impls/monero.dart/lib/src/checksum_monero.dart +++ b/impls/monero.dart/lib/src/checksum_monero.dart @@ -1,4 +1,4 @@ // ignore_for_file: constant_identifier_names const String wallet2_api_c_h_sha256 = "e8db0ef0324a153f5e3ecca4c0db23c54f4576e84988f04bd4f11c1142f9d7ad"; -const String wallet2_api_c_cpp_sha256 = "d1842cded0040c16b8886878681c8938005f69ec1378fa9be68a430311cc3666"; +const String wallet2_api_c_cpp_sha256 = "d1842cded0040c16b8886878681c8938005f69ec1378fa9be68a430311cc3666-b089f9ee69924882c5d14dd1a6991deb05d9d1cd"; const String wallet2_api_c_exp_sha256 = "c8913ac41068f67b57c9b0a3c7dd8973e3c1273b66c2ff0aadb0003931da748c"; diff --git a/impls/monero.dart/lib/src/checksum_wownero.dart b/impls/monero.dart/lib/src/checksum_wownero.dart index f4ed1e7..5b71c28 100644 --- a/impls/monero.dart/lib/src/checksum_wownero.dart +++ b/impls/monero.dart/lib/src/checksum_wownero.dart @@ -1,4 +1,4 @@ // ignore_for_file: constant_identifier_names const String wallet2_api_c_h_sha256 = "8a8d386dd5d996c89a0586c55b295ef95ca584bf1ffa26255152b291910a0a77"; -const String wallet2_api_c_cpp_sha256 = "ed400bd9c4709383ffd42a9fbe68be37a2a47a42f92eacaf3a2dbd248c422739"; +const String wallet2_api_c_cpp_sha256 = "ed400bd9c4709383ffd42a9fbe68be37a2a47a42f92eacaf3a2dbd248c422739-e25963cbc11ca0a0fe5eb34b9bd7c72e4f51b795"; const String wallet2_api_c_exp_sha256 = "3673e40e1a7115552276d1d541f6e4d5a0fef47c40fff7b988f49923af84c8a4"; -- cgit v1.2.3 From 00a935025e1f405ae84f0618669011b12e6a6514 Mon Sep 17 00:00:00 2001 From: Czarek Nakamoto Date: Wed, 28 Aug 2024 11:07:35 +0200 Subject: update checksum --- generate_checksum.sh | 2 +- impls/monero.dart/lib/src/checksum_monero.dart | 2 +- impls/monero.dart/lib/src/checksum_wownero.dart | 2 +- monero_libwallet2_api_c/src/main/cpp/monero_checksum.h | 2 +- wownero_libwallet2_api_c/src/main/cpp/wownero_checksum.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) (limited to 'impls') diff --git a/generate_checksum.sh b/generate_checksum.sh index 7fcca70..5847ff5 100755 --- a/generate_checksum.sh +++ b/generate_checksum.sh @@ -1,6 +1,6 @@ #!/bin/bash cd "$(realpath $(dirname $0))" - +function sha256sum() { shasum -a 256 "$@" ; } && export -f sha256sum for coin in monero wownero; do submodule_hash=$(git ls-tree HEAD ${coin} | xargs | awk '{ print $3 }') diff --git a/impls/monero.dart/lib/src/checksum_monero.dart b/impls/monero.dart/lib/src/checksum_monero.dart index 364e618..4ab72a3 100644 --- a/impls/monero.dart/lib/src/checksum_monero.dart +++ b/impls/monero.dart/lib/src/checksum_monero.dart @@ -1,4 +1,4 @@ // ignore_for_file: constant_identifier_names const String wallet2_api_c_h_sha256 = "e8db0ef0324a153f5e3ecca4c0db23c54f4576e84988f04bd4f11c1142f9d7ad"; -const String wallet2_api_c_cpp_sha256 = "d1842cded0040c16b8886878681c8938005f69ec1378fa9be68a430311cc3666-b089f9ee69924882c5d14dd1a6991deb05d9d1cd"; +const String wallet2_api_c_cpp_sha256 = "dca52ac9ee009fda9fb5726543a454885e61d8eb74fb33112288029ed625bec5-b089f9ee69924882c5d14dd1a6991deb05d9d1cd"; const String wallet2_api_c_exp_sha256 = "c8913ac41068f67b57c9b0a3c7dd8973e3c1273b66c2ff0aadb0003931da748c"; diff --git a/impls/monero.dart/lib/src/checksum_wownero.dart b/impls/monero.dart/lib/src/checksum_wownero.dart index 5b71c28..8d08889 100644 --- a/impls/monero.dart/lib/src/checksum_wownero.dart +++ b/impls/monero.dart/lib/src/checksum_wownero.dart @@ -1,4 +1,4 @@ // ignore_for_file: constant_identifier_names const String wallet2_api_c_h_sha256 = "8a8d386dd5d996c89a0586c55b295ef95ca584bf1ffa26255152b291910a0a77"; -const String wallet2_api_c_cpp_sha256 = "ed400bd9c4709383ffd42a9fbe68be37a2a47a42f92eacaf3a2dbd248c422739-e25963cbc11ca0a0fe5eb34b9bd7c72e4f51b795"; +const String wallet2_api_c_cpp_sha256 = "28e4d44c565cd7d97d3f18cdd322be48f89dc9fded82fb533af56a8eaa4e0bda-e25963cbc11ca0a0fe5eb34b9bd7c72e4f51b795"; const String wallet2_api_c_exp_sha256 = "3673e40e1a7115552276d1d541f6e4d5a0fef47c40fff7b988f49923af84c8a4"; diff --git a/monero_libwallet2_api_c/src/main/cpp/monero_checksum.h b/monero_libwallet2_api_c/src/main/cpp/monero_checksum.h index f07cafe..20cbeae 100644 --- a/monero_libwallet2_api_c/src/main/cpp/monero_checksum.h +++ b/monero_libwallet2_api_c/src/main/cpp/monero_checksum.h @@ -1,6 +1,6 @@ #ifndef MONEROC_CHECKSUMS #define MONEROC_CHECKSUMS const char * MONERO_wallet2_api_c_h_sha256 = "e8db0ef0324a153f5e3ecca4c0db23c54f4576e84988f04bd4f11c1142f9d7ad"; -const char * MONERO_wallet2_api_c_cpp_sha256 = "d1842cded0040c16b8886878681c8938005f69ec1378fa9be68a430311cc3666-b089f9ee69924882c5d14dd1a6991deb05d9d1cd"; +const char * MONERO_wallet2_api_c_cpp_sha256 = "dca52ac9ee009fda9fb5726543a454885e61d8eb74fb33112288029ed625bec5-b089f9ee69924882c5d14dd1a6991deb05d9d1cd"; const char * MONERO_wallet2_api_c_exp_sha256 = "c8913ac41068f67b57c9b0a3c7dd8973e3c1273b66c2ff0aadb0003931da748c"; #endif diff --git a/wownero_libwallet2_api_c/src/main/cpp/wownero_checksum.h b/wownero_libwallet2_api_c/src/main/cpp/wownero_checksum.h index 9a6f552..b7ff10c 100644 --- a/wownero_libwallet2_api_c/src/main/cpp/wownero_checksum.h +++ b/wownero_libwallet2_api_c/src/main/cpp/wownero_checksum.h @@ -1,6 +1,6 @@ #ifndef MONEROC_CHECKSUMS #define MONEROC_CHECKSUMS const char * WOWNERO_wallet2_api_c_h_sha256 = "8a8d386dd5d996c89a0586c55b295ef95ca584bf1ffa26255152b291910a0a77"; -const char * WOWNERO_wallet2_api_c_cpp_sha256 = "ed400bd9c4709383ffd42a9fbe68be37a2a47a42f92eacaf3a2dbd248c422739-e25963cbc11ca0a0fe5eb34b9bd7c72e4f51b795"; +const char * WOWNERO_wallet2_api_c_cpp_sha256 = "28e4d44c565cd7d97d3f18cdd322be48f89dc9fded82fb533af56a8eaa4e0bda-e25963cbc11ca0a0fe5eb34b9bd7c72e4f51b795"; const char * WOWNERO_wallet2_api_c_exp_sha256 = "3673e40e1a7115552276d1d541f6e4d5a0fef47c40fff7b988f49923af84c8a4"; #endif -- cgit v1.2.3 From 3cb38bee9385faf46b03fd73aab85f3ac4115bf7 Mon Sep 17 00:00:00 2001 From: Czarek Nakamoto Date: Wed, 28 Aug 2024 11:08:19 +0200 Subject: std::set -> std::vector --- impls/monero.dart/lib/src/checksum_wownero.dart | 2 +- wownero_libwallet2_api_c/src/main/cpp/wallet2_api_c.cpp | 2 +- wownero_libwallet2_api_c/src/main/cpp/wownero_checksum.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'impls') diff --git a/impls/monero.dart/lib/src/checksum_wownero.dart b/impls/monero.dart/lib/src/checksum_wownero.dart index 8d08889..7d501c6 100644 --- a/impls/monero.dart/lib/src/checksum_wownero.dart +++ b/impls/monero.dart/lib/src/checksum_wownero.dart @@ -1,4 +1,4 @@ // ignore_for_file: constant_identifier_names const String wallet2_api_c_h_sha256 = "8a8d386dd5d996c89a0586c55b295ef95ca584bf1ffa26255152b291910a0a77"; -const String wallet2_api_c_cpp_sha256 = "28e4d44c565cd7d97d3f18cdd322be48f89dc9fded82fb533af56a8eaa4e0bda-e25963cbc11ca0a0fe5eb34b9bd7c72e4f51b795"; +const String wallet2_api_c_cpp_sha256 = "07d67f34a07869aaa4af6ca04e142dbad2fb1fba0e2ebdefd22bc333fd982e25-e25963cbc11ca0a0fe5eb34b9bd7c72e4f51b795"; const String wallet2_api_c_exp_sha256 = "3673e40e1a7115552276d1d541f6e4d5a0fef47c40fff7b988f49923af84c8a4"; diff --git a/wownero_libwallet2_api_c/src/main/cpp/wallet2_api_c.cpp b/wownero_libwallet2_api_c/src/main/cpp/wallet2_api_c.cpp index 2347496..19a14ba 100644 --- a/wownero_libwallet2_api_c/src/main/cpp/wallet2_api_c.cpp +++ b/wownero_libwallet2_api_c/src/main/cpp/wallet2_api_c.cpp @@ -1252,7 +1252,7 @@ void* WOWNERO_Wallet_createTransactionMultDest(void* wallet_ptr, const char* dst uint32_t subaddr_account, const char* preferredInputs, const char* preferredInputs_separator) { Monero::Wallet *wallet = reinterpret_cast(wallet_ptr); - std::set dst_addr = splitStringVector(std::string(dst_addr_list), std::string(dst_addr_list_separator)); + std::vector dst_addr = splitStringVector(std::string(dst_addr_list), std::string(dst_addr_list_separator)); Monero::optional> optAmount; if (!amount_sweep_all) { diff --git a/wownero_libwallet2_api_c/src/main/cpp/wownero_checksum.h b/wownero_libwallet2_api_c/src/main/cpp/wownero_checksum.h index b7ff10c..40723cc 100644 --- a/wownero_libwallet2_api_c/src/main/cpp/wownero_checksum.h +++ b/wownero_libwallet2_api_c/src/main/cpp/wownero_checksum.h @@ -1,6 +1,6 @@ #ifndef MONEROC_CHECKSUMS #define MONEROC_CHECKSUMS const char * WOWNERO_wallet2_api_c_h_sha256 = "8a8d386dd5d996c89a0586c55b295ef95ca584bf1ffa26255152b291910a0a77"; -const char * WOWNERO_wallet2_api_c_cpp_sha256 = "28e4d44c565cd7d97d3f18cdd322be48f89dc9fded82fb533af56a8eaa4e0bda-e25963cbc11ca0a0fe5eb34b9bd7c72e4f51b795"; +const char * WOWNERO_wallet2_api_c_cpp_sha256 = "07d67f34a07869aaa4af6ca04e142dbad2fb1fba0e2ebdefd22bc333fd982e25-e25963cbc11ca0a0fe5eb34b9bd7c72e4f51b795"; const char * WOWNERO_wallet2_api_c_exp_sha256 = "3673e40e1a7115552276d1d541f6e4d5a0fef47c40fff7b988f49923af84c8a4"; #endif -- cgit v1.2.3 From 1e22390f512f97c89b6b4c75da4958c16316da22 Mon Sep 17 00:00:00 2001 From: cyan Date: Wed, 4 Sep 2024 14:57:12 +0200 Subject: fix find wallets (#46) * Update WalletManager_findWallets * prevent crash when there are no wallets found * return List instead of colon separated String --- impls/monero.dart/lib/monero.dart | 11 +++++++---- impls/monero.dart/lib/wownero.dart | 12 +++++++----- 2 files changed, 14 insertions(+), 9 deletions(-) (limited to 'impls') diff --git a/impls/monero.dart/lib/monero.dart b/impls/monero.dart/lib/monero.dart index b30bd3f..997f1b6 100644 --- a/impls/monero.dart/lib/monero.dart +++ b/impls/monero.dart/lib/monero.dart @@ -3585,7 +3585,8 @@ bool WalletManager_verifyWalletPassword( return s; } -String WalletManager_findWallets(WalletManager wm_ptr, {required String path}) { +List WalletManager_findWallets(WalletManager wm_ptr, + {required String path}) { debugStart?.call('MONERO_WalletManager_findWallets'); lib ??= MoneroC(DynamicLibrary.open(libPath)); try { @@ -3595,13 +3596,15 @@ String WalletManager_findWallets(WalletManager wm_ptr, {required String path}) { .cast(); final str = strPtr.toDartString(); calloc.free(path_); - MONERO_free(strPtr.cast()); + if (str.isNotEmpty) { + MONERO_free(strPtr.cast()); + } debugEnd?.call('MONERO_WalletManager_findWallets'); - return str; + return str.split(";"); } catch (e) { errorHandler?.call('MONERO_WalletManager_findWallets', e); debugEnd?.call('MONERO_WalletManager_findWallets'); - return ""; + return []; } } diff --git a/impls/monero.dart/lib/wownero.dart b/impls/monero.dart/lib/wownero.dart index 5a0a288..e87488c 100644 --- a/impls/monero.dart/lib/wownero.dart +++ b/impls/monero.dart/lib/wownero.dart @@ -3220,7 +3220,8 @@ bool WalletManager_verifyWalletPassword( return s; } -String WalletManager_findWallets(WalletManager wm_ptr, {required String path}) { +List WalletManager_findWallets(WalletManager wm_ptr, + {required String path}) { debugStart?.call('WOWNERO_WalletManager_findWallets'); lib ??= WowneroC(DynamicLibrary.open(libPath)); try { @@ -3230,13 +3231,15 @@ String WalletManager_findWallets(WalletManager wm_ptr, {required String path}) { .cast(); final str = strPtr.toDartString(); calloc.free(path_); - WOWNERO_free(strPtr.cast()); + if (str.isNotEmpty) { + WOWNERO_free(strPtr.cast()); + } debugEnd?.call('WOWNERO_WalletManager_findWallets'); - return str; + return str.split(";"); } catch (e) { errorHandler?.call('WOWNERO_WalletManager_findWallets', e); debugEnd?.call('WOWNERO_WalletManager_findWallets'); - return ""; + return []; } } @@ -3606,7 +3609,6 @@ int WOWNERO_deprecated_14WordSeedHeight({ return s; } - String WOWNERO_checksum_wallet2_api_c_h() { debugStart?.call('WOWNERO_checksum_wallet2_api_c_h'); lib ??= WowneroC(DynamicLibrary.open(libPath)); -- cgit v1.2.3 From 4f844740bced43b5653d3152717f8b1e10b13293 Mon Sep 17 00:00:00 2001 From: cyan Date: Sun, 8 Sep 2024 17:52:09 +0200 Subject: use less memory for debugCallLength Map (#48) * use less memory for debugCallLength Map * ignore errors in default debug functions --- impls/monero.dart/lib/monero.dart | 34 ++++++++++++++++++++++++++++------ impls/monero.dart/lib/wownero.dart | 34 ++++++++++++++++++++++++++++------ 2 files changed, 56 insertions(+), 12 deletions(-) (limited to 'impls') diff --git a/impls/monero.dart/lib/monero.dart b/impls/monero.dart/lib/monero.dart index 997f1b6..4fcc970 100644 --- a/impls/monero.dart/lib/monero.dart +++ b/impls/monero.dart/lib/monero.dart @@ -101,14 +101,36 @@ final Stopwatch sw = Stopwatch()..start(); bool printStarts = false; void Function(String call)? debugStart = (call) { - if (printStarts) print("MONERO: $call"); - debugCallLength[call] ??= []; - debugCallLength[call]!.add(sw.elapsedMicroseconds); + try { + if (printStarts) print("MONERO: $call"); + debugCallLength[call] ??= []; + debugCallLength[call]!.add(sw.elapsedMicroseconds); + } catch (e) {} }; +void debugChores() { + for (var key in debugCallLength.keys) { + if (debugCallLength[key]!.length > 1000000) { + final elm = + debugCallLength[key]!.reduce((value, element) => value + element); + debugCallLength[key]!.clear(); + debugCallLength["${key}_1M"] ??= []; + debugCallLength["${key}_1M"]!.add(elm); + } + } +} + +int debugCount = 0; + void Function(String call)? debugEnd = (call) { - final id = debugCallLength[call]!.length - 1; - debugCallLength[call]![id] = - sw.elapsedMicroseconds - debugCallLength[call]![id]; + try { + final id = debugCallLength[call]!.length - 1; + if (++debugCount > 1000000) { + debugCount = 0; + debugChores(); + } + debugCallLength[call]![id] = + sw.elapsedMicroseconds - debugCallLength[call]![id]; + } catch (e) {} }; void Function(String call, dynamic error)? errorHandler = (call, error) { print("$call: $error"); diff --git a/impls/monero.dart/lib/wownero.dart b/impls/monero.dart/lib/wownero.dart index e87488c..d355005 100644 --- a/impls/monero.dart/lib/wownero.dart +++ b/impls/monero.dart/lib/wownero.dart @@ -101,14 +101,36 @@ final Stopwatch sw = Stopwatch()..start(); bool printStarts = false; void Function(String call)? debugStart = (call) { - if (printStarts) print("MONERO: $call"); - debugCallLength[call] ??= []; - debugCallLength[call]!.add(sw.elapsedMicroseconds); + try { + if (printStarts) print("MONERO: $call"); + debugCallLength[call] ??= []; + debugCallLength[call]!.add(sw.elapsedMicroseconds); + } catch (e) {} }; +void debugChores() { + for (var key in debugCallLength.keys) { + if (debugCallLength[key]!.length > 1000000) { + final elm = + debugCallLength[key]!.reduce((value, element) => value + element); + debugCallLength[key]!.clear(); + debugCallLength["${key}_1M"] ??= []; + debugCallLength["${key}_1M"]!.add(elm); + } + } +} + +int debugCount = 0; + void Function(String call)? debugEnd = (call) { - final id = debugCallLength[call]!.length - 1; - debugCallLength[call]![id] = - sw.elapsedMicroseconds - debugCallLength[call]![id]; + try { + final id = debugCallLength[call]!.length - 1; + if (++debugCount > 1000000) { + debugCount = 0; + debugChores(); + } + debugCallLength[call]![id] = + sw.elapsedMicroseconds - debugCallLength[call]![id]; + } catch (e) {} }; void Function(String call, dynamic error)? errorHandler = (call, error) { print("$call: $error"); -- cgit v1.2.3 From 0868b9bc3c4a59ddc5bfff13462e8840cffb7084 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 6 Sep 2024 09:57:39 +0000 Subject: chore(deps): update dependency ffigen to v14 --- impls/monero.dart/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'impls') diff --git a/impls/monero.dart/pubspec.yaml b/impls/monero.dart/pubspec.yaml index 4f48698..d85d600 100644 --- a/impls/monero.dart/pubspec.yaml +++ b/impls/monero.dart/pubspec.yaml @@ -12,4 +12,4 @@ dependencies: dev_dependencies: lints: ^4.0.0 test: ^1.24.0 - ffigen: ^13.0.0 \ No newline at end of file + ffigen: ^14.0.0 \ No newline at end of file -- cgit v1.2.3 From d1940944943cd79ce1f2b2080456dd28bec5c36f Mon Sep 17 00:00:00 2001 From: cyan Date: Thu, 19 Sep 2024 10:59:07 +0200 Subject: feat: deno ffi bindings (#40) * initial ts commit * monero.ts improvements * test on latest, build on debian:bookworm * feat: upstream changes to bindings * chore: update checksums * feat: allow manually loading dylib * chore: add readme * fix: free strings after being read to prevent potential memory leaks * fix: load dylib * fix: checksum checks segfaulting because of freeing const variables --------- Co-authored-by: Mateusz Franik <47059999+Im-Beast@users.noreply.github.com> Co-authored-by: Im-Beast --- .github/workflows/full_check.yaml | 121 ++++++- .vscode/settings.json | 3 + generate_checksum.sh | 14 +- impls/monero.ts/.gitignore | 2 + impls/monero.ts/README.md | 42 +++ impls/monero.ts/checksum.ts | 65 ++++ impls/monero.ts/checksum_monero.ts | 5 + impls/monero.ts/checksum_wownero.ts | 5 + impls/monero.ts/deno.jsonc | 5 + impls/monero.ts/mod.ts | 6 + impls/monero.ts/src/bindings.ts | 562 +++++++++++++++++++++++++++++ impls/monero.ts/src/pending_transaction.ts | 81 +++++ impls/monero.ts/src/transaction_history.ts | 38 ++ impls/monero.ts/src/transaction_info.ts | 104 ++++++ impls/monero.ts/src/utils.ts | 25 ++ impls/monero.ts/src/wallet.ts | 304 ++++++++++++++++ impls/monero.ts/src/wallet_manager.ts | 27 ++ 17 files changed, 1406 insertions(+), 3 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 impls/monero.ts/.gitignore create mode 100644 impls/monero.ts/README.md create mode 100644 impls/monero.ts/checksum.ts create mode 100644 impls/monero.ts/checksum_monero.ts create mode 100644 impls/monero.ts/checksum_wownero.ts create mode 100644 impls/monero.ts/deno.jsonc create mode 100644 impls/monero.ts/mod.ts create mode 100644 impls/monero.ts/src/bindings.ts create mode 100644 impls/monero.ts/src/pending_transaction.ts create mode 100644 impls/monero.ts/src/transaction_history.ts create mode 100644 impls/monero.ts/src/transaction_info.ts create mode 100644 impls/monero.ts/src/utils.ts create mode 100644 impls/monero.ts/src/wallet.ts create mode 100644 impls/monero.ts/src/wallet_manager.ts (limited to 'impls') diff --git a/.github/workflows/full_check.yaml b/.github/workflows/full_check.yaml index a7edcc0..03e6f37 100644 --- a/.github/workflows/full_check.yaml +++ b/.github/workflows/full_check.yaml @@ -137,7 +137,7 @@ jobs: coin: [monero, wownero] runs-on: ubuntu-latest container: - image: debian:bookworm + image: debian:bullseye steps: - name: Install dependencies run: | @@ -698,6 +698,123 @@ jobs: with: name: ${{ matrix.coin }} xmruw apk path: unnamed_monero_wallet/build/app/outputs/flutter-apk/*.apk + bulk_lib_release: + name: create single release file + runs-on: ubuntu-latest + needs: [ + lib_mingw, lib_android, lib_linux, lib_sailfishos_aarch64, lib_sailfishos_i486, lib_darwin, lib_macos, lib_ios + ] + steps: + - uses: actions/download-artifact@v4 + with: + name: android monero + path: release/monero + - uses: actions/download-artifact@v4 + with: + name: android wownero + path: release/wownero + - uses: actions/download-artifact@v4 + with: + name: darwin monero + path: release/monero + - uses: actions/download-artifact@v4 + with: + name: darwin wownero + path: release/wownero + - uses: actions/download-artifact@v4 + with: + name: ios monero + path: release/monero + - uses: actions/download-artifact@v4 + with: + name: ios wownero + path: release/wownero + - uses: actions/download-artifact@v4 + with: + name: linux monero + path: release/monero + - uses: actions/download-artifact@v4 + with: + name: linux wownero + path: release/wownero + - uses: actions/download-artifact@v4 + with: + name: macos monero + path: release/monero + - uses: actions/download-artifact@v4 + with: + name: macos wownero + path: release/wownero + - uses: actions/download-artifact@v4 + with: + name: mingw monero + path: release/monero + - uses: actions/download-artifact@v4 + with: + name: mingw wownero + path: release/wownero + - uses: actions/download-artifact@v4 + with: + name: sfos aarch64 monero + path: release/monero + - uses: actions/download-artifact@v4 + with: + name: sfos aarch64 wownero + path: release/wownero + - uses: actions/download-artifact@v4 + with: + name: sfos_i486 monero + path: release/monero + - uses: actions/download-artifact@v4 + with: + name: sfos_i486 wownero + path: release/wownero + - name: zip release dir + run: zip -r release-bundle.zip release + - name: Release + uses: softprops/action-gh-release@v2 + if: startsWith(github.ref, 'refs/tags/') + with: + files: release-bundle.zip + token: ${{ secrets.CUSTOM_GITHUB_TOKEN }} + - name: Upload lib + uses: actions/upload-artifact@v4 + with: + name: release-bulk + path: release + deno_monerots_test_linux: + name: test ts library + runs-on: ubuntu-24.04 + needs: [ + lib_linux + ] + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + submodules: recursive + - uses: actions/download-artifact@v4 + with: + name: linux monero + path: release/monero + - name: unpack and move monero_c + run: | + unxz -f -k release/*/*.xz + - uses: denoland/setup-deno@v1 + with: + deno-version: vx.x.x + - name: Create symlink + run: | + cd impls/monero.ts + mkdir lib + cd lib + ln -s ../../../release/monero/x86_64-linux-gnu_libwallet2_api_c.so + mv x86_64-linux-gnu_libwallet2_api_c.so monero_libwallet2_api_c.so + cd .. + - name: Run tests + run: | + cd impls/monero.ts + deno run --unstable-ffi --allow-ffi checksum.ts comment_pr: name: comment on pr @@ -752,4 +869,4 @@ jobs: with: issue-number: ${{steps.get_issue_number.outputs.result}} body: | - [download artifacts #${{github.run_id}}](https://nightly.link/MrCyjaneK/monero_c/actions/runs/${{github.run_id}}) (this comment will update whenever you push) \ No newline at end of file + [download artifacts #${{github.run_id}}](https://nightly.link/MrCyjaneK/monero_c/actions/runs/${{github.run_id}}) (this comment will update whenever you push) diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..b943dbc --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "deno.enable": true +} \ No newline at end of file diff --git a/generate_checksum.sh b/generate_checksum.sh index 5847ff5..4b82e53 100755 --- a/generate_checksum.sh +++ b/generate_checksum.sh @@ -1,6 +1,11 @@ #!/bin/bash cd "$(realpath $(dirname $0))" -function sha256sum() { shasum -a 256 "$@" ; } && export -f sha256sum + +if [[ "$(uname)" == "Darwin" ]]; +then + function sha256sum() { shasum -a 256 "$@" ; } && export -f sha256sum +fi + for coin in monero wownero; do submodule_hash=$(git ls-tree HEAD ${coin} | xargs | awk '{ print $3 }') @@ -22,6 +27,13 @@ EOF const String wallet2_api_c_h_sha256 = "${COIN_wallet2_api_c_h_sha256}"; const String wallet2_api_c_cpp_sha256 = "${COIN_wallet2_api_c_cpp_sha256}"; const String wallet2_api_c_exp_sha256 = "${COIN_wallet2_api_c_exp_sha256}"; +EOF + cat > impls/monero.ts/checksum_${coin}.ts << EOF +export const ${coin}Checksum = { + wallet2_api_c_h_sha256: "${COIN_wallet2_api_c_h_sha256}", + wallet2_api_c_cpp_sha256: "${COIN_wallet2_api_c_cpp_sha256}", + wallet2_api_c_exp_sha256: "${COIN_wallet2_api_c_exp_sha256}", +} EOF done diff --git a/impls/monero.ts/.gitignore b/impls/monero.ts/.gitignore new file mode 100644 index 0000000..8b61d3b --- /dev/null +++ b/impls/monero.ts/.gitignore @@ -0,0 +1,2 @@ +*_libwallet2_api_c.* +lib diff --git a/impls/monero.ts/README.md b/impls/monero.ts/README.md new file mode 100644 index 0000000..e3b20f6 --- /dev/null +++ b/impls/monero.ts/README.md @@ -0,0 +1,42 @@ +# monero.ts + +`monero_c` bindings for Deno. + +## Usage + +This library does not ship with `monero_c` libraries.\ +To use these bindings you have to bring your own `monero_c` libraries.\ +There are at least two ways to do so: +- Ahead-of-time, during builds where you only ship necessary library for a given platform.\ + See [monero-tui](https://github.com/Im-Beast/monero-tui/blob/main/.github/workflows/dev-build.yml) build workflow as an example of doing so. + ```ts + import { loadDylib, Wallet, WalletManager } from "https://raw.githubusercontent.com/MrCyjaneK/monero_c/master/impls/monero.ts/mod.ts"; + + // Try to load dylib from the default lib/* path + loadDylib(); + + const wm = await WalletManager.new(); + const wallet = await Wallet.create(wm, "./my_wallet", "password"); + + console.log(await wallet.address()); + + await wallet.store(); + ``` +- Just-in-time, where you download and cache the library at runtime.\ + You can use something like [plug](https://jsr.io/@denosaurs/plug) to achieve the result. + ```ts + import { dlopen } from "jsr:@denosaurs/plug"; + // It's recommened to put the monero.ts github link into your import_map to reduce the url clutter + import { loadDylib, symbols, Wallet, WalletManager } from "https://raw.githubusercontent.com/MrCyjaneK/monero_c/master/impls/monero.ts/mod.ts"; + + // Load dylib loaded by plug + const lib = await dlopen(..., symbols); + loadDylib(lib); + + const wm = await WalletManager.new(); + const wallet = await Wallet.create(wm, "./my_wallet", "password"); + + console.log(await wallet.address()); + + await wallet.store(); + ``` diff --git a/impls/monero.ts/checksum.ts b/impls/monero.ts/checksum.ts new file mode 100644 index 0000000..22d3038 --- /dev/null +++ b/impls/monero.ts/checksum.ts @@ -0,0 +1,65 @@ +import { moneroChecksum } from "./checksum_monero.ts"; +import { readCString } from "./src/utils.ts"; +import { dylib, loadDylib } from "./src/bindings.ts"; + +loadDylib(); + +export class ChecksumError extends Error { + readonly code: number; + readonly errors: string[]; + + constructor(code: number, errors: string[]) { + super("MoneroC binding checksum failed:\n" + errors.join("\n")); + this.code = code; + this.errors = errors; + } +} + +/** + * Validates MoneroC checksums + * @returns {null} if checksums are correct + * @returns {ChecksumError} which contains information about why checksum failed + */ +export async function validateChecksum(): Promise { + const cppHeaderHash = await readCString(await dylib.symbols.MONERO_checksum_wallet2_api_c_h(), false); + const tsHeaderHash = moneroChecksum.wallet2_api_c_h_sha256; + + const errors: string[] = []; + + let errorCode = 0; + if (cppHeaderHash !== tsHeaderHash) { + errors.push("ERR: Header file check mismatch"); + errorCode++; + } + + const cppSourceHash = await readCString(await dylib.symbols.MONERO_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 dylib.symbols.MONERO_checksum_wallet2_api_c_exp(), false); + const tsExportHash = moneroChecksum.wallet2_api_c_exp_sha256; + if (cppExportHash !== tsExportHash) { + if (Deno.build.os !== "darwin") { + errors.push("WARN: EXP source file check mismatch"); + } else { + errors.push(`ERR: EXP source file check mismatch ${cppExportHash} == ${tsExportHash}`); + } + errorCode++; + } + + if (errorCode) { + return new ChecksumError(errorCode, errors); + } + + return null; +} + +if (import.meta.main) { + const maybeError = await validateChecksum(); + if (maybeError) { + throw maybeError; + } +} diff --git a/impls/monero.ts/checksum_monero.ts b/impls/monero.ts/checksum_monero.ts new file mode 100644 index 0000000..88406a0 --- /dev/null +++ b/impls/monero.ts/checksum_monero.ts @@ -0,0 +1,5 @@ +export const moneroChecksum = { + wallet2_api_c_h_sha256: "e8db0ef0324a153f5e3ecca4c0db23c54f4576e84988f04bd4f11c1142f9d7ad", + wallet2_api_c_cpp_sha256: "dca52ac9ee009fda9fb5726543a454885e61d8eb74fb33112288029ed625bec5-b089f9ee69924882c5d14dd1a6991deb05d9d1cd", + wallet2_api_c_exp_sha256: "c8913ac41068f67b57c9b0a3c7dd8973e3c1273b66c2ff0aadb0003931da748c", +} diff --git a/impls/monero.ts/checksum_wownero.ts b/impls/monero.ts/checksum_wownero.ts new file mode 100644 index 0000000..8b2899c --- /dev/null +++ b/impls/monero.ts/checksum_wownero.ts @@ -0,0 +1,5 @@ +export const wowneroChecksum = { + wallet2_api_c_h_sha256: "8a8d386dd5d996c89a0586c55b295ef95ca584bf1ffa26255152b291910a0a77", + wallet2_api_c_cpp_sha256: "07d67f34a07869aaa4af6ca04e142dbad2fb1fba0e2ebdefd22bc333fd982e25-e25963cbc11ca0a0fe5eb34b9bd7c72e4f51b795", + wallet2_api_c_exp_sha256: "3673e40e1a7115552276d1d541f6e4d5a0fef47c40fff7b988f49923af84c8a4", +} diff --git a/impls/monero.ts/deno.jsonc b/impls/monero.ts/deno.jsonc new file mode 100644 index 0000000..a7b75ec --- /dev/null +++ b/impls/monero.ts/deno.jsonc @@ -0,0 +1,5 @@ +{ + "fmt": { + "lineWidth": 120 + } +} diff --git a/impls/monero.ts/mod.ts b/impls/monero.ts/mod.ts new file mode 100644 index 0000000..1eca773 --- /dev/null +++ b/impls/monero.ts/mod.ts @@ -0,0 +1,6 @@ +export * from "./src/bindings.ts"; +export * from "./src/pending_transaction.ts"; +export * from "./src/transaction_history.ts"; +export * from "./src/transaction_info.ts"; +export * from "./src/wallet.ts"; +export * from "./src/wallet_manager.ts"; diff --git a/impls/monero.ts/src/bindings.ts b/impls/monero.ts/src/bindings.ts new file mode 100644 index 0000000..b854f7d --- /dev/null +++ b/impls/monero.ts/src/bindings.ts @@ -0,0 +1,562 @@ +export const symbols = { + "MONERO_WalletManagerFactory_getWalletManager": { + nonblocking: true, + parameters: [], + // void* + result: "pointer", + }, + + //#region WalletManager + "MONERO_WalletManager_createWallet": { + nonblocking: true, + // void* wm_ptr, const char* path, const char* password, const char* language, int networkType + parameters: ["pointer", "pointer", "pointer", "pointer", "i32"], + // void* + result: "pointer", + }, + "MONERO_WalletManager_openWallet": { + nonblocking: true, + // void* wm_ptr, const char* path, const char* password, int networkType + "parameters": ["pointer", "pointer", "pointer", "i32"], + // void* + result: "pointer", + }, + "MONERO_WalletManager_recoveryWallet": { + nonblocking: true, + // void* wm_ptr, const char* path, const char* password, const char* mnemonic, + // int networkType, uint64_t restoreHeight, uint64_t kdfRounds, const char* seedOffset + parameters: ["pointer", "pointer", "pointer", "pointer", "i32", "u64", "u64", "pointer"], + // void* + result: "pointer", + }, + "MONERO_WalletManager_blockchainHeight": { + nonblocking: true, + // void* wm_ptr + parameters: ["pointer"], + // uint64_t + result: "u64", + }, + "MONERO_WalletManager_blockchainTargetHeight": { + nonblocking: true, + // void* wm_ptr + parameters: ["pointer"], + // uint64_t + result: "u64", + }, + "MONERO_WalletManager_setDaemonAddress": { + nonblocking: true, + // void* wm_ptr, const char* address + parameters: ["pointer", "pointer"], + // void + result: "void", + }, + //#endregion + + //#region Wallet + "MONERO_Wallet_init": { + nonblocking: true, + // void* wallet_ptr, const char* daemon_address, uint64_t upper_transaction_size_limit, + // const char* daemon_username, const char* daemon_password, bool use_ssl, bool lightWallet, + // const char* proxy_address + parameters: ["pointer", "pointer", "u64", "pointer", "pointer", "bool", "bool", "pointer"], + // bool + result: "bool", + }, + "MONERO_Wallet_init3": { + nonblocking: true, + // void* wallet_ptr, const char* argv0, const char* default_log_base_name, + // const char* log_path, bool console + parameters: ["pointer", "pointer", "pointer", "pointer", "bool"], + // void + result: "void", + }, + "MONERO_Wallet_setTrustedDaemon": { + nonblocking: true, + // void* wallet_ptr, bool arg + parameters: ["pointer", "bool"], + // void + result: "void", + }, + "MONERO_Wallet_startRefresh": { + nonblocking: true, + // void* wallet_ptr + parameters: ["pointer"], + // void + result: "void", + }, + "MONERO_Wallet_refreshAsync": { + nonblocking: true, + // void* wallet_ptr + parameters: ["pointer"], + // void + result: "void", + }, + "MONERO_Wallet_blockChainHeight": { + nonblocking: true, + // void* wallet_ptr + parameters: ["pointer"], + // uint64_t + result: "u64", + }, + "MONERO_Wallet_daemonBlockChainHeight": { + nonblocking: true, + // void* wallet_ptr + parameters: ["pointer"], + // uint64_t + result: "u64", + }, + "MONERO_Wallet_synchronized": { + nonblocking: true, + // void* wallet_ptr + parameters: ["pointer"], + // bool + result: "bool", + }, + "MONERO_Wallet_store": { + nonblocking: true, + // void* wallet_ptr, const char* path + parameters: ["pointer", "pointer"], + // bool + result: "bool", + }, + "MONERO_Wallet_address": { + nonblocking: true, + // void* wallet_ptr, uint64_t accountIndex, uint64_t addressIndex + parameters: ["pointer", "u64", "u64"], + // char* + result: "pointer", + }, + "MONERO_Wallet_balance": { + nonblocking: true, + // void* wallet_ptr, uint32_t accountIndex + parameters: ["pointer", "u32"], + // uint64_t + result: "u64", + }, + "MONERO_Wallet_unlockedBalance": { + nonblocking: true, + // void* wallet_ptr, uint32_t accountIndex + parameters: ["pointer", "u32"], + // uint64_t + result: "u64", + }, + "MONERO_Wallet_addSubaddressAccount": { + nonblocking: true, + // void* wallet_ptr, const char* label + parameters: ["pointer", "pointer"], + // void + result: "void", + }, + "MONERO_Wallet_numSubaddressAccounts": { + nonblocking: true, + // void* wallet_ptr + parameters: ["pointer"], + // size_t + result: "usize", + }, + "MONERO_Wallet_addSubaddress": { + nonblocking: true, + // void* wallet_ptr, uint32_t accountIndex, const char* label + parameters: ["pointer", "u32", "pointer"], + // void + result: "void", + }, + "MONERO_Wallet_numSubaddresses": { + nonblocking: true, + // void* wallet_ptr, uint32_t accountIndex + parameters: ["pointer", "u32"], + // size_t + result: "usize", + }, + "MONERO_Wallet_getSubaddressLabel": { + nonblocking: true, + // void* wallet_ptr, uint32_t accountIndex, uint32_t addressIndex + parameters: ["pointer", "u32", "u32"], + // const char* + result: "pointer", + }, + "MONERO_Wallet_setSubaddressLabel": { + nonblocking: true, + // void* wallet_ptr, uint32_t accountIndex, uint32_t addressIndex, const char* label + parameters: ["pointer", "u32", "u32", "pointer"], + // void + result: "void", + }, + "MONERO_Wallet_status": { + nonblocking: true, + // void* wallet_ptr + parameters: ["pointer"], + // int + result: "i32", + }, + "MONERO_Wallet_errorString": { + nonblocking: true, + // void* wallet_ptr + parameters: ["pointer"], + // char* + result: "pointer", + }, + "MONERO_Wallet_history": { + nonblocking: true, + // void* wallet_ptr + parameters: ["pointer"], + // void* + result: "pointer", + }, + "MONERO_Wallet_createTransaction": { + nonblocking: true, + // void* wallet_ptr, const char* dst_addr, const char* payment_id + // uint64_t amount, uint32_t mixin_count, int pendingTransactionPriority, + // uint32_t subaddr_account, const char* preferredInputs, const char* separator + parameters: ["pointer", "pointer", "pointer", "u64", "u32", "i32", "u32", "pointer", "pointer"], + // void* + result: "pointer", + }, + "MONERO_Wallet_amountFromString": { + nonblocking: true, + // const char* amount + parameters: ["pointer"], + // uint64_t + result: "u64", + }, + //#endregion + + //#region TransactionHistory + "MONERO_TransactionHistory_count": { + nonblocking: true, + // void* txHistory_ptr + parameters: ["pointer"], + // int + result: "i32", + }, + "MONERO_TransactionHistory_transaction": { + nonblocking: true, + // void* txHistory_ptr, int index + parameters: ["pointer", "i32"], + // void* + result: "pointer", + }, + "MONERO_TransactionHistory_transactionById": { + nonblocking: true, + // void* txHistory_ptr, const char* id + parameters: ["pointer", "pointer"], + // void* + result: "pointer", + }, + "MONERO_TransactionHistory_refresh": { + nonblocking: true, + // void* txHistory_ptr + parameters: ["pointer"], + // void + result: "void", + }, + "MONERO_TransactionHistory_setTxNote": { + nonblocking: true, + // void* txHistory_ptr, const char* txid, const char* note + parameters: ["pointer", "pointer", "pointer"], + // void + result: "void", + }, + //#endregion + + //#region TransactionInfo + "MONERO_TransactionInfo_direction": { + nonblocking: true, + // void* txInfo_ptr + parameters: ["pointer"], + // int + result: "i32", + }, + "MONERO_TransactionInfo_isPending": { + nonblocking: true, + // void* txInfo_ptr + parameters: ["pointer"], + // bool + result: "bool", + }, + "MONERO_TransactionInfo_isFailed": { + nonblocking: true, + // void* txInfo_ptr + parameters: ["pointer"], + // bool + result: "bool", + }, + "MONERO_TransactionInfo_isCoinbase": { + nonblocking: true, + // void* txInfo_ptr + parameters: ["pointer"], + // bool + result: "bool", + }, + "MONERO_TransactionInfo_amount": { + nonblocking: true, + // void* txInfo_ptr + parameters: ["pointer"], + // uint64_t + result: "u64", + }, + "MONERO_TransactionInfo_fee": { + nonblocking: true, + // void* txInfo_ptr + parameters: ["pointer"], + // uint64_t + result: "u64", + }, + "MONERO_TransactionInfo_blockHeight": { + nonblocking: true, + // void* txInfo_ptr + parameters: ["pointer"], + // uint64_t + result: "u64", + }, + "MONERO_TransactionInfo_description": { + nonblocking: true, + // void* txInfo_ptr + parameters: ["pointer"], + // const char* + result: "pointer", + }, + "MONERO_TransactionInfo_subaddrIndex": { + nonblocking: true, + // void* txInfo_ptr + parameters: ["pointer"], + // const char* + result: "pointer", + }, + "MONERO_TransactionInfo_subaddrAccount": { + nonblocking: true, + // void* txInfo_ptr + parameters: ["pointer"], + // uint32_t + result: "u32", + }, + "MONERO_TransactionInfo_label": { + nonblocking: true, + // void* txInfo_ptr + parameters: ["pointer"], + // const char* + result: "pointer", + }, + "MONERO_TransactionInfo_confirmations": { + nonblocking: true, + // void* txInfo_ptr + parameters: ["pointer"], + // uint64_t + result: "u64", + }, + "MONERO_TransactionInfo_unlockTime": { + nonblocking: true, + // void* txInfo_ptr + parameters: ["pointer"], + // uint64_t + result: "u64", + }, + "MONERO_TransactionInfo_hash": { + nonblocking: true, + // void* txInfo_ptr + parameters: ["pointer"], + // const char* + result: "pointer", + }, + "MONERO_TransactionInfo_timestamp": { + nonblocking: true, + // void* txInfo_ptr + parameters: ["pointer"], + // uint64_t + result: "u64", + }, + "MONERO_TransactionInfo_paymentId": { + nonblocking: true, + // void* txInfo_ptr + parameters: ["pointer"], + // const char* + result: "pointer", + }, + "MONERO_TransactionInfo_transfers_count": { + nonblocking: true, + // void* txInfo_ptr + parameters: ["pointer"], + // int + result: "i32", + }, + "MONERO_TransactionInfo_transfers_amount": { + nonblocking: true, + // void* txInfo_ptr, int index + parameters: ["pointer", "i32"], + // uint64_t + result: "u64", + }, + "MONERO_TransactionInfo_transfers_address": { + nonblocking: true, + // void* txInfo_ptr, int index + parameters: ["pointer", "i32"], + // const char* + result: "pointer", + }, + //#endregion + + //#region PendingTransaction + "MONERO_PendingTransaction_status": { + nonblocking: true, + // void* pendingTx_ptr + parameters: ["pointer"], + // int + result: "i32", + }, + "MONERO_PendingTransaction_errorString": { + nonblocking: true, + // void* pendingTx_ptr + parameters: ["pointer"], + // const char* + result: "pointer", + }, + "MONERO_PendingTransaction_commit": { + nonblocking: true, + // void* pendingTx_ptr, const char* filename, bool overwrite + parameters: ["pointer", "pointer", "bool"], + // bool + result: "bool", + }, + "MONERO_PendingTransaction_commitUR": { + nonblocking: true, + // void* pendingTx_ptr, int max_fragment_length + parameters: ["pointer", "i32"], + // const char* + result: "pointer", + }, + "MONERO_PendingTransaction_amount": { + nonblocking: true, + // void* pendingTx_ptr + parameters: ["pointer"], + // uint64_t + result: "u64", + }, + "MONERO_PendingTransaction_dust": { + nonblocking: true, + // void* pendingTx_ptr + parameters: ["pointer"], + // uint64_t + result: "u64", + }, + "MONERO_PendingTransaction_fee": { + nonblocking: true, + // void* pendingTx_ptr + parameters: ["pointer"], + // uint64_t + result: "u64", + }, + "MONERO_PendingTransaction_txid": { + nonblocking: true, + // void* pendingTx_ptr, const char* separator + parameters: ["pointer", "pointer"], + // const char* + result: "pointer", + }, + "MONERO_PendingTransaction_txCount": { + nonblocking: true, + // void* pendingTx_ptr + parameters: ["pointer"], + // uint64_t + result: "u64", + }, + "MONERO_PendingTransaction_subaddrAccount": { + nonblocking: true, + // void* pendingTx_ptr, const char* separator + parameters: ["pointer", "pointer"], + // const char* + result: "pointer", + }, + "MONERO_PendingTransaction_subaddrIndices": { + nonblocking: true, + // void* pendingTx_ptr, const char* separator + parameters: ["pointer", "pointer"], + // const char* + result: "pointer", + }, + "MONERO_PendingTransaction_multisigSignData": { + nonblocking: true, + // void* pendingTx_ptr + parameters: ["pointer"], + // const char* + result: "pointer", + }, + "MONERO_PendingTransaction_signMultisigTx": { + nonblocking: true, + // void* pendingTx_ptr + parameters: ["pointer"], + // void + result: "void", + }, + "MONERO_PendingTransaction_signersKeys": { + nonblocking: true, + // void* pendingTx_ptr + parameters: ["pointer"], + // const char* + result: "pointer", + }, + "MONERO_PendingTransaction_hex": { + nonblocking: true, + // void* pendingTx_ptr, const char* separator + parameters: ["pointer", "pointer"], + // const char* + result: "pointer", + }, + //#endregion + + //#region Checksum + "MONERO_checksum_wallet2_api_c_h": { + nonblocking: true, + parameters: [], + // const char* + result: "pointer", + }, + "MONERO_checksum_wallet2_api_c_cpp": { + nonblocking: true, + parameters: [], + // const char* + result: "pointer", + }, + "MONERO_checksum_wallet2_api_c_exp": { + nonblocking: true, + parameters: [], + // const char* + result: "pointer", + }, + //#endregion + + "MONERO_free": { + nonblocking: true, + // void* ptr + parameters: ["pointer"], + // void + result: "void", + }, +} as const; + +type MoneroTsDylib = Deno.DynamicLibrary; + +export let dylib: MoneroTsDylib; +export function loadDylib(newDylib?: MoneroTsDylib) { + if (newDylib) { + dylib = newDylib; + return; + } + + let libPath: string; + switch (Deno.build.os) { + case "darwin": + libPath = "./lib/monero_libwallet2_api_c.dylib"; + break; + case "android": + libPath = "./lib/libmonero_libwallet2_api_c.so"; + break; + case "windows": + libPath = "./lib/monero_libwallet2_api_c.dll"; + break; + default: + libPath = "./lib/monero_libwallet2_api_c.so"; + break; + } + + dylib = Deno.dlopen(libPath, symbols); +} diff --git a/impls/monero.ts/src/pending_transaction.ts b/impls/monero.ts/src/pending_transaction.ts new file mode 100644 index 0000000..cf48721 --- /dev/null +++ b/impls/monero.ts/src/pending_transaction.ts @@ -0,0 +1,81 @@ +import { dylib } from "./bindings.ts"; +import { CString, readCString, type Sanitizer } from "./utils.ts"; + +export type PendingTransactionPtr = Deno.PointerObject<"transactionInfo">; + +export class PendingTransaction { + #pendingTxPtr: PendingTransactionPtr; + sanitizer?: Sanitizer; + + constructor(pendingTxPtr: PendingTransactionPtr, sanitizer?: Sanitizer) { + this.sanitizer = sanitizer; + this.#pendingTxPtr = pendingTxPtr; + } + + async status(): Promise { + return await dylib.symbols.MONERO_PendingTransaction_status(this.#pendingTxPtr); + } + + async errorString(): Promise { + if (!await this.status()) return null; + + const error = await dylib.symbols.MONERO_PendingTransaction_errorString(this.#pendingTxPtr); + if (!error) return null; + + return await readCString(error) || null; + } + + async throwIfError(sanitize = true): Promise { + const maybeError = await this.errorString(); + if (maybeError) { + if (sanitize) this.sanitizer?.(); + throw new Error(maybeError); + } + } + + async commit(fileName: string, overwrite: boolean, sanitize = true): Promise { + const bool = await dylib.symbols.MONERO_PendingTransaction_commit( + this.#pendingTxPtr, + CString(fileName), + overwrite, + ); + await this.throwIfError(sanitize); + return bool; + } + + async commitUR(maxFragmentLength: number): Promise { + const result = await dylib.symbols.MONERO_PendingTransaction_commitUR( + this.#pendingTxPtr, + maxFragmentLength, + ); + if (!result) return null; + await this.throwIfError(); + return await readCString(result) || null; + } + + async amount(): Promise { + return await dylib.symbols.MONERO_PendingTransaction_amount(this.#pendingTxPtr); + } + + async dust(): Promise { + return await dylib.symbols.MONERO_PendingTransaction_dust(this.#pendingTxPtr); + } + + async fee(): Promise { + return await dylib.symbols.MONERO_PendingTransaction_fee(this.#pendingTxPtr); + } + + async txid(separator: string, sanitize = true): Promise { + const result = await dylib.symbols.MONERO_PendingTransaction_txid( + this.#pendingTxPtr, + CString(separator), + ); + if (!result) return null; + await this.throwIfError(sanitize); + return await readCString(result) || null; + } + + async txCount(): Promise { + return await dylib.symbols.MONERO_PendingTransaction_txCount(this.#pendingTxPtr); + } +} diff --git a/impls/monero.ts/src/transaction_history.ts b/impls/monero.ts/src/transaction_history.ts new file mode 100644 index 0000000..cc76fc2 --- /dev/null +++ b/impls/monero.ts/src/transaction_history.ts @@ -0,0 +1,38 @@ +import { dylib } from "./bindings.ts"; +import { TransactionInfo, TransactionInfoPtr } from "./transaction_info.ts"; +import { CString } from "./utils.ts"; + +export type TransactionHistoryPtr = Deno.PointerObject<"transactionHistory">; + +export class TransactionHistory { + #txHistoryPtr: TransactionHistoryPtr; + + constructor(txHistoryPtr: TransactionHistoryPtr) { + this.#txHistoryPtr = txHistoryPtr; + } + + async count(): Promise { + return await dylib.symbols.MONERO_TransactionHistory_count(this.#txHistoryPtr); + } + + async transaction(index: number): Promise { + return new TransactionInfo( + (await dylib.symbols.MONERO_TransactionHistory_transaction( + this.#txHistoryPtr, + index, + )) as TransactionInfoPtr, + ); + } + + async refresh(): Promise { + await dylib.symbols.MONERO_TransactionHistory_refresh(this.#txHistoryPtr); + } + + async setTxNote(transactionId: string, note: string): Promise { + await dylib.symbols.MONERO_TransactionHistory_setTxNote( + this.#txHistoryPtr, + CString(transactionId), + CString(note), + ); + } +} diff --git a/impls/monero.ts/src/transaction_info.ts b/impls/monero.ts/src/transaction_info.ts new file mode 100644 index 0000000..7db45f5 --- /dev/null +++ b/impls/monero.ts/src/transaction_info.ts @@ -0,0 +1,104 @@ +import { dylib } from "./bindings.ts"; +import { readCString, Sanitizer } from "./utils.ts"; + +export type TransactionInfoPtr = Deno.PointerObject<"transactionInfo">; + +export class TransactionInfo { + #txInfoPtr: TransactionInfoPtr; + sanitizer?: Sanitizer; + + constructor(txInfoPtr: TransactionInfoPtr, sanitizer?: Sanitizer) { + this.#txInfoPtr = txInfoPtr; + this.sanitizer = sanitizer; + } + + async direction(): Promise<"in" | "out"> { + switch (await dylib.symbols.MONERO_TransactionInfo_direction(this.#txInfoPtr)) { + case 0: + return "in"; + case 1: + return "out"; + default: + await this.sanitizer?.(); + throw new Error("Invalid TransactionInfo direction"); + } + } + + async isPending(): Promise { + return await dylib.symbols.MONERO_TransactionInfo_isPending(this.#txInfoPtr); + } + + async isFailed(): Promise { + return await dylib.symbols.MONERO_TransactionInfo_isFailed(this.#txInfoPtr); + } + + async isCoinbase(): Promise { + return await dylib.symbols.MONERO_TransactionInfo_isCoinbase(this.#txInfoPtr); + } + + async amount(): Promise { + return await dylib.symbols.MONERO_TransactionInfo_amount(this.#txInfoPtr); + } + + async fee(): Promise { + return await dylib.symbols.MONERO_TransactionInfo_fee(this.#txInfoPtr); + } + + async blockHeight(): Promise { + return await dylib.symbols.MONERO_TransactionInfo_blockHeight(this.#txInfoPtr); + } + + async description(): Promise { + const description = await dylib.symbols.MONERO_TransactionInfo_description(this.#txInfoPtr); + return await readCString(description) || ""; + } + + async subaddrIndex(): Promise { + const subaddrIndex = await dylib.symbols.MONERO_TransactionInfo_subaddrIndex(this.#txInfoPtr); + return await readCString(subaddrIndex) || ""; + } + + async subaddrAccount(): Promise { + return await dylib.symbols.MONERO_TransactionInfo_subaddrAccount(this.#txInfoPtr); + } + + async label(): Promise { + const label = await dylib.symbols.MONERO_TransactionInfo_label(this.#txInfoPtr); + return await readCString(label) || ""; + } + + async confirmations(): Promise { + return await dylib.symbols.MONERO_TransactionInfo_confirmations(this.#txInfoPtr); + } + + async unlockTime(): Promise { + return await dylib.symbols.MONERO_TransactionInfo_unlockTime(this.#txInfoPtr); + } + + async hash(): Promise { + const hash = await dylib.symbols.MONERO_TransactionInfo_hash(this.#txInfoPtr); + return await readCString(hash) || ""; + } + + async timestamp(): Promise { + return await dylib.symbols.MONERO_TransactionInfo_timestamp(this.#txInfoPtr); + } + + async paymentId(): Promise { + const paymentId = await dylib.symbols.MONERO_TransactionInfo_paymentId(this.#txInfoPtr); + return await readCString(paymentId) || ""; + } + + async transfersCount(): Promise { + return await dylib.symbols.MONERO_TransactionInfo_transfers_count(this.#txInfoPtr); + } + + async transfersAmount(index: number): Promise { + return await dylib.symbols.MONERO_TransactionInfo_transfers_amount(this.#txInfoPtr, index); + } + + async transfersAddress(index: number): Promise { + const transfersAddress = await dylib.symbols.MONERO_TransactionInfo_transfers_address(this.#txInfoPtr, index); + return await readCString(transfersAddress) || ""; + } +} diff --git a/impls/monero.ts/src/utils.ts b/impls/monero.ts/src/utils.ts new file mode 100644 index 0000000..6fa640f --- /dev/null +++ b/impls/monero.ts/src/utils.ts @@ -0,0 +1,25 @@ +import { dylib } from "../mod.ts"; + +export type Sanitizer = () => void | PromiseLike; + +const textEncoder = new TextEncoder(); +export function CString(string: string): Deno.PointerValue { + return Deno.UnsafePointer.of(textEncoder.encode(`${string}\x00`)); +} + +/** + * This method reads string from the given pointer and frees the string. + * + * SAFETY: Do not use readCString twice on the same pointer as it will cause double free\ + * If you want to read CString without freeing it set the {@linkcode free} parameter to false + */ +export async function readCString(pointer: Deno.PointerObject, free?: boolean): Promise; +export async function readCString(pointer: Deno.PointerValue, free?: boolean): Promise; +export async function readCString(pointer: Deno.PointerValue, free = true): Promise { + if (!pointer) return null; + const string = new Deno.UnsafePointerView(pointer).getCString(); + if (free) { + await dylib.symbols.MONERO_free(pointer); + } + return string; +} diff --git a/impls/monero.ts/src/wallet.ts b/impls/monero.ts/src/wallet.ts new file mode 100644 index 0000000..07c40ce --- /dev/null +++ b/impls/monero.ts/src/wallet.ts @@ -0,0 +1,304 @@ +import { dylib } from "./bindings.ts"; +import { CString, readCString, Sanitizer } from "./utils.ts"; +import { WalletManager, type WalletManagerPtr } from "./wallet_manager.ts"; +import { TransactionHistory, TransactionHistoryPtr } from "./transaction_history.ts"; + +import { PendingTransaction } from "./pending_transaction.ts"; +import { PendingTransactionPtr } from "./pending_transaction.ts"; + +export type WalletPtr = Deno.PointerObject<"walletManager">; + +export class Wallet { + #walletManagerPtr: WalletManagerPtr; + #walletPtr: WalletPtr; + sanitizer?: Sanitizer; + + constructor(walletManagerPtr: WalletManager, walletPtr: WalletPtr, sanitizer?: Sanitizer) { + this.#walletPtr = walletPtr; + this.#walletManagerPtr = walletManagerPtr.getPointer(); + this.sanitizer = sanitizer; + } + + async store(path = ""): Promise { + const bool = await dylib.symbols.MONERO_Wallet_store(this.#walletPtr, CString(path)); + await this.throwIfError(); + return bool; + } + + async initWallet(): Promise { + await this.init(); + await this.setTrustedDaemon(true); + await this.setDaemonAddress("http://nodex.monerujo.io:18081"); + await this.startRefresh(); + await this.refreshAsync(); + await this.throwIfError(); + } + + async setDaemonAddress(address: string): Promise { + await dylib.symbols.MONERO_WalletManager_setDaemonAddress( + this.#walletManagerPtr, + CString(address), + ); + } + + async startRefresh(): Promise { + await dylib.symbols.MONERO_Wallet_startRefresh(this.#walletPtr); + await this.throwIfError(); + } + + async refreshAsync(): Promise { + await dylib.symbols.MONERO_Wallet_refreshAsync(this.#walletPtr); + await this.throwIfError(); + } + + async init(): Promise { + const bool = await dylib.symbols.MONERO_Wallet_init( + this.#walletPtr, + CString("http://nodex.monerujo.io:18081"), + 0n, + CString(""), + CString(""), + false, + false, + CString(""), + ); + await this.throwIfError(); + return bool; + } + + async setTrustedDaemon(value: boolean): Promise { + await dylib.symbols.MONERO_Wallet_setTrustedDaemon(this.#walletPtr, value); + } + + static async create( + walletManager: WalletManager, + path: string, + password: string, + sanitizeError = true, + ): Promise { + // We assign holder of the pointer in Wallet constructor + const walletManagerPtr = walletManager.getPointer(); + + const walletPtr = await dylib.symbols.MONERO_WalletManager_createWallet( + walletManagerPtr, + CString(path), + CString(password), + CString("English"), + 0, + ); + + const wallet = new Wallet(walletManager, walletPtr as WalletPtr, walletManager.sanitizer); + await wallet.throwIfError(sanitizeError); + await wallet.initWallet(); + + return wallet; + } + + static async open( + walletManager: WalletManager, + path: string, + password: string, + sanitizeError = true, + ): Promise { + // We assign holder of the pointer in Wallet constructor + const walletManagerPtr = walletManager.getPointer(); + + const walletPtr = await dylib.symbols.MONERO_WalletManager_openWallet( + walletManagerPtr, + CString(path), + CString(password), + 0, + ); + + const wallet = new Wallet(walletManager, walletPtr as WalletPtr, walletManager.sanitizer); + await wallet.throwIfError(sanitizeError); + await wallet.initWallet(); + + return wallet; + } + + static async recover( + walletManager: WalletManager, + path: string, + password: string, + mnemonic: string, + restoreHeight: bigint, + seedOffset: string = "", + sanitizeError = true, + ): Promise { + // We assign holder of the pointer in Wallet constructor + const walletManagerPtr = walletManager.getPointer(); + + const walletPtr = await dylib.symbols.MONERO_WalletManager_recoveryWallet( + walletManagerPtr, + CString(path), + CString(password), + CString(mnemonic), + 0, + restoreHeight, + 1n, + CString(seedOffset), + ); + + const wallet = new Wallet(walletManager, walletPtr as WalletPtr, walletManager.sanitizer); + await wallet.throwIfError(sanitizeError); + await wallet.initWallet(); + + return wallet; + } + + async address(accountIndex = 0n, addressIndex = 0n): Promise { + const address = await dylib.symbols.MONERO_Wallet_address(this.#walletPtr, accountIndex, addressIndex); + if (!address) { + const error = await this.errorString(); + throw new Error(`Failed getting address from a wallet: ${error ?? ""}`); + } + return await readCString(address); + } + + async balance(accountIndex = 0): Promise { + return await dylib.symbols.MONERO_Wallet_balance(this.#walletPtr, accountIndex); + } + + async unlockedBalance(accountIndex = 0): Promise { + return await dylib.symbols.MONERO_Wallet_unlockedBalance(this.#walletPtr, accountIndex); + } + + status(): Promise { + return dylib.symbols.MONERO_Wallet_status(this.#walletPtr); + } + + async errorString(): Promise { + if (!await this.status()) return null; + + const error = await dylib.symbols.MONERO_Wallet_errorString(this.#walletPtr); + if (!error) return null; + + return await readCString(error) || null; + } + + async throwIfError(sanitize = true): Promise { + const maybeError = await this.errorString(); + if (maybeError) { + if (sanitize) this.sanitizer?.(); + throw new Error(maybeError); + } + } + + async synchronized(): Promise { + const synchronized = await dylib.symbols.MONERO_Wallet_synchronized(this.#walletPtr); + await this.throwIfError(); + return synchronized; + } + + async blockChainHeight(): Promise { + const height = await dylib.symbols.MONERO_Wallet_blockChainHeight(this.#walletPtr); + await this.throwIfError(); + return height; + } + + async daemonBlockChainHeight(): Promise { + const height = await dylib.symbols.MONERO_Wallet_daemonBlockChainHeight(this.#walletPtr); + await this.throwIfError(); + return height; + } + + async managerBlockChainHeight(): Promise { + const height = await dylib.symbols.MONERO_WalletManager_blockchainHeight(this.#walletManagerPtr); + await this.throwIfError(); + return height; + } + + async managerTargetBlockChainHeight(): Promise { + const height = await dylib.symbols.MONERO_WalletManager_blockchainTargetHeight(this.#walletManagerPtr); + await this.throwIfError(); + return height; + } + + async addSubaddressAccount(label: string): Promise { + await dylib.symbols.MONERO_Wallet_addSubaddressAccount( + this.#walletPtr, + CString(label), + ); + await this.throwIfError(); + } + + async numSubaddressAccounts(): Promise { + const accountsLen = await dylib.symbols.MONERO_Wallet_numSubaddressAccounts(this.#walletPtr); + await this.throwIfError(); + return accountsLen; + } + + async addSubaddress(accountIndex: number, label: string): Promise { + await dylib.symbols.MONERO_Wallet_addSubaddress( + this.#walletPtr, + accountIndex, + CString(label), + ); + await this.throwIfError(); + } + + async numSubaddresses(accountIndex: number): Promise { + const address = await dylib.symbols.MONERO_Wallet_numSubaddresses( + this.#walletPtr, + accountIndex, + ); + await this.throwIfError(); + return address; + } + + async getSubaddressLabel(accountIndex: number, addressIndex: number): Promise { + const label = await dylib.symbols.MONERO_Wallet_getSubaddressLabel(this.#walletPtr, accountIndex, addressIndex); + if (!label) { + const error = await this.errorString(); + throw new Error(`Failed getting subaddress label from a wallet: ${error ?? ""}`); + } + return await readCString(label); + } + + async setSubaddressLabel(accountIndex: number, addressIndex: number, label: string): Promise { + await dylib.symbols.MONERO_Wallet_setSubaddressLabel( + this.#walletPtr, + accountIndex, + addressIndex, + CString(label), + ); + await this.throwIfError(); + } + + async getHistory(): Promise { + const transactionHistoryPointer = await dylib.symbols.MONERO_Wallet_history(this.#walletPtr); + await this.throwIfError(); + return new TransactionHistory(transactionHistoryPointer as TransactionHistoryPtr); + } + + async createTransaction( + destinationAddress: string, + amount: bigint, + pendingTransactionPriority = 0 | 1 | 2 | 3, + subaddressAccount: number, + sanitize = true, + prefferedInputs = "", + mixinCount = 0, + paymentId = "", + separator = ",", + ): Promise { + const pendingTxPtr = await dylib.symbols.MONERO_Wallet_createTransaction( + this.#walletPtr, + CString(destinationAddress), + CString(paymentId), + amount, + mixinCount, + pendingTransactionPriority, + subaddressAccount, + CString(prefferedInputs), + CString(separator), + ); + await this.throwIfError(sanitize); + return new PendingTransaction(pendingTxPtr as PendingTransactionPtr); + } + + async amountFromString(amount: string): Promise { + return await dylib.symbols.MONERO_Wallet_amountFromString(CString(amount)); + } +} diff --git a/impls/monero.ts/src/wallet_manager.ts b/impls/monero.ts/src/wallet_manager.ts new file mode 100644 index 0000000..ad9cf31 --- /dev/null +++ b/impls/monero.ts/src/wallet_manager.ts @@ -0,0 +1,27 @@ +import { dylib } from "./bindings.ts"; +import { Sanitizer } from "./utils.ts"; + +export type WalletManagerPtr = Deno.PointerObject<"walletManager">; + +export class WalletManager { + #ptr: WalletManagerPtr; + sanitizer?: Sanitizer; + + constructor(walletManagerPtr: WalletManagerPtr, sanitizer?: Sanitizer) { + this.#ptr = walletManagerPtr; + this.sanitizer = sanitizer; + } + + getPointer(): WalletManagerPtr { + return this.#ptr; + } + + static async new(sanitizer?: Sanitizer) { + const ptr = await dylib.symbols.MONERO_WalletManagerFactory_getWalletManager(); + if (!ptr) { + sanitizer?.(); + throw new Error("Failed retrieving wallet manager"); + } + return new WalletManager(ptr as WalletManagerPtr, sanitizer); + } +} -- cgit v1.2.3 From 33f36186c891ff911d2e24a26e3962e148f61340 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 27 Sep 2024 18:02:35 +0000 Subject: chore(deps): update dependency lints to v5 --- impls/monero.dart/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'impls') diff --git a/impls/monero.dart/pubspec.yaml b/impls/monero.dart/pubspec.yaml index d85d600..174a781 100644 --- a/impls/monero.dart/pubspec.yaml +++ b/impls/monero.dart/pubspec.yaml @@ -10,6 +10,6 @@ dependencies: ffi: ^2.1.0 dev_dependencies: - lints: ^4.0.0 + lints: ^5.0.0 test: ^1.24.0 ffigen: ^14.0.0 \ No newline at end of file -- cgit v1.2.3 From 67f4baa015a4407d096e35b6e5a81d72932fb55f Mon Sep 17 00:00:00 2001 From: cyan Date: Sun, 22 Sep 2024 15:29:40 +0000 Subject: add C# code --- impls/monero.c#/README.md | 7 ++ impls/monero.c#/monero_wrapper.cs | 184 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 191 insertions(+) create mode 100644 impls/monero.c#/README.md create mode 100644 impls/monero.c#/monero_wrapper.cs (limited to 'impls') diff --git a/impls/monero.c#/README.md b/impls/monero.c#/README.md new file mode 100644 index 0000000..bfbb3b7 --- /dev/null +++ b/impls/monero.c#/README.md @@ -0,0 +1,7 @@ +# monero.c# + +> C# port for monero + +This is not a ready-to-use package (as opposed to monero.dart and monero.ts), but it works. You can check the `monero_wrapper.cs`. + +Currently C# code is optimized to be used in Godot.., if you are not planning to use it there - simply do not extend Node class and remove Godot import, if you are planning to use it in production, please let me know - we can work on a better approach to using monero with proper package code in here. \ No newline at end of file diff --git a/impls/monero.c#/monero_wrapper.cs b/impls/monero.c#/monero_wrapper.cs new file mode 100644 index 0000000..ce7749d --- /dev/null +++ b/impls/monero.c#/monero_wrapper.cs @@ -0,0 +1,184 @@ +using Godot; +using System; +using System.Runtime.InteropServices; + +public partial class monero_wrapper : Node +{ + public static IntPtr wmPtr = MONERO_WalletManagerFactory_getWalletManager(); + public static IntPtr wPtr; + public static IntPtr pendingTx; + public static IntPtr txHistory; + public string path = ""; + + // Called when the node enters the scene tree for the first time. + public override void _Ready() + { + } + + // Called every frame. 'delta' is the elapsed time since the previous frame. + public override void _Process(double delta) + { + } + + public static bool openWallet(string path, string password) { + MONERO_WalletManager_createWallet(wmPtr, path, password, "English", 0); + wPtr = MONERO_WalletManager_openWallet(wmPtr, path, password, 0); + return MONERO_Wallet_status(wPtr) == 0; + } + + public static void initWallet(string daemonAddress, bool useSsl, String proxyString) { + //MONERO_Wallet_init(string daemon_password, bool use_ssl, bool lightWallet, string proxy_address); + MONERO_Wallet_init(wPtr, daemonAddress, 0, "", "", useSsl, false, proxyString); + GD.Print(lastError()); + MONERO_Wallet_init3(wPtr, "", "", "/dev/shm/godot_moneroc.log", false); + GD.Print(lastError()); + MONERO_Wallet_setTrustedDaemon(wPtr, true); + GD.Print(lastError()); + MONERO_Wallet_refreshAsync(wPtr); + GD.Print(lastError()); + MONERO_Wallet_startRefresh(wPtr); + GD.Print(lastError()); + } + + public static void storeWallet() { + MONERO_Wallet_store(wPtr); + } + + public static string lastError() { + IntPtr resultPtr = MONERO_Wallet_errorString(wPtr); + string result = Marshal.PtrToStringAnsi(resultPtr); + return result; + } + + public static int lastErrorCode() { + return MONERO_Wallet_status(wPtr); + } + + public static string lastTxError() { + IntPtr resultPtr = MONERO_PendingTransaction_errorString(pendingTx); + string result = Marshal.PtrToStringAnsi(resultPtr); + return result; + } + + public static int lastTxErrorCode() { + return MONERO_PendingTransaction_status(pendingTx); + } + + public static string getAddress(ulong accountIndex, ulong addressIndex) { + IntPtr resultPtr = MONERO_Wallet_address(wPtr, accountIndex, addressIndex); + string result = Marshal.PtrToStringAnsi(resultPtr); + return result; + } + + public static ulong getBalance(uint accountIndex) { + return MONERO_Wallet_balance(wPtr, accountIndex); + } + + public static void createTransaction(string address, ulong amount) { + pendingTx = MONERO_Wallet_createTransaction(wPtr, address, "", amount, 0, 0, 0, "", ""); + MONERO_PendingTransaction_commit(pendingTx, "", false); + } + + public static int getTransactionCount() { + txHistory = MONERO_Wallet_history(wPtr); + MONERO_TransactionHistory_refresh(txHistory); + return MONERO_TransactionHistory_count(txHistory); + } + + public static int getTransactionDirection(int index) { + txHistory = MONERO_Wallet_history(wPtr); + IntPtr txPtr = MONERO_TransactionHistory_transaction(txHistory, index); + return MONERO_TransactionInfo_direction(txPtr); + } + + public static ulong getTransactionAmount(int index) { + txHistory = MONERO_Wallet_history(wPtr); + IntPtr txPtr = MONERO_TransactionHistory_transaction(txHistory, index); + return MONERO_TransactionInfo_amount(txPtr); + } + + public static ulong getTransactionTimestamp(int index) { + txHistory = MONERO_Wallet_history(wPtr); + IntPtr txPtr = MONERO_TransactionHistory_transaction(txHistory, index); + return MONERO_TransactionInfo_timestamp(txPtr); + } + + [DllImport("/usr/lib/monero_libwallet2_api_c.so")] + public static extern ulong MONERO_TransactionInfo_timestamp(IntPtr txPtr); + + [DllImport("/usr/lib/monero_libwallet2_api_c.so")] + public static extern IntPtr MONERO_TransactionHistory_transaction(IntPtr txHistory, int index); + + [DllImport("/usr/lib/monero_libwallet2_api_c.so")] + public static extern int MONERO_TransactionInfo_direction(IntPtr txPtr); + + [DllImport("/usr/lib/monero_libwallet2_api_c.so")] + public static extern int MONERO_TransactionHistory_count(IntPtr txHistory); + + [DllImport("/usr/lib/monero_libwallet2_api_c.so")] + public static extern ulong MONERO_TransactionInfo_amount(IntPtr txPtr); + + [DllImport("/usr/lib/monero_libwallet2_api_c.so")] + public static extern IntPtr MONERO_Wallet_history(IntPtr wm_ptr); + + [DllImport("/usr/lib/monero_libwallet2_api_c.so")] + public static extern IntPtr MONERO_TransactionHistory_refresh(IntPtr txHistory); + + [DllImport("/usr/lib/monero_libwallet2_api_c.so")] + public static extern IntPtr MONERO_WalletManager_createWallet(IntPtr wm_ptr, string path, string password, string language, int networkType); + + [DllImport("/usr/lib/monero_libwallet2_api_c.so")] + public static extern IntPtr MONERO_WalletManager_openWallet(IntPtr wm_ptr, string path, string password, int networkType); + + [DllImport("/usr/lib/monero_libwallet2_api_c.so")] + public static extern IntPtr MONERO_WalletManagerFactory_getWalletManager(); + + [DllImport("/usr/lib/monero_libwallet2_api_c.so")] + public static extern int MONERO_Wallet_status(IntPtr wPtr); + + [DllImport("/usr/lib/monero_libwallet2_api_c.so")] + public static extern int MONERO_PendingTransaction_status(IntPtr wPtr); + + [DllImport("/usr/lib/monero_libwallet2_api_c.so")] + public static extern bool MONERO_WalletManager_walletExists(IntPtr wmPtr, string path); + + [DllImport("/usr/lib/monero_libwallet2_api_c.so")] + public static extern IntPtr MONERO_Wallet_errorString(IntPtr wPtr); + + [DllImport("/usr/lib/monero_libwallet2_api_c.so")] + public static extern IntPtr MONERO_PendingTransaction_errorString(IntPtr pendingTx); + + [DllImport("/usr/lib/monero_libwallet2_api_c.so")] + public static extern ulong MONERO_Wallet_balance(IntPtr wPtr, uint accountIndex); + + [DllImport("/usr/lib/monero_libwallet2_api_c.so")] + public static extern IntPtr MONERO_Wallet_address(IntPtr wPtr, ulong accountIndex, ulong addressIndex); + + [DllImport("/usr/lib/monero_libwallet2_api_c.so")] + public static extern IntPtr MONERO_Wallet_createTransaction(IntPtr wallet_ptr, string dst_addr, string payment_id, + ulong amount, uint mixin_count, + int pendingTransactionPriority, + uint subaddr_account, + string preferredInputs, string separator); + + [DllImport("/usr/lib/monero_libwallet2_api_c.so")] + public static extern bool MONERO_PendingTransaction_commit(IntPtr pendingTx_ptr, string filename, bool overwrite); + + [DllImport("/usr/lib/monero_libwallet2_api_c.so")] + public static extern bool MONERO_Wallet_init(IntPtr wallet_ptr, string daemon_address, ulong upper_transaction_size_limit, string daemon_username, string daemon_password, bool use_ssl, bool lightWallet, string proxy_address); + + [DllImport("/usr/lib/monero_libwallet2_api_c.so")] + public static extern bool MONERO_Wallet_init3(IntPtr wallet_ptr, string argv0, string default_log_base_name, string log_path, bool console); + + [DllImport("/usr/lib/monero_libwallet2_api_c.so")] + public static extern void MONERO_Wallet_setTrustedDaemon(IntPtr wallet_ptr, bool arg); + + [DllImport("/usr/lib/monero_libwallet2_api_c.so")] + public static extern void MONERO_Wallet_startRefresh(IntPtr wallet_ptr); + + [DllImport("/usr/lib/monero_libwallet2_api_c.so")] + public static extern void MONERO_Wallet_refreshAsync(IntPtr wallet_ptr); + + [DllImport("/usr/lib/monero_libwallet2_api_c.so")] + public static extern bool MONERO_Wallet_store(IntPtr wallet_ptr); +} -- cgit v1.2.3