Resolve "WIP: UTXO Selection and Storage"
This commit is contained in:
@@ -0,0 +1,154 @@
|
||||
import {
|
||||
type InputTemplateBCH,
|
||||
type TransactionTemplate,
|
||||
type WalletAddresses,
|
||||
type WalletTransactions,
|
||||
} from './types.js';
|
||||
|
||||
import { type BlockchainUTXOs } from '../blockchain';
|
||||
import { type EventMap, EventEmitter } from '../utils';
|
||||
|
||||
import { type TokenBalances, type Address } from '@xocash/primitives';
|
||||
|
||||
/**
|
||||
* Common interface for all wallet types.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* All function signatures are deliberately asynchronous to accommodate for cases where wallets might be remote.
|
||||
* For example, we might eventually want to support a multisig service.
|
||||
* Or we might have to support some other custodial "Apple Pay"-like OS-interface to get accepted onto their app store.
|
||||
*/
|
||||
export abstract class BaseWallet<
|
||||
WalletEvents extends EventMap,
|
||||
> extends EventEmitter<WalletEvents> {
|
||||
/**
|
||||
* Start monitoring this wallet for any transaction activity.
|
||||
*/
|
||||
abstract start(): Promise<void>;
|
||||
|
||||
/**
|
||||
* Stop monitoring this wallet for any transaction activity.
|
||||
*/
|
||||
abstract stop(): Promise<void>;
|
||||
|
||||
/**
|
||||
* Remove any event listeners from this wallet.
|
||||
*/
|
||||
abstract destroy(): Promise<void>;
|
||||
|
||||
/**
|
||||
* Fetch all transactions from the blockchain involving this wallet.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* We will want to add a query argument so that workers can use this efficiently:
|
||||
*
|
||||
* ```ts
|
||||
* {
|
||||
* limit?: number;
|
||||
* offset?: number;
|
||||
* sort?: () => number;
|
||||
* filter?: () => boolean;
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* This "query" argument should be turned into a generic type as we will want to re-use it for Activities.
|
||||
*/
|
||||
abstract getTransactions(): Promise<WalletTransactions>;
|
||||
|
||||
/**
|
||||
* Fetch all unspents from the blockchain belonging to this wallet.
|
||||
*/
|
||||
abstract getUnspents(): Promise<BlockchainUTXOs>;
|
||||
|
||||
/**
|
||||
* Fetch all unspents from the blockchain belonging to this wallet.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* I was considering removing this and just storing unspents as "UTXOSignable"s.
|
||||
* But that might not be ideal if we want to have Watch-only wallets.
|
||||
* A better approach might be to have Fetch Unspents return `Array<UTXO | UTXOSignable>`
|
||||
* Still need to flesh that out.
|
||||
*
|
||||
* EDIT: We're going to want to store state for caching anyway...
|
||||
* May as well just getUnspentDirectives() from the local state instead of fetch.
|
||||
* Likewise for balances.
|
||||
*/
|
||||
abstract getUnspentDirectives(): Promise<Array<InputTemplateBCH>>;
|
||||
|
||||
/**
|
||||
* Get the satoshi balance of this wallet.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* Consider confirmed/unconfirmed balances (or some other representation).
|
||||
*
|
||||
* This becomes important in some instances because services like BitPay require one confirmation.
|
||||
* This'll also have bearing on how we define our UTXO Selection strategies.
|
||||
*/
|
||||
abstract getBalanceSats(): Promise<bigint>;
|
||||
|
||||
/**
|
||||
* Get the token balance of this wallet.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* Consider confirmed/unconfirmed balances (or some other representation).
|
||||
*
|
||||
* This becomes important in some instances because services like BitPay require one confirmation.
|
||||
* This'll also have bearing on how we define our UTXO Selection strategies.
|
||||
*/
|
||||
abstract getBalanceTokens(): Promise<TokenBalances>;
|
||||
|
||||
/**
|
||||
* Get all addresses belonging to this wallet.
|
||||
*/
|
||||
abstract getAddresses(): Promise<WalletAddresses>;
|
||||
|
||||
/**
|
||||
* Get the address that this wallet should receive to.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* Not all wallets will have an address (e.g. a HD Wallet), but should still be able to return an address that:
|
||||
* a) Change will be sent to.
|
||||
* b) Funds should be received to.
|
||||
*/
|
||||
abstract getReceivingAddress(): Promise<Address>;
|
||||
|
||||
/**
|
||||
* Select UTXOs from this wallet to meet the amounts required.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* TODO: We are going to want to return the Transaction that was compiled.
|
||||
*
|
||||
* TODO: This should accept a second argument (probably function) that can filter/sory UTXOs.
|
||||
* The intent here is to provide a "spending policy". E.g. Only use (or prioritise) UTXOs with 1-conf.
|
||||
*/
|
||||
abstract signTransaction(
|
||||
template: Partial<TransactionTemplate>,
|
||||
): Promise<Uint8Array>;
|
||||
|
||||
/**
|
||||
* Select UTXOs from this wallet to meet the amounts required and broadcast it to the Blockchain.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* TODO: We are going to want to return the Transaction that was compiled.
|
||||
*/
|
||||
abstract sendTransaction(
|
||||
template: Partial<TransactionTemplate>,
|
||||
): Promise<void>;
|
||||
|
||||
// TODO: This should be a push-only list.
|
||||
// Need to understand how Jason's pruning approach works.
|
||||
// It might make more sense to "key" activities by type:
|
||||
// This would allow us to filter more effectively each time a new activity is added.
|
||||
// As it stands, we would have to collate the entire list if it's done by timestamp.
|
||||
abstract addActivity<T>(activity: T): Promise<void>;
|
||||
|
||||
abstract export(): Promise<string>;
|
||||
}
|
||||
Reference in New Issue
Block a user