summaryrefslogtreecommitdiff
path: root/impls/monero.ts/src/transaction_info.ts
diff options
context:
space:
mode:
authorMateusz Franik <47059999+Im-Beast@users.noreply.github.com>2024-12-01 15:02:20 +0100
committerGitHub <noreply@github.com>2024-12-01 09:02:20 -0500
commit40c1a1bda4b6f125c702f5a37ecc48a6ebec24b8 (patch)
treef5dece80ded669b856ab875d2814fcb9bf0b157b /impls/monero.ts/src/transaction_info.ts
parentc41c4dad9aa5003a914cfb2c528c76386f952665 (diff)
feat!: monero.ts rewrite, integration tests (#80)
* feat: move spend/view key symbols to the monero.ts implementation * feat: add integration tests for `0001-polyseed.patch` * feat(monero.ts): add support for backgroundSync and closing the wallet * feat: add integration tests for `0002-wallet-background-sync-with-just-the-view-key.patch` * feat!: require users to provide own node url BREAKING CHANGE: Requires users manual call to `Wallet.initWallet` after wallet creation with preferred node url * feat: add background sync test for `0002-wallet-background-sync-with-just-the-view-key.patch` * ci: add integration tests step * feat(monero.ts): support creating and recovering wallet from polyseed * feat: actually test polyseeds in the integration test * chore: remove legacy comments * fix: uncomment getting moneroC * feat(monero.ts): add support for reading wallet's seed * feat: add seed test for `0009-Add-recoverDeterministicWalletFromSpendKey.patch` * chore: slight refactor * feat(monero.ts): add bindings for `setOffline` and `isOffline` * feat: add integration tests for `0012-WIP-UR-functions.patch` * fix: use correct node depending on the coin * fix: prevent segfaults on wownero * feat(monero.ts): add partial bindings for `Coins` and `CoinsInfo` * feat: add integration tests for `0004-coin-control.patch` * fix coin control * clean up console.logs * chore: comment out the entire block * dev: add devcontainer config for deno * fix(monero.ts): invalid PendingTransactionPtr brand * feat(monero.ts): add bindings for retrieving keys and managing transactions * feat: improve `0012-WIP-UR-functions.patch` tests to follow the airgap doc * fix(monero.ts): make UR methods optional so wownero can load properly * remove flaky balance assertions * tests: add a little bit of delay to make 0002 patch test less flake-y * tests: run wallet transaction tests on ci * enable logging to determine why it segfaults on ci * add delay to every syncBlockchain call * its console logging time * even more console.logs * eep * eep more * dont assert that its not frozen * remove console.logs * fix(monero.ts): type typo becoming a default value * feat(monero.ts): add bindings for `createTransactionMultDest` * feat(monero.ts): support returning multiple values whenever necessary * feat(monero.ts): add missing reexports * feat(monero.ts)!: rewrite bindings BREAKING CHANGES!: - Calls to methods no longer automatically throw errors, you should take care of handling errors yourself - This means the whole sanitizer ordeal is gone, no more sanitize arguments etc. - Some misplaced methods have been moved to their "proper" place, e.g. creating Wallet is now possible using WalletManager instance methods, instead of passing WalletManager instance to Wallet's static method - Return types probably changed in places, methods were inconsitent about returning string or empty string and `string | null`, now its always `string | null` - Every available symbol should now be available in `symbols`, even for the things that are not yet implemented, so you can access them in that case * tests: adapt tests to monero.ts changes * tests: reuse dylib in tests --------- Co-authored-by: cyan <cyjan@mrcyjanek.net>
Diffstat (limited to 'impls/monero.ts/src/transaction_info.ts')
-rw-r--r--impls/monero.ts/src/transaction_info.ts169
1 files changed, 106 insertions, 63 deletions
diff --git a/impls/monero.ts/src/transaction_info.ts b/impls/monero.ts/src/transaction_info.ts
index 22ea0e7..9becfb9 100644
--- a/impls/monero.ts/src/transaction_info.ts
+++ b/impls/monero.ts/src/transaction_info.ts
@@ -1,104 +1,147 @@
-import { dylib } from "./bindings.ts";
-import { getSymbol, readCString, Sanitizer } from "./utils.ts";
+import { fns } from "./bindings.ts";
+import { C_SEPARATOR, CString, maybeMultipleStrings, readCString, SEPARATOR } from "./utils.ts";
-export type TransactionInfoPtr = Deno.PointerObject<"transactionInfo">;
+export type TransactionInfoPtr = Deno.PointerObject<"pendingTransaction">;
-export class TransactionInfo {
- #txInfoPtr: TransactionInfoPtr;
- sanitizer?: Sanitizer;
-
- constructor(txInfoPtr: TransactionInfoPtr, sanitizer?: Sanitizer) {
- this.#txInfoPtr = txInfoPtr;
- this.sanitizer = sanitizer;
- }
+export interface TransferData {
+ address: string | null;
+ amount: bigint;
+}
- async direction(): Promise<"in" | "out"> {
- switch (await getSymbol("TransactionInfo_direction")(this.#txInfoPtr)) {
- case 0:
- return "in";
- case 1:
- return "out";
- default:
- await this.sanitizer?.();
- throw new Error("Invalid TransactionInfo direction");
+export class TransactionInfo<MultDest extends boolean = boolean> {
+ #ptr: TransactionInfoPtr;
+
+ #amount!: bigint;
+ #fee!: bigint;
+ #timestamp!: bigint;
+ #transfersCount!: number;
+ #paymentId!: string | null;
+ #hash!: string | null;
+
+ #subaddrAccount!: number;
+ #subaddrIndex!: string | null;
+
+ #transfers!: readonly TransferData[];
+
+ constructor(ptr: TransactionInfoPtr) {
+ this.#ptr = ptr;
+ }
+
+ static async new(ptr: TransactionInfoPtr): Promise<TransactionInfo> {
+ const instance = new TransactionInfo(ptr);
+
+ const [amount, paymentId, fee, hash, subaddrIndex, subaddrAccount, timestamp, transfersCount] = await Promise.all([
+ fns.TransactionInfo_amount(ptr),
+ fns.TransactionInfo_paymentId(ptr).then(readCString),
+ fns.TransactionInfo_fee(ptr),
+ fns.TransactionInfo_hash(ptr).then(readCString),
+ fns.TransactionInfo_subaddrIndex(ptr, C_SEPARATOR).then(readCString),
+ fns.TransactionInfo_subaddrAccount(ptr),
+ fns.TransactionInfo_timestamp(ptr),
+ fns.TransactionInfo_transfers_count(ptr),
+ ]);
+
+ instance.#amount = amount;
+ instance.#fee = fee;
+ instance.#timestamp = timestamp;
+ instance.#transfersCount = transfersCount;
+ instance.#paymentId = paymentId;
+ instance.#hash = hash;
+
+ instance.#subaddrAccount = subaddrAccount;
+ instance.#subaddrIndex = subaddrIndex;
+
+ const transfers = [];
+ for (let i = 0; i < transfersCount; ++i) {
+ const [amount, address] = await Promise.all([
+ fns.TransactionInfo_transfers_amount(ptr, i),
+ fns.TransactionInfo_transfers_address(ptr, i).then(readCString),
+ ]);
+
+ transfers.push({ amount, address });
}
- }
+ Object.freeze(transfers);
+ instance.#transfers = transfers;
- async isPending(): Promise<boolean> {
- return await getSymbol("TransactionInfo_isPending")(this.#txInfoPtr);
+ return instance;
}
- async isFailed(): Promise<boolean> {
- return await getSymbol("TransactionInfo_isFailed")(this.#txInfoPtr);
+ get amount(): bigint {
+ return this.#amount;
}
- async isCoinbase(): Promise<boolean> {
- return await getSymbol("TransactionInfo_isCoinbase")(this.#txInfoPtr);
+ get fee(): bigint {
+ return this.#fee;
}
- async amount(): Promise<bigint> {
- return await getSymbol("TransactionInfo_amount")(this.#txInfoPtr);
+ get timestamp(): bigint {
+ return this.#timestamp;
}
- async fee(): Promise<bigint> {
- return await getSymbol("TransactionInfo_fee")(this.#txInfoPtr);
+ get transfersCount(): number {
+ return this.#transfersCount;
}
- async blockHeight(): Promise<bigint> {
- return await getSymbol("TransactionInfo_blockHeight")(this.#txInfoPtr);
+ get paymentId(): string | null {
+ return this.#paymentId;
}
- async description(): Promise<string> {
- const description = await getSymbol("TransactionInfo_description")(this.#txInfoPtr);
- return await readCString(description) || "";
+ get hash(): string | null {
+ return this.#hash;
}
- async subaddrIndex(): Promise<string> {
- const subaddrIndex = await getSymbol("TransactionInfo_subaddrIndex")(this.#txInfoPtr);
- return await readCString(subaddrIndex) || "";
+ get subaddrAccount(): number {
+ return this.#subaddrAccount;
}
- async subaddrAccount(): Promise<number> {
- return await getSymbol("TransactionInfo_subaddrAccount")(this.#txInfoPtr);
+ get subaddrIndex(): string | null {
+ return this.#subaddrIndex;
}
- async label(): Promise<string> {
- const label = await getSymbol("TransactionInfo_label")(this.#txInfoPtr);
- return await readCString(label) || "";
+ get transfers(): readonly TransferData[] {
+ return this.#transfers;
}
- async confirmations(): Promise<bigint> {
- return await getSymbol("TransactionInfo_confirmations")(this.#txInfoPtr);
+ async direction(): Promise<"in" | "out"> {
+ switch (await fns.TransactionInfo_direction(this.#ptr)) {
+ case 0:
+ return "in";
+ case 1:
+ return "out";
+ default:
+ throw new Error("Invalid TransactionInfo direction");
+ }
}
- async unlockTime(): Promise<bigint> {
- return await getSymbol("TransactionInfo_unlockTime")(this.#txInfoPtr);
+ async description(): Promise<string | null> {
+ return await readCString(
+ await fns.TransactionInfo_description(this.#ptr),
+ );
}
- async hash(): Promise<string> {
- const hash = await getSymbol("TransactionInfo_hash")(this.#txInfoPtr);
- return await readCString(hash) || "";
+ async label(): Promise<string | null> {
+ return await readCString(
+ await fns.TransactionInfo_label(this.#ptr),
+ );
}
- async timestamp(): Promise<bigint> {
- return await getSymbol("TransactionInfo_timestamp")(this.#txInfoPtr);
+ async confirmations(): Promise<bigint> {
+ return await fns.TransactionInfo_confirmations(this.#ptr);
}
- async paymentId(): Promise<string> {
- const paymentId = await getSymbol("TransactionInfo_paymentId")(this.#txInfoPtr);
- return await readCString(paymentId) || "";
+ async unlockTime(): Promise<bigint> {
+ return await fns.TransactionInfo_unlockTime(this.#ptr);
}
- async transfersCount(): Promise<number> {
- return await getSymbol("TransactionInfo_transfers_count")(this.#txInfoPtr);
+ async isPending(): Promise<boolean> {
+ return await fns.TransactionInfo_isPending(this.#ptr);
}
- async transfersAmount(index: number): Promise<bigint> {
- return await getSymbol("TransactionInfo_transfers_amount")(this.#txInfoPtr, index);
+ async isFailed(): Promise<boolean> {
+ return await fns.TransactionInfo_isFailed(this.#ptr);
}
- async transfersAddress(index: number): Promise<string> {
- const transfersAddress = await getSymbol("TransactionInfo_transfers_address")(this.#txInfoPtr, index);
- return await readCString(transfersAddress) || "";
+ async isCoinbase(): Promise<boolean> {
+ return await fns.TransactionInfo_isCoinbase(this.#ptr);
}
}