import { WalletManager } from "./wallet_manager.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 { #walletManager: WalletManager; #ptr: WalletPtr; constructor(walletManager: WalletManager, ptr: WalletPtr) { this.#walletManager = walletManager; this.#ptr = ptr; } getPointer() { return this.#ptr; } async init(daemonInfo: DaemonInfo, log = false): Promise { 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, ); } await this.setTrustedDaemon(true); await this.startRefresh(); await this.refreshAsync(); return success; } async setTrustedDaemon(value: boolean): Promise { return await fns.Wallet_setTrustedDaemon(this.#ptr, value); } async startRefresh(): Promise { return await fns.Wallet_startRefresh(this.#ptr); } async refreshAsync(): Promise { return await fns.Wallet_refreshAsync(this.#ptr); } async setupBackgroundSync( backgroundSyncType: number, walletPassword: string, backgroundCachePassword: string, ): Promise { return await fns.Wallet_setupBackgroundSync( this.#ptr, backgroundSyncType, CString(walletPassword), CString(backgroundCachePassword), ); } async startBackgroundSync(): Promise { return await fns.Wallet_startBackgroundSync(this.#ptr); } async stopBackgroundSync(walletPassword: string): Promise { return await fns.Wallet_stopBackgroundSync(this.#ptr, CString(walletPassword)); } async store(path = ""): Promise { return await fns.Wallet_store(this.#ptr, CString(path)); } async close(store: boolean): Promise { return await fns.WalletManager_closeWallet(this.#walletManager.getPointer(), this.#ptr, store); } async seed(offset = ""): Promise { return await readCString( await fns.Wallet_seed(this.#ptr, CString(offset)), ); } async address(accountIndex = 0n, addressIndex = 0n): Promise { return await readCString( await fns.Wallet_address(this.#ptr, accountIndex, addressIndex), ); } async setRefreshFromBlockHeight(height = 0n): Promise { return await fns.Wallet_setRefreshFromBlockHeight(this.#ptr, height); } async balance(accountIndex = 0): Promise { return await fns.Wallet_balance(this.#ptr, accountIndex); } async unlockedBalance(accountIndex = 0): Promise { return await fns.Wallet_unlockedBalance(this.#ptr, accountIndex); } async synchronized(): Promise { return await fns.Wallet_synchronized(this.#ptr); } async blockChainHeight(): Promise { return await fns.Wallet_blockChainHeight(this.#ptr); } async daemonBlockChainHeight(): Promise { return await fns.Wallet_daemonBlockChainHeight(this.#ptr); } async addSubaddressAccount(label: string): Promise { return await fns.Wallet_addSubaddressAccount(this.#ptr, CString(label)); } async numSubaddressAccounts(): Promise { return await fns.Wallet_numSubaddressAccounts(this.#ptr); } async addSubaddress(accountIndex: number, label: string): Promise { return await fns.Wallet_addSubaddress( this.#ptr, accountIndex, CString(label), ); } async numSubaddresses(accountIndex: number): Promise { return await fns.Wallet_numSubaddresses( this.#ptr, accountIndex, ); } async getSubaddressLabel(accountIndex: number, addressIndex: number): Promise { return await readCString( await fns.Wallet_getSubaddressLabel(this.#ptr, accountIndex, addressIndex), ); } async setSubaddressLabel(accountIndex: number, addressIndex: number, label: string): Promise { return await fns.Wallet_setSubaddressLabel(this.#ptr, accountIndex, addressIndex, CString(label)); } async isOffline(): Promise { return await fns.Wallet_isOffline(this.#ptr); } async setOffline(offline: boolean): Promise { return await fns.Wallet_setOffline(this.#ptr, offline); } async publicViewKey(): Promise { return await readCString(await fns.Wallet_publicViewKey(this.#ptr)); } async secretViewKey(): Promise { return await readCString(await fns.Wallet_secretViewKey(this.#ptr)); } async publicSpendKey(): Promise { return await readCString(await fns.Wallet_publicSpendKey(this.#ptr)); } async secretSpendKey(): Promise { return await readCString(await fns.Wallet_secretSpendKey(this.#ptr)); } async exportOutputs(fileName: string, all: boolean): Promise { return await fns.Wallet_exportOutputs(this.#ptr, CString(fileName), all); } async exportOutputsUR(maxFragmentLength: bigint, all: boolean): Promise { const exportOutputsUR = fns.Wallet_exportOutputsUR; if (!exportOutputsUR) return null; return await readCString( await exportOutputsUR(this.#ptr, maxFragmentLength, all), ); } async importOutputs(fileName: string): Promise { return await fns.Wallet_importOutputs(this.#ptr, CString(fileName)); } async importOutputsUR(input: string): Promise { const importOutputsUR = fns.Wallet_importOutputsUR; if (!importOutputsUR) return null; return await importOutputsUR(this.#ptr, CString(input)); } async exportKeyImages(fileName: string, all: boolean): Promise { return await fns.Wallet_exportKeyImages(this.#ptr, CString(fileName), all); } async exportKeyImagesUR(maxFragmentLength: bigint, all: boolean): Promise { const exportKeyImagesUR = fns.Wallet_exportKeyImagesUR; if (!exportKeyImagesUR) return null; return await readCString( await exportKeyImagesUR(this.#ptr, maxFragmentLength, all), ); } async importKeyImages(fileName: string): Promise { return await fns.Wallet_importKeyImages(this.#ptr, CString(fileName)); } async importKeyImagesUR(input: string): Promise { const importKeyImagesUR = fns.Wallet_importKeyImagesUR; if (!importKeyImagesUR) return null; return await importKeyImagesUR(this.#ptr, CString(input)); } async loadUnsignedTx(fileName: string): Promise { const pendingTxPtr = await fns.Wallet_loadUnsignedTx(this.#ptr, CString(fileName)); return UnsignedTransaction.new(pendingTxPtr as UnsignedTransactionPtr); } async loadUnsignedTxUR(input: string): Promise { 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, subaddressAccount: number, prefferedInputs = "", mixinCount = 0, paymentId = "", ): Promise { const pendingTxPtr = await fns.Wallet_createTransaction( this.#ptr, CString(destinationAddress), CString(paymentId), amount, mixinCount, pendingTransactionPriority, subaddressAccount, CString(prefferedInputs), 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 { 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, ); if (!pendingTxPtr) return null; return PendingTransaction.new(pendingTxPtr as PendingTransactionPtr); } async coins(): Promise { const coinsPtr = await fns.Wallet_coins(this.#ptr); if (!coinsPtr) return null; return new Coins(coinsPtr as CoinsPtr); } async status(): Promise { return await fns.Wallet_status(this.#ptr); } async errorString(): Promise { if (!await this.status()) return null; const error = await fns.Wallet_errorString(this.#ptr); return await readCString(error); } async throwIfError(): Promise { const maybeError = await this.errorString(); if (maybeError) { throw new Error(maybeError); } } }