rust_blocktank_client/types/
blocktank.rs

1use serde::{Deserialize, Serialize};
2use crate::BlocktankError;
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    pub zero_conf: bool,
331    /// If the LSP allows the client to have a minimal channel reserve.
332    pub zero_reserve: bool,
333    /// Node id to notify in case the node is offline and the order is ready to open the channel.
334    pub client_node_id: Option<String>,
335    /// Weeks how long Blocktank guarantees to keep the channel open.
336    pub channel_expiry_weeks: u32,
337    /// How long Blocktank guarantees to keep the channel open.
338    pub channel_expires_at: String,
339    /// How long the order with its proposed feeSat is valid for.
340    pub order_expires_at: String,
341    /// Channel in case the order has been executed.
342    pub channel: Option<IBtChannel>,
343    /// Node if of the LSP that will/has opened the channel.
344    pub lsp_node: ILspNode,
345    /// LNURL to open the channel.
346    pub lnurl: Option<String>,
347    /// Payment object showing invoices and the status of the payment.
348    pub payment: IBtPayment,
349    /// @deprecated Use the `source` field.
350    pub coupon_code: Option<String>,
351    /// Source what created this order. Example: bitkit, widget
352    pub source: Option<String>,
353    /// Discount if discount was given.
354    pub discount: Option<IDiscount>,
355    pub updated_at: String,
356    pub created_at: String,
357}
358
359#[derive(Debug, Serialize, Deserialize, Clone)]
360#[serde(rename_all = "camelCase")]
361pub struct IBtPayment {
362    /// @deprecated Will be removed in future releases. Use state2 instead.
363    pub state: BtPaymentState,
364    pub state2: BtPaymentState2,
365    pub paid_sat: u64,
366    pub bolt11_invoice: IBtBolt11Invoice,
367    pub onchain: IBtOnchainTransactions,
368    /// Internal flag
369    pub is_manually_paid: Option<bool>,
370    /// Refund objects
371    pub manual_refunds: Option<Vec<IManualRefund>>,
372}
373
374#[derive(Debug, Serialize, Deserialize, Clone)]
375#[serde(rename_all = "camelCase")]
376pub struct ICJitEntry {
377    /// Id of this CJitEntry
378    pub id: String,
379    /// State of this entry
380    pub state: CJitStateEnum,
381    /// Fee in satoshi to open this channel.
382    pub fee_sat: u64,
383    /// Onchain transaction fees for the channel open.
384    /// This is variable depending on the network fee conditions.
385    pub network_fee_sat: u64,
386    /// Service fees to pay for us to fulfill the channel open. Includes liquidity fees.
387    pub service_fee_sat: u64,
388    /// Requested channel size in satoshi
389    pub channel_size_sat: u64,
390    /// Number of weeks before Blocktank might close then channel.
391    pub channel_expiry_weeks: u32,
392    /// Channel open error if the channel open failed.
393    pub channel_open_error: Option<String>,
394    /// Node id of the node to open the channel to.
395    pub node_id: String,
396    /// Invoice to be paid for the channel open.
397    pub invoice: IBtBolt11Invoice,
398    /// Opened channel
399    pub channel: Option<IBtChannel>,
400    /// LSP node the channel is opened from. The client needs to establish a peer connection to it before the channel open.
401    pub lsp_node: ILspNode,
402    /// @deprecated Use `source` instead
403    pub coupon_code: String,
404    /// Source what created this Cjit. Example: 'bitkit', 'widget'.
405    pub source: Option<String>,
406    /// Discount if available
407    pub discount: Option<IDiscount>,
408    /// Date when this CJit offer expires.
409    pub expires_at: String,
410    pub updated_at: String,
411    pub created_at: String,
412}
413
414#[derive(Debug, Serialize, Deserialize, Clone)]
415#[serde(rename_all = "camelCase")]
416pub struct IDiscount {
417    /// User provided discount code label
418    pub code: String,
419    /// Absolute discount given for this code.
420    pub absolute_sat: u64,
421    /// Relative discount % given for this code.
422    pub relative: f64,
423    /// Overall sum of the discount calculated by `fee * relative + absoluteSat`.
424    pub overall_sat: u64,
425}
426
427#[derive(Debug, Serialize, Deserialize, Clone)]
428#[serde(rename_all = "camelCase")]
429pub struct ILspNode {
430    pub alias: String,
431    pub pubkey: String,
432    pub connection_strings: Vec<String>,
433    pub readonly: Option<bool>,
434}
435
436#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
437pub enum ManualRefundStateEnum {
438    #[serde(rename = "CREATED")]
439    Created,
440    #[serde(rename = "APPROVED")]
441    Approved,
442    #[serde(rename = "REJECTED")]
443    Rejected,
444    #[serde(rename = "SENT")]
445    Sent,
446}
447
448#[derive(Debug, Serialize, Deserialize, Clone)]
449#[serde(rename_all = "camelCase")]
450pub struct IManualRefund {
451    pub amount_sat: u64,
452    pub target: String,
453    pub state: ManualRefundStateEnum,
454    pub created_by_name: String,
455    pub voted_by_name: Option<String>,
456    pub reason: Option<String>,
457    #[serde(rename = "targetType")]
458    pub target_type: String, // 'lightning' | 'onchain'
459}
460
461#[derive(Debug, Serialize, Deserialize, Clone)]
462#[serde(rename_all = "camelCase")]
463pub struct CreateOrderOptions {
464    /// Initial number of satoshis the client wants to provide on their channel side. The client pays this balance
465    /// to the LSP. The LSP will push the balance to the LSP on channel creation. Defaults to 0.
466    pub client_balance_sat: u64,
467
468    /// Node id the client wants to receive the channel from. The id must come from the node list provided by `get_info`.
469    /// If not provided, a random node will be chosen.
470    pub lsp_node_id: Option<String>,
471
472    /// @deprecated Use `source` field instead.
473    pub coupon_code: String,
474
475    /// What created this order. Example: 'bitkit', 'widget'.
476    pub source: Option<String>,
477
478    /// User-entered discount code.
479    pub discount_code: Option<String>,
480
481    /// If the channel opened should be a turbo aka. zeroConf channel.
482    pub turbo_channel: bool,
483
484    /// If the on-chain payment should be accepted without any block confirmations.
485    pub zero_conf_payment: Option<bool>,
486
487    /// Allow the peer to have zero channel reserve (dust limit).
488    pub zero_reserve: bool,
489
490    /// Optional id of the node that the channel should be opened to. If supplied,
491    /// performs a channel limit check on the node at order creation to prevent
492    /// any surprises when the channel is actually getting opened.
493    /// Node that should be woken up via a push notification as soon as the payment is confirmed.
494    /// Ownership of the node must be proven with a signature.
495    pub client_node_id: Option<String>,
496
497    /// Timestamp that has been used to sign the open proof.
498    pub timestamp: Option<String>,
499
500    /// Signature `channelOpen-${ISO-timestamp}` created by the private key of the node.
501    pub signature: Option<String>,
502
503    /// User-entered refund on-chain address.
504    pub refund_onchain_address: Option<String>,
505
506    /// Should the channel be public.
507    pub announce_channel: bool,
508}
509
510// Default values for CreateOrderOptions
511impl Default for CreateOrderOptions {
512    fn default() -> Self {
513        Self {
514            client_balance_sat: 0,
515            lsp_node_id: None,
516            coupon_code: String::new(),
517            source: None,
518            discount_code: None,
519            turbo_channel: false,
520            zero_conf_payment: None,
521            zero_reserve: false,
522            client_node_id: None,
523            timestamp: None,
524            signature: None,
525            refund_onchain_address: None,
526            announce_channel: false,
527        }
528    }
529}
530
531#[derive(Debug, Serialize, Deserialize, Clone)]
532#[serde(rename_all = "camelCase")]
533pub struct CreateCjitOptions {
534    /// What created this order. Example: 'bitkit', 'widget'.
535    pub source: Option<String>,
536
537    /// User-entered discount code.
538    pub discount_code: Option<String>,
539}
540
541// Default values for CreateCjitOptions
542impl Default for CreateCjitOptions {
543    fn default() -> Self {
544        Self {
545            source: None,
546            discount_code: None,
547        }
548    }
549}
550
551impl std::str::FromStr for BtOrderState2 {
552    type Err = BlocktankError;
553
554    fn from_str(s: &str) -> Result<Self, Self::Err> {
555        match s {
556            "Created" => Ok(BtOrderState2::Created),
557            "Expired" => Ok(BtOrderState2::Expired),
558            "Executed" => Ok(BtOrderState2::Executed),
559            "Paid" => Ok(BtOrderState2::Paid),
560            _ => Err(BlocktankError::DataError {
561                error_details: format!("Invalid BtOrderState2 value: {}", s)
562            }),
563        }
564    }
565}
566
567impl std::str::FromStr for BtOrderState {
568    type Err = BlocktankError;
569
570    fn from_str(s: &str) -> Result<Self, Self::Err> {
571        match s {
572            "Created" => Ok(BtOrderState::Created),
573            "Expired" => Ok(BtOrderState::Expired),
574            "Open" => Ok(BtOrderState::Open),
575            "Closed" => Ok(BtOrderState::Closed),
576            _ => Err(BlocktankError::DataError {
577                error_details: format!("Invalid BtOrderState value: {}", s)
578            }),
579        }
580    }
581}
582
583impl std::str::FromStr for CJitStateEnum {
584    type Err = BlocktankError;
585
586    fn from_str(s: &str) -> Result<Self, Self::Err> {
587        match s {
588            "Created" => Ok(CJitStateEnum::Created),
589            "Completed" => Ok(CJitStateEnum::Completed),
590            "Expired" => Ok(CJitStateEnum::Expired),
591            "Failed" => Ok(CJitStateEnum::Failed),
592            _ => Err(BlocktankError::DataError {
593                error_details: format!("Invalid CJitStateEnum value: {}", s)
594            }),
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}