Wallet

Struct Wallet 

Source
pub struct Wallet {
    pub chain: Arc<ChainSource>,
    pub exit: RwLock<Exit>,
    /* private fields */
}
Expand description

The central entry point for using this library as an Ark wallet.

Overview

Key capabilities

  • Address management:
    • derive and peek deterministic Ark addresses and their indices
  • Funds lifecycle:
    • board funds from an external onchain wallet onto the Ark
    • send out-of-round Ark payments (arkoor)
    • offboard funds to onchain addresses
    • manage HTLCs and Lightning receives/sends
  • VTXO management:
    • query spendable and pending VTXOs
    • refresh expiring or risky VTXOs
    • compute balance broken down by spendable/pending states
  • Synchronization and maintenance:
    • sync against the Ark server and the onchain source
    • reconcile pending rounds, exits, and offchain state
    • periodic maintenance helpers (e.g., auto-register boards, refresh policies)

Construction and persistence

Example

let network = Network::Signet;
let mnemonic = Mnemonic::generate(12)?;
let cfg = Config {
  server_address: String::from("https://ark.signet.2nd.dev"),
  esplora_address: Some(String::from("https://esplora.signet.2nd.dev")),
  ..Default::default()
};

// You can either use the included SQLite implementation or create your own.
let persister = SqliteClient::open(db_path).await?;
let db: Arc<dyn BarkPersister> = Arc::new(persister);

// Load or create an onchain wallet if needed
let onchain_wallet = OnchainWallet::load_or_create(network, mnemonic.to_seed(""), db.clone())?;

// Create or open the Ark wallet
let mut wallet = Wallet::create_with_onchain(
	&mnemonic,
	network,
	cfg.clone(),
	db,
	&onchain_wallet,
	false,
).await?;
// let mut wallet = Wallet::create(&mnemonic, network, cfg.clone(), db.clone(), false).await?;
// let mut wallet = Wallet::open(&mnemonic, db.clone(), cfg.clone()).await?;
// let mut wallet = Wallet::open_with_onchain(
//    &mnemonic, network, cfg.clone(), db.clone(), &onchain_wallet
// ).await?;

// There are two main ways to update the wallet, the primary is to use one of the maintenance
// commands which will sync everything, refresh VTXOs and reconcile pending lightning payments.
wallet.maintenance().await?;
wallet.maintenance_with_onchain(&mut onchain_wallet).await?;

// Alternatively, you can use the fine-grained sync commands to sync individual parts of the
// wallet state and use `maintenance_refresh` where necessary to refresh VTXOs.
wallet.sync().await?;
wallet.sync_pending_lightning_send_vtxos().await?;
wallet.register_all_confirmed_boards(&mut onchain_wallet).await?;
wallet.sync_exits(&mut onchain_wallet).await?;
wallet.maintenance_refresh().await?;

// Generate a new Ark address to receive funds via arkoor
let addr = wallet.new_address()?;

// Query balance and VTXOs
let balance = wallet.balance()?;
let vtxos = wallet.vtxos()?;

// Progress any unilateral exits, make sure to sync first
wallet.exit.progress_exit(&mut onchain_wallet, None).await?;

Fields§

§chain: Arc<ChainSource>

The chain source the wallet is connected to

§exit: RwLock<Exit>

Exit subsystem handling unilateral exits and on-chain reconciliation outside Ark rounds.

Implementations§

Source§

impl Wallet

Source

pub fn chain_source<P: BarkPersister>( config: &Config, ) -> Result<ChainSourceSpec>

Creates a onchain::ChainSource instance to communicate with an onchain backend from the given Config.

Source

pub fn require_chainsource_version(&self) -> Result<()>

Verifies that the bark Wallet can be used with the configured onchain::ChainSource. More specifically, if the onchain::ChainSource connects to Bitcoin Core it must be a high enough version to support ephemeral anchors.

Source

pub fn derive_store_next_keypair(&self) -> Result<(Keypair, u32)>

Derive and store the keypair directly after currently last revealed one, together with its index.

Source

