Files
monero_c/impls/monero.ts/src/transaction_info.ts
Mateusz Franik 40c1a1bda4 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>
2024-12-01 09:02:20 -05:00

148 lines
3.6 KiB
TypeScript

import { fns } from "./bindings.ts";
import { C_SEPARATOR, CString, maybeMultipleStrings, readCString, SEPARATOR } from "./utils.ts";
export type TransactionInfoPtr = Deno.PointerObject<"pendingTransaction">;
export interface TransferData {
address: string | null;
amount: bigint;
}
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;
return instance;
}
get amount(): bigint {
return this.#amount;
}
get fee(): bigint {
return this.#fee;
}
get timestamp(): bigint {
return this.#timestamp;
}
get transfersCount(): number {
return this.#transfersCount;
}
get paymentId(): string | null {
return this.#paymentId;
}
get hash(): string | null {
return this.#hash;
}
get subaddrAccount(): number {
return this.#subaddrAccount;
}
get subaddrIndex(): string | null {
return this.#subaddrIndex;
}
get transfers(): readonly TransferData[] {
return this.#transfers;
}
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 description(): Promise<string | null> {
return await readCString(
await fns.TransactionInfo_description(this.#ptr),
);
}
async label(): Promise<string | null> {
return await readCString(
await fns.TransactionInfo_label(this.#ptr),
);
}
async confirmations(): Promise<bigint> {
return await fns.TransactionInfo_confirmations(this.#ptr);
}
async unlockTime(): Promise<bigint> {
return await fns.TransactionInfo_unlockTime(this.#ptr);
}
async isPending(): Promise<boolean> {
return await fns.TransactionInfo_isPending(this.#ptr);
}
async isFailed(): Promise<boolean> {
return await fns.TransactionInfo_isFailed(this.#ptr);
}
async isCoinbase(): Promise<boolean> {
return await fns.TransactionInfo_isCoinbase(this.#ptr);
}
}