diff options
Diffstat (limited to 'impls/monero.ts/src/wallet.ts')
| -rw-r--r-- | impls/monero.ts/src/wallet.ts | 446 |
1 files changed, 234 insertions, 212 deletions
diff --git a/impls/monero.ts/src/wallet.ts b/impls/monero.ts/src/wallet.ts index ea25f21..673ccab 100644 --- a/impls/monero.ts/src/wallet.ts +++ b/impls/monero.ts/src/wallet.ts @@ -1,294 +1,268 @@ -import { dylib } from "./bindings.ts"; -import { CString, getSymbol, readCString, Sanitizer } from "./utils.ts"; +import { WalletManager } from "./wallet_manager.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"; +import { C_SEPARATOR, CString, readCString, SEPARATOR } from "./utils.ts"; +import { PendingTransaction, PendingTransactionPtr } from "./pending_transaction.ts"; +import { UnsignedTransaction, UnsignedTransactionPtr } from "./unsigned_transaction.ts"; +import { Coins, CoinsPtr } from "./coins.ts"; +import { fns } from "./bindings.ts"; export type WalletPtr = Deno.PointerObject<"walletManager">; +interface DaemonInfo { + address?: string; + username?: string; + password?: string; + lightWallet?: boolean; + proxyAddress?: string; +} + export class Wallet { - #walletManagerPtr: WalletManagerPtr; - #walletPtr: WalletPtr; - sanitizer?: Sanitizer; + #walletManager: WalletManager; + #ptr: WalletPtr; - constructor(walletManagerPtr: WalletManager, walletPtr: WalletPtr, sanitizer?: Sanitizer) { - this.#walletPtr = walletPtr; - this.#walletManagerPtr = walletManagerPtr.getPointer(); - this.sanitizer = sanitizer; + constructor(walletManager: WalletManager, ptr: WalletPtr) { + this.#walletManager = walletManager; + this.#ptr = ptr; } - getPointer(): WalletPtr { - return this.#walletPtr; + getPointer() { + return this.#ptr; } - async store(path = ""): Promise<boolean> { - const bool = await getSymbol("Wallet_store")(this.#walletPtr, CString(path)); - await this.throwIfError(); - return bool; - } + async init(daemonInfo: DaemonInfo, log = false): Promise<boolean> { + const success = await fns.Wallet_init( + this.#ptr, + CString(daemonInfo.address ?? ""), + 0n, + CString(daemonInfo.username ?? ""), + CString(daemonInfo.password ?? ""), + false, + daemonInfo.lightWallet ?? false, + CString(daemonInfo.proxyAddress ?? ""), + ); + + if (log) { + await fns.Wallet_init3( + this.#ptr, + CString(""), + CString(""), + CString(""), + true, + ); + } - async initWallet(daemonAddress = "http://nodex.monerujo.io:18081"): Promise<void> { - await this.init(); await this.setTrustedDaemon(true); - await this.setDaemonAddress(daemonAddress); await this.startRefresh(); await this.refreshAsync(); - await this.throwIfError(); + + return success; } - async setDaemonAddress(address: string): Promise<void> { - await getSymbol("WalletManager_setDaemonAddress")( - this.#walletManagerPtr, - CString(address), - ); + async setTrustedDaemon(value: boolean): Promise<void> { + return await fns.Wallet_setTrustedDaemon(this.#ptr, value); } async startRefresh(): Promise<void> { - await getSymbol("Wallet_startRefresh")(this.#walletPtr); - await this.throwIfError(); + return await fns.Wallet_startRefresh(this.#ptr); } async refreshAsync(): Promise<void> { - await getSymbol("Wallet_refreshAsync")(this.#walletPtr); - await this.throwIfError(); - } - - async init(): Promise<boolean> { - const bool = await getSymbol("Wallet_init")( - this.#walletPtr, - CString("http://nodex.monerujo.io:18081"), - 0n, - CString(""), - CString(""), - false, - false, - CString(""), + return await fns.Wallet_refreshAsync(this.#ptr); + } + + async setupBackgroundSync( + backgroundSyncType: number, + walletPassword: string, + backgroundCachePassword: string, + ): Promise<boolean> { + return await fns.Wallet_setupBackgroundSync( + this.#ptr, + backgroundSyncType, + CString(walletPassword), + CString(backgroundCachePassword), ); - await this.throwIfError(); - return bool; } - async setTrustedDaemon(value: boolean): Promise<void> { - await getSymbol("Wallet_setTrustedDaemon")(this.#walletPtr, value); - } - - static async create( - walletManager: WalletManager, - path: string, - password: string, - sanitizeError = true, - ): Promise<Wallet> { - // We assign holder of the pointer in Wallet constructor - const walletManagerPtr = walletManager.getPointer(); - - const walletPtr = await getSymbol("WalletManager_createWallet")( - walletManagerPtr, - CString(path), - CString(password), - CString("English"), - 0, - ); + async startBackgroundSync(): Promise<boolean> { + return await fns.Wallet_startBackgroundSync(this.#ptr); + } - const wallet = new Wallet(walletManager, walletPtr as WalletPtr, walletManager.sanitizer); - await wallet.throwIfError(sanitizeError); - await wallet.initWallet(); + async stopBackgroundSync(walletPassword: string): Promise<boolean> { + return await fns.Wallet_stopBackgroundSync(this.#ptr, CString(walletPassword)); + } - return wallet; + async store(path = ""): Promise<boolean> { + return await fns.Wallet_store(this.#ptr, CString(path)); } - static async open( - walletManager: WalletManager, - path: string, - password: string, - sanitizeError = true, - ): Promise<Wallet> { - // We assign holder of the pointer in Wallet constructor - const walletManagerPtr = walletManager.getPointer(); + async close(store: boolean): Promise<boolean> { + return await fns.WalletManager_closeWallet(this.#walletManager.getPointer(), this.#ptr, store); + } - const walletPtr = await getSymbol("WalletManager_openWallet")( - walletManagerPtr, - CString(path), - CString(password), - 0, + async seed(offset = ""): Promise<string | null> { + return await readCString( + await fns.Wallet_seed(this.#ptr, CString(offset)), ); + } - 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<Wallet> { - // We assign holder of the pointer in Wallet constructor - const walletManagerPtr = walletManager.getPointer(); - - const walletPtr = await getSymbol("WalletManager_recoveryWallet")( - walletManagerPtr, - CString(path), - CString(password), - CString(mnemonic), - 0, - restoreHeight, - 1n, - CString(seedOffset), + async address(accountIndex = 0n, addressIndex = 0n): Promise<string | null> { + return await readCString( + await fns.Wallet_address(this.#ptr, accountIndex, addressIndex), ); + } - const wallet = new Wallet(walletManager, walletPtr as WalletPtr, walletManager.sanitizer); - await wallet.throwIfError(sanitizeError); - await wallet.initWallet(); + async balance(accountIndex = 0): Promise<bigint> { + return await fns.Wallet_balance(this.#ptr, accountIndex); + } - return wallet; + async unlockedBalance(accountIndex = 0): Promise<bigint> { + return await fns.Wallet_unlockedBalance(this.#ptr, accountIndex); } - async address(accountIndex = 0n, addressIndex = 0n): Promise<string> { - const address = await getSymbol("Wallet_address")(this.#walletPtr, accountIndex, addressIndex); - if (!address) { - const error = await this.errorString(); - throw new Error(`Failed getting address from a wallet: ${error ?? "<Error unknown>"}`); - } - return await readCString(address); + async synchronized(): Promise<boolean> { + return await fns.Wallet_synchronized(this.#ptr); } - async balance(accountIndex = 0): Promise<bigint> { - return await getSymbol("Wallet_balance")(this.#walletPtr, accountIndex); + async blockChainHeight(): Promise<bigint> { + return await fns.Wallet_blockChainHeight(this.#ptr); } - async unlockedBalance(accountIndex = 0): Promise<bigint> { - return await getSymbol("Wallet_unlockedBalance")(this.#walletPtr, accountIndex); + async daemonBlockChainHeight(): Promise<bigint> { + return await fns.Wallet_daemonBlockChainHeight(this.#ptr); } - status(): Promise<number> { - return getSymbol("Wallet_status")(this.#walletPtr); + async addSubaddressAccount(label: string): Promise<void> { + return await fns.Wallet_addSubaddressAccount(this.#ptr, CString(label)); } - async errorString(): Promise<string | null> { - if (!await this.status()) return null; + async numSubaddressAccounts(): Promise<bigint> { + return await fns.Wallet_numSubaddressAccounts(this.#ptr); + } - const error = await getSymbol("Wallet_errorString")(this.#walletPtr); - if (!error) return null; + async addSubaddress(accountIndex: number, label: string): Promise<void> { + return await fns.Wallet_addSubaddress( + this.#ptr, + accountIndex, + CString(label), + ); + } - return await readCString(error) || null; + async numSubaddresses(accountIndex: number): Promise<bigint> { + return await fns.Wallet_numSubaddresses( + this.#ptr, + accountIndex, + ); } - async throwIfError(sanitize = true): Promise<void> { - const maybeError = await this.errorString(); - if (maybeError) { - if (sanitize) this.sanitizer?.(); - throw new Error(maybeError); - } + async getSubaddressLabel(accountIndex: number, addressIndex: number): Promise<string | null> { + return await readCString( + await fns.Wallet_getSubaddressLabel(this.#ptr, accountIndex, addressIndex), + ); } - async synchronized(): Promise<boolean> { - const synchronized = await getSymbol("Wallet_synchronized")(this.#walletPtr); - await this.throwIfError(); - return synchronized; + async setSubaddressLabel(accountIndex: number, addressIndex: number, label: string): Promise<void> { + return await fns.Wallet_setSubaddressLabel(this.#ptr, accountIndex, addressIndex, CString(label)); } - async blockChainHeight(): Promise<bigint> { - const height = await getSymbol("Wallet_blockChainHeight")(this.#walletPtr); - await this.throwIfError(); - return height; + async isOffline(): Promise<boolean> { + return await fns.Wallet_isOffline(this.#ptr); } - async daemonBlockChainHeight(): Promise<bigint> { - const height = await getSymbol("Wallet_daemonBlockChainHeight")(this.#walletPtr); - await this.throwIfError(); - return height; + async setOffline(offline: boolean): Promise<void> { + return await fns.Wallet_setOffline(this.#ptr, offline); } - async managerBlockChainHeight(): Promise<bigint> { - const height = await getSymbol("WalletManager_blockchainHeight")(this.#walletManagerPtr); - await this.throwIfError(); - return height; + async publicViewKey(): Promise<string | null> { + return await readCString(await fns.Wallet_publicViewKey(this.#ptr)); } - async managerTargetBlockChainHeight(): Promise<bigint> { - const height = await getSymbol("WalletManager_blockchainTargetHeight")(this.#walletManagerPtr); - await this.throwIfError(); - return height; + async secretViewKey(): Promise<string | null> { + return await readCString(await fns.Wallet_secretViewKey(this.#ptr)); } - async addSubaddressAccount(label: string): Promise<void> { - await getSymbol("Wallet_addSubaddressAccount")( - this.#walletPtr, - CString(label), - ); - await this.throwIfError(); + async publicSpendKey(): Promise<string | null> { + return await readCString(await fns.Wallet_publicSpendKey(this.#ptr)); } - async numSubaddressAccounts(): Promise<bigint> { - const accountsLen = await getSymbol("Wallet_numSubaddressAccounts")(this.#walletPtr); - await this.throwIfError(); - return accountsLen; + async secretSpendKey(): Promise<string | null> { + return await readCString(await fns.Wallet_secretSpendKey(this.#ptr)); } - async addSubaddress(accountIndex: number, label: string): Promise<void> { - await getSymbol("Wallet_addSubaddress")( - this.#walletPtr, - accountIndex, - CString(label), - ); - await this.throwIfError(); + async exportOutputs(fileName: string, all: boolean): Promise<boolean> { + return await fns.Wallet_exportOutputs(this.#ptr, CString(fileName), all); } - async numSubaddresses(accountIndex: number): Promise<bigint> { - const address = await getSymbol("Wallet_numSubaddresses")( - this.#walletPtr, - accountIndex, + async exportOutputsUR(maxFragmentLength: bigint, all: boolean): Promise<string | null> { + const exportOutputsUR = fns.Wallet_exportOutputsUR; + if (!exportOutputsUR) return null; + + return await readCString( + await exportOutputsUR(this.#ptr, maxFragmentLength, all), ); - await this.throwIfError(); - return address; } - async getSubaddressLabel(accountIndex: number, addressIndex: number): Promise<string> { - const label = await getSymbol("Wallet_getSubaddressLabel")(this.#walletPtr, accountIndex, addressIndex); - if (!label) { - const error = await this.errorString(); - throw new Error(`Failed getting subaddress label from a wallet: ${error ?? "<Error unknown>"}`); - } - return await readCString(label); + async importOutputs(fileName: string): Promise<boolean> { + return await fns.Wallet_importOutputs(this.#ptr, CString(fileName)); } - async setSubaddressLabel(accountIndex: number, addressIndex: number, label: string): Promise<void> { - await getSymbol("Wallet_setSubaddressLabel")( - this.#walletPtr, - accountIndex, - addressIndex, - CString(label), + async importOutputsUR(input: string): Promise<boolean | null> { + const importOutputsUR = fns.Wallet_importOutputsUR; + if (!importOutputsUR) return null; + + return await importOutputsUR(this.#ptr, CString(input)); + } + + async exportKeyImages(fileName: string, all: boolean): Promise<boolean> { + return await fns.Wallet_exportKeyImages(this.#ptr, CString(fileName), all); + } + + async exportKeyImagesUR(maxFragmentLength: bigint, all: boolean): Promise<string | null> { + const exportKeyImagesUR = fns.Wallet_exportKeyImagesUR; + if (!exportKeyImagesUR) return null; + + return await readCString( + await exportKeyImagesUR(this.#ptr, maxFragmentLength, all), ); - await this.throwIfError(); } - async getHistory(): Promise<TransactionHistory> { - const transactionHistoryPointer = await getSymbol("Wallet_history")(this.#walletPtr); - await this.throwIfError(); - return new TransactionHistory(transactionHistoryPointer as TransactionHistoryPtr); + async importKeyImages(fileName: string): Promise<boolean> { + return await fns.Wallet_importKeyImages(this.#ptr, CString(fileName)); + } + + async importKeyImagesUR(input: string): Promise<boolean | null> { + const importKeyImagesUR = fns.Wallet_importKeyImagesUR; + if (!importKeyImagesUR) return null; + + return await importKeyImagesUR(this.#ptr, CString(input)); + } + + async loadUnsignedTx(fileName: string): Promise<UnsignedTransaction> { + const pendingTxPtr = await fns.Wallet_loadUnsignedTx(this.#ptr, CString(fileName)); + return UnsignedTransaction.new(pendingTxPtr as UnsignedTransactionPtr); + } + + async loadUnsignedTxUR(input: string): Promise<UnsignedTransaction | null> { + const loadUnsignedTxUR = fns.Wallet_loadUnsignedTxUR; + if (!loadUnsignedTxUR) return null; + + const pendingTxPtr = await loadUnsignedTxUR(this.#ptr, CString(input)); + if (await this.status()) { + throw this.errorString(); + } + return UnsignedTransaction.new(pendingTxPtr as UnsignedTransactionPtr); } async createTransaction( destinationAddress: string, amount: bigint, - pendingTransactionPriority = 0 | 1 | 2 | 3, + pendingTransactionPriority: 0 | 1 | 2 | 3, subaddressAccount: number, - sanitize = true, prefferedInputs = "", mixinCount = 0, paymentId = "", - separator = ",", - ): Promise<PendingTransaction> { - const pendingTxPtr = await getSymbol("Wallet_createTransaction")( - this.#walletPtr, + ): Promise<PendingTransaction | null> { + const pendingTxPtr = await fns.Wallet_createTransaction( + this.#ptr, CString(destinationAddress), CString(paymentId), amount, @@ -296,13 +270,61 @@ export class Wallet { pendingTransactionPriority, subaddressAccount, CString(prefferedInputs), - CString(separator), + C_SEPARATOR, + ); + + if (!pendingTxPtr) return null; + return PendingTransaction.new(pendingTxPtr as PendingTransactionPtr); + } + + async createTransactionMultDest( + destinationAddresses: string[], + amounts: bigint[], + amountSweepAll: boolean, + pendingTransactionPriority: 0 | 1 | 2 | 3, + subaddressAccount: number, + preferredInputs: string[] = [], + mixinCount = 0, + paymentId = "", + ): Promise<PendingTransaction> { + const pendingTxPtr = await fns.Wallet_createTransactionMultDest( + this.#ptr, + CString(destinationAddresses.join(SEPARATOR)), + C_SEPARATOR, + CString(paymentId), + amountSweepAll, + CString(amounts.join(SEPARATOR)), + C_SEPARATOR, + mixinCount, + pendingTransactionPriority, + subaddressAccount, + CString(preferredInputs.join(SEPARATOR)), + C_SEPARATOR, ); - await this.throwIfError(sanitize); - return new PendingTransaction(pendingTxPtr as PendingTransactionPtr); + return PendingTransaction.new(pendingTxPtr as PendingTransactionPtr); + } + + async coins(): Promise<Coins | null> { + const coinsPtr = await fns.Wallet_coins(this.#ptr); + if (!coinsPtr) return null; + + return new Coins(coinsPtr as CoinsPtr); + } + + async status(): Promise<number> { + return await fns.Wallet_status(this.#ptr); + } + + async errorString(): Promise<string | null> { + if (!await this.status()) return null; + const error = await fns.Wallet_errorString(this.#ptr); + return await readCString(error); } - async amountFromString(amount: string): Promise<bigint> { - return await getSymbol("Wallet_amountFromString")(CString(amount)); + async throwIfError(): Promise<void> { + const maybeError = await this.errorString(); + if (maybeError) { + throw new Error(maybeError); + } } } |