pub fn peak_keypair(&self, index: u32) -> Result<Keypair>

Retrieves a keypair based on the provided index and checks if the corresponding public key exists in the Vtxo database.

§Arguments
  • index - The index used to derive a keypair.
§Returns
  • Ok(Keypair) - If the keypair is successfully derived and its public key exists in the database.
  • Err(anyhow::Error) - If the public key does not exist in the database or if an error occurs during the database query.
Source

pub fn pubkey_keypair( &self, public_key: &PublicKey, ) -> Result<Option<(u32, Keypair)>>

Retrieves the Keypair for a provided PublicKey

§Arguments
  • public_key - The public key for which the keypair must be found
§Returns
  • Ok(Some(u32, Keypair)) - If the pubkey is found, the derivation-index and keypair are returned
  • Ok(None) - If the pubkey cannot be found in the database
  • Err(anyhow::Error) - If an error occurred related to the database query
Source

pub fn get_vtxo_key(&self, vtxo: &Vtxo) -> Result<Keypair>

Retrieves the Keypair for a provided Vtxo

§Arguments
  • vtxo - The vtxo for which the key must be found
§Returns
  • Ok(Some(Keypair)) - If the pubkey is found, the keypair is returned
  • Err(anyhow::Error) - If the corresponding public key doesn’t exist in the database or a database error occurred.
Source

pub fn new_address(&self) -> Result<Address>

Generate a new ark::Address.

Source

pub fn peak_address(&self, index: u32) -> Result<Address>

Peak for an ark::Address at the given key index.

May return an error if the address at the given index has not been derived yet.

Source

pub fn new_address_with_index(&self) -> Result<(Address, u32)>

Generate a new ark::Address and returns the index of the key used to create it.

This derives and stores the keypair directly after currently last revealed one.

Source

pub async fn create<P: BarkPersister>( mnemonic: &Mnemonic, network: Network, config: Config, db: Arc<P>, force: bool, ) -> Result<Wallet>

Create a new wallet without an optional onchain backend. This will restrict features such as boarding and unilateral exit.

The force flag will allow you to create the wallet even if a connection to the Ark server cannot be established, it will not overwrite a wallet which has already been created.

Source

pub async fn create_with_onchain<P: BarkPersister, W: ExitUnilaterally>( mnemonic: &Mnemonic, network: Network, config: Config, db: Arc<P>, onchain: &W, force: bool, ) -> Result<Wallet>

Create a new wallet with an onchain backend. This enables full Ark functionality. A default implementation of an onchain wallet when the onchain_bdk feature is enabled. See [onchain::OnchainWallet] for more details. Alternatively, implement ExitUnilaterally if you have your own onchain wallet implementation.

The force flag will allow you to create the wallet even if a connection to the Ark server cannot be established, it will not overwrite a wallet which has already been created.

Source

pub async fn open<P: BarkPersister>( mnemonic: &Mnemonic, db: Arc<P>, config: Config, ) -> Result<Wallet>

Loads the bark wallet from the given database ensuring the fingerprint remains consistent.

Source

pub async fn open_with_onchain<P: BarkPersister, W: ExitUnilaterally>( mnemonic: &Mnemonic, db: Arc<P>, onchain: &W, cfg: Config, ) -> Result<Wallet>

Similar to Wallet::open however this also unilateral exits using the provided onchain wallet.

Source

pub fn config(&self) -> &Config

Returns the config used to create/load the bark Wallet.

Source

pub fn properties(&self) -> Result<WalletProperties>

Retrieves the WalletProperties of the current bark Wallet.

Source

pub fn ark_info(&self) -> Option<&ArkInfo>

Return ArkInfo fetched on last handshake with the Ark server

Source

pub fn balance(&self) -> Result<Balance>

Return the Balance of the wallet.

Make sure you sync before calling this method.

Source

pub fn get_vtxo_by_id(&self, vtxo_id: VtxoId) -> Result<WalletVtxo>

Retrieves the full state of a Vtxo for a given VtxoId if it exists in the database.

Source

