diff --git a/impls/monero.ts/checksum.ts b/impls/monero.ts/checksum.ts index e923e40f..ac09ea99 100644 --- a/impls/monero.ts/checksum.ts +++ b/impls/monero.ts/checksum.ts @@ -19,7 +19,7 @@ export class ChecksumError extends Error { * @returns {ChecksumError} which contains information about why checksum failed */ export async function validateChecksum(): Promise { - const cppHeaderHash = readCString(await dylib.symbols.MONERO_checksum_wallet2_api_c_h()); + const cppHeaderHash = await readCString(await dylib.symbols.MONERO_checksum_wallet2_api_c_h()); const tsHeaderHash = moneroChecksum.wallet2_api_c_h_sha256; const errors: string[] = []; @@ -30,14 +30,14 @@ export async function validateChecksum(): Promise { errorCode++; } - const cppSourceHash = readCString(await dylib.symbols.MONERO_checksum_wallet2_api_c_cpp()); + const cppSourceHash = await readCString(await dylib.symbols.MONERO_checksum_wallet2_api_c_cpp()); const tsSourceHash = moneroChecksum.wallet2_api_c_cpp_sha256; if (cppSourceHash !== tsSourceHash) { errors.push(`ERR: CPP source file check mismatch ${cppSourceHash} == ${tsSourceHash}`); errorCode++; } - const cppExportHash = readCString(await dylib.symbols.MONERO_checksum_wallet2_api_c_exp()); + const cppExportHash = await readCString(await dylib.symbols.MONERO_checksum_wallet2_api_c_exp()); const tsExportHash = moneroChecksum.wallet2_api_c_exp_sha256; if (cppExportHash !== tsExportHash) { if (Deno.build.os !== "darwin") { diff --git a/impls/monero.ts/src/bindings.ts b/impls/monero.ts/src/bindings.ts index 0601812f..b854f7d3 100644 --- a/impls/monero.ts/src/bindings.ts +++ b/impls/monero.ts/src/bindings.ts @@ -523,6 +523,14 @@ export const symbols = { result: "pointer", }, //#endregion + + "MONERO_free": { + nonblocking: true, + // void* ptr + parameters: ["pointer"], + // void + result: "void", + }, } as const; type MoneroTsDylib = Deno.DynamicLibrary; diff --git a/impls/monero.ts/src/pending_transaction.ts b/impls/monero.ts/src/pending_transaction.ts index e734c759..cf487218 100644 --- a/impls/monero.ts/src/pending_transaction.ts +++ b/impls/monero.ts/src/pending_transaction.ts @@ -22,7 +22,7 @@ export class PendingTransaction { const error = await dylib.symbols.MONERO_PendingTransaction_errorString(this.#pendingTxPtr); if (!error) return null; - return readCString(error) || null; + return await readCString(error) || null; } async throwIfError(sanitize = true): Promise { @@ -50,7 +50,7 @@ export class PendingTransaction { ); if (!result) return null; await this.throwIfError(); - return readCString(result) || null; + return await readCString(result) || null; } async amount(): Promise { @@ -72,7 +72,7 @@ export class PendingTransaction { ); if (!result) return null; await this.throwIfError(sanitize); - return readCString(result) || null; + return await readCString(result) || null; } async txCount(): Promise { diff --git a/impls/monero.ts/src/transaction_info.ts b/impls/monero.ts/src/transaction_info.ts index 9c697375..7db45f5d 100644 --- a/impls/monero.ts/src/transaction_info.ts +++ b/impls/monero.ts/src/transaction_info.ts @@ -50,12 +50,12 @@ export class TransactionInfo { async description(): Promise { const description = await dylib.symbols.MONERO_TransactionInfo_description(this.#txInfoPtr); - return readCString(description) || ""; + return await readCString(description) || ""; } async subaddrIndex(): Promise { const subaddrIndex = await dylib.symbols.MONERO_TransactionInfo_subaddrIndex(this.#txInfoPtr); - return readCString(subaddrIndex) || ""; + return await readCString(subaddrIndex) || ""; } async subaddrAccount(): Promise { @@ -64,7 +64,7 @@ export class TransactionInfo { async label(): Promise { const label = await dylib.symbols.MONERO_TransactionInfo_label(this.#txInfoPtr); - return readCString(label) || ""; + return await readCString(label) || ""; } async confirmations(): Promise { @@ -77,7 +77,7 @@ export class TransactionInfo { async hash(): Promise { const hash = await dylib.symbols.MONERO_TransactionInfo_hash(this.#txInfoPtr); - return readCString(hash) || ""; + return await readCString(hash) || ""; } async timestamp(): Promise { @@ -86,7 +86,7 @@ export class TransactionInfo { async paymentId(): Promise { const paymentId = await dylib.symbols.MONERO_TransactionInfo_paymentId(this.#txInfoPtr); - return readCString(paymentId) || ""; + return await readCString(paymentId) || ""; } async transfersCount(): Promise { @@ -99,6 +99,6 @@ export class TransactionInfo { async transfersAddress(index: number): Promise { const transfersAddress = await dylib.symbols.MONERO_TransactionInfo_transfers_address(this.#txInfoPtr, index); - return readCString(transfersAddress) || ""; + return await readCString(transfersAddress) || ""; } } diff --git a/impls/monero.ts/src/utils.ts b/impls/monero.ts/src/utils.ts index 715dd7b9..187a3d0c 100644 --- a/impls/monero.ts/src/utils.ts +++ b/impls/monero.ts/src/utils.ts @@ -1,3 +1,5 @@ +import { dylib } from "../mod.ts"; + export type Sanitizer = () => void | PromiseLike; const textEncoder = new TextEncoder(); @@ -5,9 +7,14 @@ export function CString(string: string): Deno.PointerValue { return Deno.UnsafePointer.of(textEncoder.encode(`${string}\x00`)); } -export function readCString(pointer: Deno.PointerObject): string; -export function readCString(pointer: Deno.PointerValue): string | null; -export function readCString(pointer: Deno.PointerValue): string | null { +// 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 +// In that case just use `Deno.UnsafePointerView(ptr).getCString()` directly +export async function readCString(pointer: Deno.PointerObject): Promise; +export async function readCString(pointer: Deno.PointerValue): Promise; +export async function readCString(pointer: Deno.PointerValue): Promise { if (!pointer) return null; - return new Deno.UnsafePointerView(pointer).getCString(); + const string = new Deno.UnsafePointerView(pointer).getCString(); + await dylib.symbols.MONERO_free(pointer); + return string; } diff --git a/impls/monero.ts/src/wallet.ts b/impls/monero.ts/src/wallet.ts index 0906e2b3..07c40ceb 100644 --- a/impls/monero.ts/src/wallet.ts +++ b/impls/monero.ts/src/wallet.ts @@ -153,7 +153,7 @@ export class Wallet { const error = await this.errorString(); throw new Error(`Failed getting address from a wallet: ${error ?? ""}`); } - return readCString(address); + return await readCString(address); } async balance(accountIndex = 0): Promise { @@ -174,7 +174,7 @@ export class Wallet { const error = await dylib.symbols.MONERO_Wallet_errorString(this.#walletPtr); if (!error) return null; - return readCString(error) || null; + return await readCString(error) || null; } async throwIfError(sanitize = true): Promise { @@ -253,7 +253,7 @@ export class Wallet { const error = await this.errorString(); throw new Error(`Failed getting subaddress label from a wallet: ${error ?? ""}`); } - return readCString(label); + return await readCString(label); } async setSubaddressLabel(accountIndex: number, addressIndex: number, label: string): Promise {