syntax = "proto3";

// Balance and amount types: on-chain balances, off-chain balances, and
// amount specifications for transactions and channel operations.

package hydra_app;

import "primitives.proto";

message OnchainBalance {
  // The amount of asset that is confirmed on-chain and available for spending.
  DecimalString confirmed = 1;
  // The amount of asset that is pending but usable for spending on-chain.
  DecimalString trusted_pending = 2;
  // The amount of asset that is pending confirmation on-chain.
  // This will become usable once the transaction has reached the required
  // number of confirmations for finality.
  DecimalString pending = 3;
}

message OffchainBalance {
  // The amount of asset on the local side of the channels that is free to
  // spend.
  DecimalString free_local = 1;
  // The amount of asset on the remote side of the channels that can be
  // received.
  DecimalString free_remote = 2;
  // The amount of asset that is pending confirmation on the local side.
  // This can include asset that is locked in channels that are being opened
  // or updated.
  DecimalString pending_local = 3;
  // The amount of asset that is pending confirmation on the remote side.
  // This can include asset that is locked in channels that are being opened
  // or updated.
  DecimalString pending_remote = 4;
  // The amount of asset that is unavailable for spending on the local side.
  // This can include local assets that are locked in channels that are
  // inactive, closed, or being closed.
  DecimalString unavailable_local = 5;
  // The amount of asset that is unavailable for spending on the remote side.
  // This can include local assets that are locked in channels that are
  // inactive, closed, or being closed.
  DecimalString unavailable_remote = 6;
  // The amount of asset that is locked in pending channel payments sent to the
  // counterparty.
  DecimalString paying_local = 7;
  // The amount of asset that is locked in pending channel payments received
  // from the counterparty.
  DecimalString paying_remote = 8;
  // The amount of local asset that is reserved for punishment in case of a
  // channel dispute or for paying fees in case of a channel closure.
  DecimalString unspendable_local_reserve = 9;
  // The amount of remote asset that is reserved for punishment in case of a
  // channel dispute or for paying fees in case of a channel closure.
  DecimalString unspendable_remote_reserve = 10;
  // The amount of local asset redeemable on-chain when the channel is
  // redeemable, zero otherwise. This is a view into unavailable_local, not an
  // additional category.
  DecimalString redeemable_local = 11;
  // The amount of remote asset redeemable on-chain when the channel is
  // redeemable, zero otherwise. This is a view into unavailable_remote, not an
  // additional category.
  DecimalString redeemable_remote = 12;
  // The largest amount a single outbound payment can move right now. Equal
  // to free_local unless the channel protocol enforces a per-payment ceiling
  // below the balance — on a Lightning channel whose value grew past the
  // max_htlc_value_in_flight negotiated at open, free_local keeps growing
  // with deposits while this stays at roughly the original channel value.
  DecimalString max_sendable = 13;
  // The largest amount a single inbound payment can deliver right now — the
  // receiving-direction counterpart of max_sendable.
  DecimalString max_receivable = 14;
}

message Balance {
  OnchainBalance onchain = 1;
  OffchainBalance offchain = 2;
}

// Specifies the amount to send in a transaction or payment.
//
// Use `All` to send the entire available balance, or `Exact` to send a
// specific amount.
message Amount {
  // Send the entire available balance.
  message All {}
  // Send a specific amount.
  message Exact {
    // The exact amount to send.
    DecimalString amount = 1;
  }

  oneof amount {
    All all = 1;
    Exact exact = 2;
  }
}

// Amount to deposit from the local wallet into a payment channel.
//
// - `All`: deposit the entire available wallet balance.
// - `Exact`: deposit a specific amount (simple single-funded case).
// - `DualFunded`: full control over balance distribution in dual-funded
//  channels.
message DepositAmount {
  // Deposit the entire available balance.
  message All {}
  // Deposit a specific amount.
  message Exact {
    // The exact amount to deposit.
    DecimalString amount = 1;
  }
  // Dual-funded deposit with explicit balance distribution.
  message DualFunded {
    // Channel balance assigned to self.
    DecimalString local = 1;
    // Channel balance assigned to the counterparty.
    DecimalString remote = 2;
    // Amount actually deposited from the local wallet.
    DecimalString self_deposit = 3;
  }

  oneof amount {
    All all = 1;
    Exact exact = 2;
    DualFunded dual_funded = 3;
  }
}

// What one side's wallet contributes to a channel update.
//
// Leaving the oneof unset means that side's wallet does not move, which
// costs less gas than naming a zero amount.
//
// `All` resolves against that side's channel balance for `Withdraw` and
// against the local wallet for `Deposit` — so `Deposit.All` is rejected on
// a peer contribution, where that wallet is not visible. On a side that also
// pays a `BalanceCredit`, `Withdraw.All` resolves to that side's withdrawable
// balance minus the credit: the on-chain movement settles first and the
// credit comes out of what is left.
message ChannelContribution {
  oneof contribution {
    // Move this amount out of the wallet and into the channel.
    Amount deposit = 1;
    // Move this amount out of the channel and into the wallet.
    Amount withdraw = 2;
  }
}

// Balance credited to one side beyond what its own wallet moved, settled in
// the co-signed state that follows the on-chain update.
//
// It touches no wallet and reaches no chain. Leaving the oneof unset means
// nothing crosses between the sides.
message BalanceCredit {
  oneof credit {
    // Credit this much of the local side's balance to the counterparty.
    DecimalString to_peer = 1;
    // Credit this much of the counterparty's balance to the local side.
    DecimalString to_self = 2;
  }
}

// One asset's share of a channel update.
//
// The two contributions must not cancel: the chain refuses an update that
// leaves the channel holding what it already held. Contributions that cancel
// are a payment, not an update.
message ChannelUpdateAmount {
  // What the local wallet contributes.
  ChannelContribution self_contribution = 1;
  // What the counterparty's wallet contributes.
  ChannelContribution peer_contribution = 2;
  // What crosses between the two sides once both have settled.
  BalanceCredit credit = 3;
}

// Local and remote balance distribution in a channel.
//
// Used in channel operation events (opening, deposit, withdrawal) to report
// how funds are distributed between the two parties.
message ChannelBalances {
  // Amount assigned to the local party.
  DecimalString local = 1;
  // Amount assigned to the remote party.
  DecimalString remote = 2;
}