pub fn movements(&self) -> Result<Vec<Movement>>

Fetches all wallet fund movements ordered from newest to oldest.

Source

pub fn all_vtxos(&self) -> Result<Vec<WalletVtxo>>

Returns all VTXOs from the database.

Source

pub fn vtxos(&self) -> Result<Vec<WalletVtxo>>

Returns all not spent vtxos

Source

pub fn vtxos_with(&self, filter: &impl FilterVtxos) -> Result<Vec<WalletVtxo>>

Returns all vtxos matching the provided predicate

Source

pub fn spendable_vtxos(&self) -> Result<Vec<WalletVtxo>>

Returns all spendable vtxos

Source

pub fn spendable_vtxos_with( &self, filter: &impl FilterVtxos, ) -> Result<Vec<WalletVtxo>>

Returns all spendable vtxos matching the provided predicate

Source

pub fn inround_vtxos_with( &self, filter: &impl FilterVtxos, ) -> Result<Vec<WalletVtxo>>

Returns all in-round VTXOs matching the provided predicate

Source

pub fn pending_board_vtxos(&self) -> Result<Vec<WalletVtxo>>

Queries the database for any VTXO that is an unregistered board. There is a lag time between when a board is created and when it becomes spendable.

See ArkInfo::required_board_confirmations and Wallet::sync_pending_boards.

Source

pub fn pending_lightning_send_vtxos(&self) -> Result<Vec<WalletVtxo>>

Queries the database for any VTXO that is an pending lightning send.

Source

pub async fn get_expiring_vtxos( &self, threshold: BlockHeight, ) -> Result<Vec<WalletVtxo>>

Returns all vtxos that will expire within threshold blocks

Source

pub async fn sync_pending_boards(&self) -> Result<()>

Attempts to register all pendings boards with the Ark server. A board transaction must have sufficient confirmations before it will be registered. For more details see ArkInfo::required_board_confirmations.

Source

pub async fn maintenance(&self) -> Result<()>

Performs maintenance tasks on the offchain wallet.

This can take a long period of time due to syncing rounds, arkoors, checking pending payments and refreshing VTXOs if necessary.

Source

pub async fn maintenance_with_onchain<W: PreparePsbt + SignPsbt + ExitUnilaterally>( &self, onchain: &mut W, ) -> Result<()>

Performs maintenance tasks on the onchain and offchain wallet.

This can take a long period of time due to syncing the onchain wallet, registering boards, syncing rounds, arkoors, and the exit system, checking pending lightning payments and refreshing VTXOs if necessary.

Source

pub async fn maintenance_refresh(&self) -> Result<Option<RoundId>>

Performs a refresh of all VTXOs that are due to be refreshed, if any. This will include any VTXOs within the expiry threshold (Config::vtxo_refresh_expiry_threshold) or those which are uneconomical to exit due to onchain network conditions.

Returns a RoundId if a refresh occurs.

Source

pub async fn sync(&self)

Sync offchain wallet and update onchain fees. This is a much more lightweight alternative to Wallet::maintenance as it will not refresh VTXOs or sync the onchain wallet.

Notes:

Source

pub async fn sync_exits<W: ExitUnilaterally>( &self, onchain: &mut W, ) -> Result<()>

Sync the transaction status of unilateral exits

This will not progress the unilateral exits in any way, it will merely check the transaction status of each transaction as well as check whether any exits have become claimable or have been claimed.

Source

pub async fn sync_pending_lightning_send_vtxos(&self) -> Result<()>

Syncs pending lightning payments, verifying whether the payment status has changed and creating a revocation VTXO if necessary.

Source

pub async fn dangerous_drop_vtxo(&self, vtxo_id: VtxoId) -> Result<()>

Drop a specific Vtxo from the database. This is destructive and will result in a loss of funds.

Source

pub async fn dangerous_drop_all_vtxos(&self) -> Result<()>

Drop all VTXOs from the database. This is destructive and will result in a loss of funds.

Source

