rust_blocktank_client/types/
blocktank.rs

1use crate::BlocktankError;
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
5#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
6pub enum BitcoinNetworkEnum {
7    #[serde(rename = "mainnet")]
8    Mainnet,
9    #[serde(rename = "testnet")]
10    Testnet,
11    #[serde(rename = "signet")]
12    Signet,
13    #[serde(rename = "regtest")]
14    Regtest,
15}
16
17#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
18pub enum BtBolt11InvoiceState {
19    /// Expect payment
20    #[serde(rename = "pending")]
21    Pending,
22    /// Payment received but not confirmed/rejected yet. Only possible with HODL invoices.
23    #[serde(rename = "holding")]
24    Holding,
25    /// Payment confirmed
26    #[serde(rename = "paid")]
27    Paid,
28    /// Payment rejected or invoice expired.
29    #[serde(rename = "canceled")]
30    Canceled,
31}
32
33#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
34pub enum BtChannelOrderErrorType {
35    /// Order is not in the right state to open a channel. Should be `order.state`=`created` and `order.payment.state`=`paid`.
36    #[serde(rename = "WRONG_ORDER_STATE")]
37    WrongOrderState,
38    /// Could not establish connection to peer.
39    #[serde(rename = "PEER_NOT_REACHABLE")]
40    PeerNotReachable,
41    /// Peer rejected channel open request.
42    #[serde(rename = "CHANNEL_REJECTED_BY_DESTINATION")]
43    ChannelRejectedByDestination,
44    /// LSP rejected channel open request.
45    #[serde(rename = "CHANNEL_REJECTED_BY_LSP")]
46    ChannelRejectedByLsp,
47    /// Blocktank service is temporarily unavailable.
48    #[serde(rename = "BLOCKTANK_NOT_READY")]
49    BlocktankNotReady,
50}
51
52#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
53pub enum BtOpenChannelState {
54    /// Channel is waiting for the required confirmations.
55    #[serde(rename = "opening")]
56    Opening,
57    /// Channel is ready to transact.
58    #[serde(rename = "open")]
59    Open,
60    /// Channel is has been closed with at least 1 onchain confirmation.
61    #[serde(rename = "closed")]
62    Closed,
63}
64
65/// @deprecated Use BtOrderState2 instead.
66#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
67pub enum BtOrderState {
68    #[serde(rename = "created")]
69    Created,
70    /// No payment made, order expired.
71    #[serde(rename = "expired")]
72    Expired,
73    #[serde(rename = "open")]
74    Open,
75    #[serde(rename = "closed")]
76    Closed,
77}
78
79#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
80pub enum BtOrderState2 {
81    /// Order created. Ready to receive payment.
82    #[serde(rename = "created")]
83    Created,
84    /// Order expired.
85    #[serde(rename = "expired")]
86    Expired,
87    /// Order successfully executed.
88    #[serde(rename = "executed")]
89    Executed,
90    /// Order paid and ready to open channel.
91    #[serde(rename = "paid")]
92    Paid,
93}
94
95/// @deprecated Use BtPaymentState2 instead.
96#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
97pub enum BtPaymentState {
98    /// Ready to receive payments
99    #[serde(rename = "created")]
100    Created,
101    /// Partially paid order will just be displayed as `created`.
102    #[serde(rename = "partiallyPaid")]
103    PartiallyPaid,
104    /// Order is paid
105    #[serde(rename = "paid")]
106    Paid,
107    /// Order is refunded.
108    #[serde(rename = "refunded")]
109    Refunded,
110    /// Onchain refunds can't be done automatically. `refundAvailable` is displayed in this case.
111    #[serde(rename = "refundAvailable")]
112    RefundAvailable,
113}
114
115#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
116pub enum BtPaymentState2 {
117    /// Ready to receive payments
118    #[serde(rename = "created")]
119    Created,
120    /// Order is paid
121    #[serde(rename = "paid")]
122    Paid,
123    /// Order is refunded.
124    #[serde(rename = "refunded")]
125    Refunded,
126    /// Onchain refunds can't be done automatically. `refundAvailable` is displayed in this case.
127    #[serde(rename = "refundAvailable")]
128    RefundAvailable,
129    /// Payments not possible anymore.
130    #[serde(rename = "canceled")]
131    Canceled,
132}
133
134#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
135pub enum CJitStateEnum {
136    /// Invoice is ready to receive funds.
137    #[serde(rename = "created")]
138    Created,
139    /// Channel opened and funds pushed to client.
140    #[serde(rename = "completed")]
141    Completed,
142    /// Invoice expired.
143    #[serde(rename = "expired")]
144    Expired,
145    /// Channel open failed.
146    #[serde(rename = "failed")]
147    Failed,
148}
149
150#[derive(Debug, Serialize, Deserialize, Clone)]
151#[serde(rename_all = "camelCase")]
152pub struct IBt0ConfMinTxFeeWindow {
153    /// Minimum fee rate that is required for Blocktank to accept the onchain payment to be 0conf.
154    #[serde(rename = "satPerVByte")]
155    pub sat_per_vbyte: f64,
156    /// How long this fee rate is valid for.
157    pub validity_ends_at: String,
158}
159
160#[derive(Debug, Serialize, Deserialize, Clone)]
161#[serde(rename_all = "camelCase")]
162pub struct IBtBolt11Invoice {
163    pub request: String,
164    pub state: BtBolt11InvoiceState,
165    pub expires_at: String,
166    pub updated_at: String,
167}
168
169#[derive(Debug, Serialize, Deserialize, Clone)]
170#[serde(rename_all = "camelCase")]
171pub struct FundingTx {
172    pub id: String,
173    pub vout: u64,
174}
175
176#[derive(Debug, Serialize, Deserialize, Clone)]
177#[serde(rename_all = "camelCase")]
178pub struct IBtChannel {
179    pub state: BtOpenChannelState,
180    pub lsp_node_pubkey: String,
181    pub client_node_pubkey: String,
182    pub announce_channel: bool,
183    pub funding_tx: FundingTx,
184    /// @deprecated Use close.tx_id instead.
185    pub closing_tx_id: Option<String>,
186    /// Only available if state === closed. Channels before Oct 2023 may have default values assigned that do not represent reality.
187    pub close: Option<IBtChannelClose>,
188    /// @deprecated Available as soon as the channel is confirmed.
189    pub short_channel_id: Option<String>,
190}
191
192#[derive(Debug, Serialize, Deserialize, Clone)]
193#[serde(rename_all = "camelCase")]
194pub struct IBtChannelClose {
195    /// Transaction id of the closing transaction. Only available if state === OpenChannelOrderState.CLOSED.
196    pub tx_id: String,
197    /// Which method has been used to close this channel?
198    #[serde(rename = "type")]
199    pub close_type: String, // 'cooperative' | 'force' | 'breach'
200    /// Who closed this channel?
201    pub initiator: String, // 'lsp' | 'client'
202    /// When Blocktank registered the channel close.
203    pub registered_at: String,
204}
205
206#[derive(Debug, Serialize, Deserialize, Clone)]
207#[serde(rename_all = "camelCase")]
208pub struct IBtEstimateFeeResponse {
209    pub fee_sat: u64,
210    #[serde(rename = "min0ConfTxFee")]
211    pub min_0_conf_tx_fee: IBt0ConfMinTxFeeWindow,
212}
213
214#[derive(Debug, Serialize, Deserialize, Clone)]
215#[serde(rename_all = "camelCase")]
216pub struct IBtEstimateFeeResponse2 {
217    /// Sum fee to pay
218    pub fee_sat: u64,
219    /// Network fee that Blocktank needs to pay to open and close the channel.
220    pub network_fee_sat: u64,
221    /// Service fee that Blocktank charges to open the channel.
222    pub service_fee_sat: u64,
223    #[serde(rename = "min0ConfTxFee")]
224    pub min_0_conf_tx_fee: IBt0ConfMinTxFeeWindow,
225}
226
227#[derive(Debug, Serialize, Deserialize, Clone)]
228#[serde(rename_all = "camelCase")]
229pub struct IBtInfoOptions {
230    /// Minimum channel size
231    pub min_channel_size_sat: u64,
232    /// Maximum channel size
233    pub max_channel_size_sat: u64,
234    /// Minimum channel lease time in weeks.
235    pub min_expiry_weeks: u32,
236    /// Maximum channel lease time in weeks.
237    pub max_expiry_weeks: u32,
238    /// Minimum payment confirmation for safe payments.
239    pub min_payment_confirmations: u32,
240    /// Minimum payment confirmations for high value payments.
241    pub min_high_risk_payment_confirmations: u32,
242    /// Maximum clientBalanceSat that is accepted as 0conf/turbochannel.
243    pub max_0_conf_client_balance_sat: u64,
244    /// @deprecated Same as maxChannelSizeSat.
245    pub max_client_balance_sat: u64,
246}
247
248#[derive(Debug, Serialize, Deserialize, Clone)]
249pub struct IBtInfoVersions {
250    /// SemVer versions of the http micro services.
251    pub http: String,
252    /// SemVer versions of the btc micro services.
253    pub btc: String,
254    /// SemVer versions of the ln2 micro services.
255    pub ln2: String,
256}
257
258#[derive(Debug, Serialize, Deserialize, Clone)]
259pub struct FeeRates {
260    /// Fast fee in sat/vbyte.
261    pub fast: u32,
262    /// Mid fee in sat/vbyte.
263    pub mid: u32,
264    /// Slow fee in sat/vbyte.
265    pub slow: u32,
266}
267
268#[derive(Debug, Serialize, Deserialize, Clone)]
269#[serde(rename_all = "camelCase")]
270pub struct IBtInfoOnchain {
271    pub network: BitcoinNetworkEnum,
272    pub fee_rates: FeeRates,
273}
274
275#[derive(Debug, Serialize, Deserialize, Clone)]
276pub struct IBtInfo {
277    /// @deprecated Use the `versions` object instead.
278    pub version: u32,
279    /// Available nodes.
280    pub nodes: Vec<ILspNode>,
281    pub options: IBtInfoOptions,
282    /// SemVer versions of the micro services.
283    pub versions: IBtInfoVersions,
284    pub onchain: IBtInfoOnchain,
285}
286
287#[derive(Debug, Serialize, Deserialize, Clone)]
288#[serde(rename_all = "camelCase")]
289pub struct IBtOnchainTransaction {
290    pub amount_sat: u64,
291    pub tx_id: String,
292    pub vout: u32,
293    pub block_height: Option<u32>,
294    pub block_confirmation_count: u32,
295    #[serde(rename = "feeRateSatPerVbyte")]
296    pub fee_rate_sat_per_vbyte: f64,
297    pub confirmed: bool,
298    #[serde(rename = "suspicious0ConfReason")]
299    pub suspicious_0_conf_reason: String,
300}
301
302#[derive(Debug, Serialize, Deserialize, Clone)]
303#[serde(rename_all = "camelCase")]
304pub struct IBtOnchainTransactions {
305    pub address: String,
306    pub confirmed_sat: u64,
307    pub required_confirmations: u32,
308    pub transactions: Vec<IBtOnchainTransaction>,
309}
310
311#[derive(Debug, Serialize, Deserialize, Clone)]
312#[serde(rename_all = "camelCase")]
313pub struct IBtOrder {
314    pub id: String,
315    /// @deprecated Will be removed in future releases. Use state2 instead.
316    pub state: BtOrderState,
317    /// State of the order
318    pub state2: BtOrderState2,
319    /// Fees in satoshi to pay before the channel open is possible.
320    pub fee_sat: u64,
321    /// Onchain transaction fees for the channel open.
322    /// This is variable depending on the network fee conditions.
323    pub network_fee_sat: u64,
324    /// Service fees to pay for us to fulfill the channel open. Includes liquidity fees.
325    pub service_fee_sat: u64,
326    pub lsp_balance_sat: u64,
327    /// Requested funds on the client side.
328    pub client_balance_sat: u64,
329    /// If this the channel should be a turbo channel.
330    #[serde(rename = "zeroConf")]
331    pub zero_conf: bool,
332    /// If the LSP allows the client to have a minimal channel reserve.
333    pub zero_reserve: bool,
334    /// Node id to notify in case the node is offline and the order is ready to open the channel.
335    pub client_node_id: Option<String>,
336    /// Weeks how long Blocktank guarantees to keep the channel open.
337    pub channel_expiry_weeks: u32,
338    /// How long Blocktank guarantees to keep the channel open.
339    pub channel_expires_at: String,
340    /// How long the order with its proposed feeSat is valid for.
341    pub order_expires_at: String,
342    /// Channel in case the order has been executed.
343    pub channel: Option<IBtChannel>,
344    /// Node if of the LSP that will/has opened the channel.
345    pub lsp_node: ILspNode,
346    /// LNURL to open the channel.
347    pub lnurl: Option<String>,
348    /// Payment object showing invoices and the status of the payment.
349    pub payment: IBtPayment,
350    /// @deprecated Use the `source` field.
351    pub coupon_code: Option<String>,
352    /// Source what created this order. Example: bitkit, widget
353    pub source: Option<String>,
354    /// Discount if discount was given.
355    pub discount: Option<IDiscount>,
356    pub updated_at: String,
357    pub created_at: String,
358}
359
360#[derive(Debug, Serialize, Deserialize, Clone)]
361#[serde(rename_all = "camelCase")]
362pub struct IBtPayment {
363    /// @deprecated Will be removed in future releases. Use state2 instead.
364    pub state: BtPaymentState,
365    pub state2: BtPaymentState2,
366    pub paid_sat: u64,
367    pub bolt11_invoice: IBtBolt11Invoice,
368    pub onchain: IBtOnchainTransactions,
369    /// Internal flag
370    pub is_manually_paid: Option<bool>,
371    /// Refund objects
372    pub manual_refunds: Option<Vec<IManualRefund>>,
373}
374
375#[derive(Debug, Serialize, Deserialize, Clone)]
376#[serde(rename_all = "camelCase")]
377pub struct ICJitEntry {
378    /// Id of this CJitEntry
379    pub id: String,
380    /// State of this entry
381    pub state: CJitStateEnum,
382    /// Fee in satoshi to open this channel.
383    pub fee_sat: u64,
384    /// Onchain transaction fees for the channel open.
385    /// This is variable depending on the network fee conditions.
386    pub network_fee_sat: u64,
387    /// Service fees to pay for us to fulfill the channel open. Includes liquidity fees.
388    pub service_fee_sat: u64,
389    /// Requested channel size in satoshi
390    pub channel_size_sat: u64,
391    /// Number of weeks before Blocktank might close then channel.
392    pub channel_expiry_weeks: u32,
393    /// Channel open error if the channel open failed.
394    pub channel_open_error: Option<String>,
395    /// Node id of the node to open the channel to.
396    pub node_id: String,
397    /// Invoice to be paid for the channel open.
398    pub invoice: IBtBolt11Invoice,
399    /// Opened channel
400    pub channel: Option<IBtChannel>,
401    /// LSP node the channel is opened from. The client needs to establish a peer connection to it before the channel open.
402    pub lsp_node: ILspNode,
403    /// @deprecated Use `source` instead
404    pub coupon_code: String,
405    /// Source what created this Cjit. Example: 'bitkit', 'widget'.
406    pub source: Option<String>,
407    /// Discount if available
408    pub discount: Option<IDiscount>,
409    /// Date when this CJit offer expires.
410    pub expires_at: String,
411    pub updated_at: String,
412    pub created_at: String,
413}
414
415#[derive(Debug, Serialize, Deserialize, Clone)]
416#[serde(rename_all = "camelCase")]
417pub struct IDiscount {
418    /// User provided discount code label
419    pub code: String,
420    /// Absolute discount given for this code.
421    pub absolute_sat: u64,
422    /// Relative discount % given for this code.
423    pub relative: f64,
424    /// Overall sum of the discount calculated by `fee * relative + absoluteSat`.
425    pub overall_sat: u64,
426}
427
428#[derive(Debug, Serialize, Deserialize, Clone)]
429#[serde(rename_all = "camelCase")]
430pub struct ILspNode {
431    pub alias: String,
432    pub pubkey: String,
433    pub connection_strings: Vec<String>,
434    pub readonly: Option<bool>,
435}
436
437#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
438pub enum ManualRefundStateEnum {
439    #[serde(rename = "CREATED")]
440    Created,
441    #[serde(rename = "APPROVED")]
442    Approved,
443    #[serde(rename = "REJECTED")]
444    Rejected,
445    #[serde(rename = "SENT")]
446    Sent,
447}
448
449#[derive(Debug, Serialize, Deserialize, Clone)]
450#[serde(rename_all = "camelCase")]
451pub struct IManualRefund {
452    pub amount_sat: u64,
453    pub target: String,
454    pub state: ManualRefundStateEnum,
455    pub created_by_name: String,
456    pub voted_by_name: Option<String>,
457    pub reason: Option<String>,
458    #[serde(rename = "targetType")]
459    pub target_type: String, // 'lightning' | 'onchain'
460}
461
462#[derive(Debug, Serialize, Deserialize, Clone)]
463#[serde(rename_all = "camelCase")]
464pub struct CreateOrderOptions {
465    /// Initial number of satoshis the client wants to provide on their channel side. The client pays this balance
466    /// to the LSP. The LSP will push the balance to the LSP on channel creation. Defaults to 0.
467    pub client_balance_sat: u64,
468
469    /// Node id the client wants to receive the channel from. The id must come from the node list provided by `get_info`.
470    /// If not provided, a random node will be chosen.
471    pub lsp_node_id: Option<String>,
472
473    /// @deprecated Use `source` field instead.
474    pub coupon_code: String,
475
476    /// What created this order. Example: 'bitkit', 'widget'.
477    pub source: Option<String>,
478
479    /// User-entered discount code.
480    pub discount_code: Option<String>,
481
482    /// If the channel opened should be a turbo aka. zeroConf channel.
483    pub zero_conf: bool,
484
485    /// If the on-chain payment should be accepted without any block confirmations.
486    pub zero_conf_payment: Option<bool>,
487
488    /// Allow the peer to have zero channel reserve (dust limit).
489    pub zero_reserve: bool,
490
491    /// Optional id of the node that the channel should be opened to. If supplied,
492    /// performs a channel limit check on the node at order creation to prevent
493    /// any surprises when the channel is actually getting opened.
494    /// Node that should be woken up via a push notification as soon as the payment is confirmed.
495    /// Ownership of the node must be proven with a signature.
496    pub client_node_id: Option<String>,
497
498    /// Timestamp that has been used to sign the open proof.
499    pub timestamp: Option<String>,
500
501    /// Signature `channelOpen-${ISO-timestamp}` created by the private key of the node.
502    pub signature: Option<String>,
503
504    /// User-entered refund on-chain address.
505    pub refund_onchain_address: Option<String>,
506
507    /// Should the channel be public.
508    pub announce_channel: bool,
509}
510
511// Default values for CreateOrderOptions
512impl Default for CreateOrderOptions {
513    fn default() -> Self {
514        Self {
515            client_balance_sat: 0,
516            lsp_node_id: None,
517            coupon_code: String::new(),
518            source: None,
519            discount_code: None,
520            zero_conf: false,
521            zero_conf_payment: None,
522            zero_reserve: false,
523            client_node_id: None,
524            timestamp: None,
525            signature: None,
526            refund_onchain_address: None,
527            announce_channel: false,
528        }
529    }
530}
531
532#[derive(Debug, Serialize, Deserialize, Clone)]
533#[serde(rename_all = "camelCase")]
534pub struct CreateCjitOptions {
535    /// What created this order. Example: 'bitkit', 'widget'.
536    pub source: Option<String>,
537
538    /// User-entered discount code.
539    pub discount_code: Option<String>,
540}
541
542// Default values for CreateCjitOptions
543impl Default for CreateCjitOptions {
544    fn default() -> Self {
545        Self {
546            source: None,
547            discount_code: None,
548        }
549    }
550}
551
552impl std::str::FromStr for BtOrderState2 {
553    type Err = BlocktankError;
554
555    fn from_str(s: &str) -> Result<Self, Self::Err> {
556        match s {
557            "Created" => Ok(BtOrderState2::Created),
558            "Expired" => Ok(BtOrderState2::Expired),
559            "Executed" => Ok(BtOrderState2::Executed),
560            "Paid" => Ok(BtOrderState2::Paid),
561            _ => Err(BlocktankError::DataError {
562                error_details: format!("Invalid BtOrderState2 value: {}", s),
563            }),
564        }
565    }
566}
567
568impl std::str::FromStr for BtOrderState {
569    type Err = BlocktankError;
570
571    fn from_str(s: &str) -> Result<Self, Self::Err> {
572        match s {
573            "Created" => Ok(BtOrderState::Created),
574            "Expired" => Ok(BtOrderState::Expired),
575            "Open" => Ok(BtOrderState::Open),
576            "Closed" => Ok(BtOrderState::Closed),
577            _ => Err(BlocktankError::DataError {
578                error_details: format!("Invalid BtOrderState value: {}", s),
579            }),
580        }
581    }
582}
583
584impl std::str::FromStr for CJitStateEnum {
585    type Err = BlocktankError;
586
587    fn from_str(s: &str) -> Result<Self, Self::Err> {
588        match s {
589            "Created" => Ok(CJitStateEnum::Created),
590            "Completed" => Ok(CJitStateEnum::Completed),
591            "Expired" => Ok(CJitStateEnum::Expired),
592            "Failed" => Ok(CJitStateEnum::Failed),
593            _ => Err(BlocktankError::DataError {
594                error_details: format!("Invalid CJitStateEnum value: {}", s),
595            }),
596        }
597    }
598}
599
600#[derive(Debug, Deserialize)]
601pub struct ApiValidationError {
602    #[serde(rename = "type")]
603    error_type: String,
604    pub(crate) errors: ApiErrorDetails,
605}
606
607#[derive(Debug, Deserialize)]
608pub struct ApiErrorDetails {
609    pub(crate) issues: Vec<ApiErrorIssue>,
610    name: String,
611}
612
613#[derive(Debug, Deserialize)]
614pub struct ApiErrorIssue {
615    code: String,
616    pub(crate) message: String,
617    path: Vec<String>,
618}