pub async fn board_amount<W: PreparePsbt + SignPsbt + GetWalletTx>( &self, onchain: &mut W, amount: Amount, ) -> Result<Board>

Board a Vtxo with the given amount.

NB we will spend a little more onchain to cover fees.

Source

pub async fn board_all<W: PreparePsbt + SignPsbt + GetWalletTx>( &self, onchain: &mut W, ) -> Result<Board>

Board a Vtxo with all the funds in your onchain wallet.

Source

pub async fn sync_past_rounds(&self) -> Result<()>

Sync all past rounds

Intended for recovery after data loss.

Source

pub async fn offboard_all(&mut self, address: Address) -> Result<Offboard>

Offboard all VTXOs to a given bitcoin::Address.

Source

pub async fn offboard_vtxos<V: VtxoRef>( &mut self, vtxos: impl IntoIterator<Item = V>, address: Address, ) -> Result<Offboard>

Offboard the given VTXOs to a given bitcoin::Address.

Source

pub async fn refresh_vtxos<V: VtxoRef>( &self, vtxos: impl IntoIterator<Item = V>, ) -> Result<Option<RoundId>>

This will refresh all provided VTXOs. Note that attempting to refresh a board VTXO which has not yet confirmed will result in an error.

Returns the RoundId of the round if a successful refresh occurred. It will return None if no Vtxo needed to be refreshed.

Source

pub async fn get_vtxos_to_refresh(&self) -> Result<Vec<WalletVtxo>>

This will find all VTXOs that meets must-refresh criteria. Then, if there are some VTXOs to refresh, it will also add those that meet should-refresh criteria.

Source

pub fn get_first_expiring_vtxo_blockheight(&self) -> Result<Option<BlockHeight>>

Returns the block height at which the first VTXO will expire

Source

pub fn get_next_required_refresh_blockheight( &self, ) -> Result<Option<BlockHeight>>

Returns the next block height at which we have a VTXO that we want to refresh

Source

pub fn validate_arkoor_address(&self, address: &Address) -> Result<()>

Validate if we can send arkoor payments to the given ark::Address, for example an error will be returned if the given ark::Address belongs to a different server (see ark::address::ArkId).

Source

pub async fn send_arkoor_payment( &self, destination: &Address, amount: Amount, ) -> Result<Vec<Vtxo>>

Makes an out-of-round payment to the given ark::Address. This does not require waiting for a round, so it should be relatively instantaneous.

If the Wallet doesn’t contain a VTXO larger than the given Amount, multiple payments will be chained together, resulting in the recipient receiving multiple VTXOs.

Note that a change Vtxo may be created as a result of this call. With each payment these will become more uneconomical to unilaterally exit, so you should eventually refresh them with Wallet::refresh_vtxos or periodically call Wallet::maintenance_refresh.

Source

pub async fn send_lightning_payment( &self, invoice: Invoice, user_amount: Option<Amount>, ) -> Result<Preimage>

Pays a Lightning Invoice using Ark VTXOs. This is also an out-of-round payment so the same Wallet::send_arkoor_payment rules apply.

Source

pub async fn check_lightning_payment( &self, payment: &PendingLightningSend, ) -> Result<Option<Preimage>>

Checks the status of a lightning payment associated with a set of VTXOs, processes the payment result and optionally takes appropriate actions based on the payment outcome.

§Arguments
  • htlc_vtxos - Slice of WalletVtxo objects that represent HTLC outputs involved in the payment.
§Returns

Returns Ok(Some(Preimage)) if the payment is successfully completed and a preimage is received. Returns Ok(None) for payments still pending, failed payments or if necessary revocation or exit processing occurs. Returns an Err if an error occurs during the process.

§Behavior
  • Validates that all HTLC VTXOs share the same invoice, amount and policy.
  • Sends a request to the lightning payment server to check the payment status.
  • Depending on the payment status:
    • Failed: Revokes the associated VTXOs.
    • Pending: Checks if the HTLC has expired based on the tip height. If expired, revokes the VTXOs.
    • Complete: Extracts the payment preimage, logs the payment, registers movement in the database and returns
Source

pub async fn bolt11_invoice(&self, amount: Amount) -> Result<Bolt11Invoice>

Create, store and return a Bolt11Invoice for offchain boarding

Source

pub fn lightning_receive_status( &self, payment: impl Into<PaymentHash>, ) -> Result<Option<LightningReceive>>

Fetches the status of a lightning receive for the given PaymentHash.

Source

pub fn pending_lightning_receives(&self) -> Result<Vec<LightningReceive>>

Fetches all pending lightning receives ordered from newest to oldest.

Source

pub fn pending_lightning_receive_balance( &self, ) -> Result<LightningReceiveBalance>

Source

pub async fn check_ln_receive( &self, payment_hash: PaymentHash, wait: bool, ) -> Result<LightningReceive>

Check for incoming lightning payment with the given PaymentHash.

This function checks for an incoming lightning payment with the given PaymentHash and returns the HTLC VTXOs that are associated with it.

§Arguments
  • payment_hash - The PaymentHash of the lightning payment to check for.
  • wait - Whether to wait for the payment to be received.
§Returns

Returns an anyhow::Result<Vec<WalletVtxo>>, which is:

  • Ok(wallet_vtxos) if the process completes successfully, where wallet_vtxos is the list of HTLC VTXOs that are associated with the payment.
  • Err if an error occurs at any stage of the operation.
§Remarks
  • The invoice must contain an explicit amount specified in milli-satoshis.
  • The HTLC expiry height is calculated by adding the servers’ HTLC expiry delta to the current chain tip.
  • The payment hash must be from an invoice previously generated using Wallet::bolt11_invoice.
Source

pub async fn check_and_claim_ln_receive( &self, payment_hash: PaymentHash, wait: bool, ) -> Result<()>

Check and claim a Lightning receive

This function checks for an incoming lightning payment with the given PaymentHash and then claims the payment using returned HTLC VTXOs.

§Arguments
  • payment_hash - The PaymentHash of the lightning payment to check for.
  • wait - Whether to wait for the payment to be received.
§Returns

Returns an anyhow::Result<()>, which is:

  • Ok(()) if the process completes successfully.
  • Err if an error occurs at any stage of the operation.
§Remarks
Source

pub async fn check_and_claim_all_open_ln_receives( &self, wait: bool, ) -> Result<()>

Check and claim all opened Lightning receive

This function fetches all opened lightning receives and then concurrently tries to check and claim them

§Arguments
  • wait - Whether to wait for each payment to be received.
§Returns

Returns an anyhow::Result<()>, which is:

  • Ok(()) if the process completes successfully.
  • Err if an error occurs at any stage of the operation.
Source

pub async fn send_lnaddr( &self, addr: &LightningAddress, amount: Amount, comment: Option<&str>, ) -> Result<(Bolt11Invoice, Preimage)>

Same as Wallet::send_lightning_payment but instead it pays a LightningAddress.

Source

pub async fn pay_offer( &self, offer: Offer, amount: Option<Amount>, ) -> Result<(Bolt12Invoice, Preimage)>

Attempts to pay the given BOLT12 Offer using offchain funds.

Source

pub async fn send_round_onchain_payment( &self, addr: Address, amount: Amount, ) -> Result<Offboard>

Sends the given Amount to an onchain bitcoin::Address. This is an in-round operation which may take a long time to perform.

Auto Trait Implementations§

§

impl !Freeze for Wallet

§

impl !RefUnwindSafe for Wallet

§

impl Send for Wallet

§

impl Sync for Wallet

§

impl Unpin for Wallet

§

impl !UnwindSafe for Wallet

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoRequest<T> for T

Source§

fn into_request(self) -> Request<T>

Wrap the input message T in a tonic::Request
Source§

impl<L> LayerExt<L> for L

Source§

fn named_layer<S>(&self, service: S) -> Layered<<L as Layer<S>>::Service, S>
where L: Layer<S>,

Applies the layer to a service and wraps it in Layered.
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<T> ErasedDestructor for T
where T: 'static,