Skip to main content

fiber_json_types/
payment.rs

1//! Payment types for the Fiber Network JSON-RPC API.
2
3use crate::schema_helpers::*;
4use crate::serde_utils::{EntityHex, Hash256, Pubkey, SliceHex, U128Hex, U32Hex, U64Hex};
5use ckb_jsonrpc_types::Script;
6use ckb_types::packed::OutPoint;
7use schemars::{json_schema, JsonSchema, Schema, SchemaGenerator};
8use serde::{Deserialize, Serialize};
9use serde_with::serde_as;
10use std::collections::HashMap;
11
12/// The status of a payment, will update as the payment progresses.
13/// The transfer path for payment status is `Created -> Inflight -> Success | Failed`.
14///
15/// **MPP Behavior**: A single session may involve multiple attempts (HTLCs) to fulfill the total amount.
16#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
17pub enum PaymentStatus {
18    /// Initial status. A payment session is created, but no HTLC has been dispatched.
19    Created,
20    /// The first hop AddTlc is sent successfully and waiting for the response.
21    Inflight,
22    /// The payment is finished. All related HTLCs are successfully settled.
23    Success,
24    /// The payment session has terminated.
25    Failed,
26}
27
28/// Parameters for getting a payment.
29#[serde_as]
30#[derive(Serialize, Deserialize, Debug, JsonSchema)]
31pub struct GetPaymentCommandParams {
32    /// The payment hash of the payment to retrieve
33    pub payment_hash: Hash256,
34}
35
36/// The node and channel information in a payment route hop.
37#[serde_as]
38#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
39pub struct SessionRouteNode {
40    /// The public key of the node
41    pub pubkey: Pubkey,
42    /// The amount for this hop
43    #[serde_as(as = "U128Hex")]
44    #[schemars(schema_with = "schema_as_uint_hex")]
45    pub amount: u128,
46    /// The channel outpoint for this hop
47    #[serde_as(as = "EntityHex")]
48    #[schemars(schema_with = "schema_as_hex_bytes")]
49    pub channel_outpoint: OutPoint,
50}
51
52/// The router is a list of nodes that the payment will go through.
53#[derive(Clone, Debug, Serialize, Deserialize, Default, JsonSchema)]
54pub struct SessionRoute {
55    /// The nodes in the route
56    pub nodes: Vec<SessionRouteNode>,
57}
58
59/// The result of a get_payment command, which includes the payment hash, status, timestamps,
60/// error message if failed, fee paid, and custom records.
61#[serde_as]
62#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema)]
63pub struct GetPaymentCommandResult {
64    /// The payment hash of the payment
65    pub payment_hash: Hash256,
66    /// The status of the payment
67    pub status: PaymentStatus,
68    #[serde_as(as = "U64Hex")]
69    #[schemars(schema_with = "schema_as_uint_hex")]
70    /// The time the payment was created at, in milliseconds from UNIX epoch
71    pub created_at: u64,
72    #[serde_as(as = "U64Hex")]
73    #[schemars(schema_with = "schema_as_uint_hex")]
74    /// The time the payment was last updated at, in milliseconds from UNIX epoch
75    pub last_updated_at: u64,
76    /// The error message if the payment failed
77    pub failed_error: Option<String>,
78    /// fee paid for the payment
79    #[serde_as(as = "U128Hex")]
80    #[schemars(schema_with = "schema_as_uint_hex")]
81    pub fee: u128,
82
83    /// The custom records to be included in the payment.
84    pub custom_records: Option<PaymentCustomRecords>,
85
86    #[cfg(debug_assertions)]
87    /// The router is a list of nodes that the payment will go through.
88    /// We store in the payment session and then will use it to track the payment history.
89    /// If the payment adapted MPP (multi-part payment), the routers will be a list of nodes.
90    /// For example:
91    ///    `A(amount, channel) -> B -> C -> D`
92    /// means A will send `amount` with `channel` to B.
93    pub routers: Vec<SessionRoute>,
94}
95
96/// Parameters for listing payments.
97#[serde_as]
98#[derive(Serialize, Deserialize, Debug, Default, JsonSchema)]
99pub struct ListPaymentsParams {
100    /// Filter payments by status. If not set, all payments are returned.
101    pub status: Option<PaymentStatus>,
102    /// The maximum number of payments to return. Default is 15.
103    #[serde_as(as = "Option<U64Hex>")]
104    #[schemars(schema_with = "schema_as_uint_hex_optional")]
105    pub limit: Option<u64>,
106    /// The payment hash to start returning payments after (exclusive cursor for pagination).
107    pub after: Option<Hash256>,
108}
109
110/// Result of listing payments.
111#[derive(Serialize, Deserialize, Debug, Clone, JsonSchema)]
112pub struct ListPaymentsResult {
113    /// The list of payments.
114    pub payments: Vec<GetPaymentCommandResult>,
115    /// The last cursor for pagination. Use this as `after` in the next request to get more results.
116    pub last_cursor: Option<Hash256>,
117}
118
119/// The custom records to be included in the payment.
120/// The key is hex encoded of `u32`, it's range limited in 0 ~ 65535, and the value is hex encoded of `Vec<u8>` with `0x` as prefix.
121/// For example:
122/// ```json
123/// "custom_records": {
124///    "0x1": "0x01020304",
125///    "0x2": "0x05060708",
126///    "0x3": "0x090a0b0c",
127///    "0x4": "0x0d0e0f10010d090a0b0c"
128///  }
129/// ```
130#[serde_as]
131#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Default)]
132pub struct PaymentCustomRecords {
133    /// The custom records to be included in the payment.
134    #[serde(flatten)]
135    #[serde_as(as = "HashMap<U32Hex, SliceHex>")]
136    pub data: HashMap<u32, Vec<u8>>,
137}
138
139impl JsonSchema for PaymentCustomRecords {
140    fn schema_name() -> std::borrow::Cow<'static, str> {
141        "PaymentCustomRecords".into()
142    }
143
144    fn json_schema(_generator: &mut SchemaGenerator) -> Schema {
145        json_schema!({
146            "type": "object",
147            "description": "Custom records map. Keys are hex-encoded u32 (0~65535), \
148                values are hex-encoded bytes. Both prefixed with 0x.",
149            "propertyNames": {
150                "type": "string",
151                "pattern": "^0x(0|[1-9a-fA-F][0-9a-fA-F]{0,3})$"
152            },
153            "additionalProperties": {
154                "type": "string",
155                "pattern": "^0x([0-9a-fA-F]{2})*$"
156            }
157        })
158    }
159}
160
161/// Parameters for sending a payment.
162#[serde_as]
163#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
164pub struct SendPaymentCommandParams {
165    /// The public key (`Pubkey`) of the payment target node, serialized as a hex string.
166    /// You can obtain a node's pubkey via the `node_info` or `graph_nodes` RPC.
167    pub target_pubkey: Option<Pubkey>,
168
169    /// the amount of the payment, the unit is Shannons for non UDT payment
170    /// If not set and there is a invoice, the amount will be set to the invoice amount
171    #[serde_as(as = "Option<U128Hex>")]
172    #[schemars(schema_with = "schema_as_uint_hex_optional")]
173    pub amount: Option<u128>,
174
175    /// the hash to use within the payment's HTLC.
176    /// If not set and `keysend` is set to true, a random hash will be generated.
177    /// If not set and there is a `payment_hash` in the invoice, it will be used.
178    /// Otherwise, `payment_hash` need to be set.
179    pub payment_hash: Option<Hash256>,
180
181    /// the TLC expiry delta should be used to set the timelock for the final hop, in milliseconds
182    #[serde_as(as = "Option<U64Hex>")]
183    #[schemars(schema_with = "schema_as_uint_hex_optional")]
184    pub final_tlc_expiry_delta: Option<u64>,
185
186    /// the TLC expiry limit for the whole payment, in milliseconds, each hop is with a default tlc delta of 1 day
187    /// suppose the payment router is with N hops, the total tlc expiry limit is at least (N-1) days
188    /// this is also the default value for the payment if this parameter is not provided
189    #[serde_as(as = "Option<U64Hex>")]
190    #[schemars(schema_with = "schema_as_uint_hex_optional")]
191    pub tlc_expiry_limit: Option<u64>,
192
193    /// the encoded invoice to send to the recipient
194    pub invoice: Option<String>,
195
196    /// the payment timeout in seconds, if the payment is not completed within this time, it will be cancelled
197    #[serde_as(as = "Option<U64Hex>")]
198    #[schemars(schema_with = "schema_as_uint_hex_optional")]
199    pub timeout: Option<u64>,
200
201    /// the maximum fee amounts in shannons that the sender is willing to pay.
202    /// Note: In trampoline routing mode, the sender will use the max_fee_amount as the total fee as much as possible.
203    #[serde_as(as = "Option<U128Hex>")]
204    #[schemars(schema_with = "schema_as_uint_hex_optional")]
205    pub max_fee_amount: Option<u128>,
206
207    /// the maximum fee rate per thousand, default is 5 (0.5%)
208    #[serde_as(as = "Option<U64Hex>")]
209    #[schemars(schema_with = "schema_as_uint_hex_optional")]
210    pub max_fee_rate: Option<u64>,
211
212    /// max parts for the payment, only used for multi-part payments
213    #[serde_as(as = "Option<U64Hex>")]
214    #[schemars(schema_with = "schema_as_uint_hex_optional")]
215    pub max_parts: Option<u64>,
216
217    /// Optional explicit trampoline hops.
218    ///
219    /// When set to a non-empty list `[t1, t2, ...]`, routing will only find a path from the
220    /// payer to `t1`, and the inner trampoline onion will encode `t1 -> t2 -> ... -> final`.
221    pub trampoline_hops: Option<Vec<Pubkey>>,
222
223    /// keysend payment
224    pub keysend: Option<bool>,
225
226    /// udt type script for the payment
227    pub udt_type_script: Option<Script>,
228
229    /// Allow paying yourself through a circular route, default is false.
230    /// This is useful for **channel rebalancing**: the payment flows out of one channel and
231    /// back through another, shifting liquidity between your channels without changing your
232    /// total balance (only routing fees are deducted).
233    /// Set `target_pubkey` to your own node pubkey and `keysend` to `true` to perform a rebalance.
234    /// Note: `allow_self_payment` is not compatible with trampoline routing.
235    pub allow_self_payment: Option<bool>,
236
237    /// Some custom records for the payment which contains a map of u32 to Vec<u8>
238    /// The key is the record type, and the value is the serialized data
239    /// For example:
240    /// ```json
241    /// "custom_records": {
242    ///    "0x1": "0x01020304",
243    ///    "0x2": "0x05060708",
244    ///    "0x3": "0x090a0b0c",
245    ///    "0x4": "0x0d0e0f10010d090a0b0c"
246    ///  }
247    /// ```
248    pub custom_records: Option<PaymentCustomRecords>,
249
250    /// Optional route hints to reach the destination through private channels.
251    /// Note:
252    ///    1. this is only used for the private channels with the last hop.
253    ///    2. `hop_hints` is only a `hint` for routing algorithm,
254    ///       it is not a guarantee that the payment will be routed through the specified channels,
255    ///       it is up to the routing algorithm to decide whether to use the hints or not.
256    ///
257    /// For example `(pubkey, channel_outpoint, fee_rate, tlc_expiry_delta)` suggest path router
258    /// to use the channel of `channel_outpoint` at hop with `pubkey` to forward the payment
259    /// and the fee rate is `fee_rate` and tlc_expiry_delta is `tlc_expiry_delta`.
260    pub hop_hints: Option<Vec<HopHint>>,
261
262    /// dry_run for payment, used for check whether we can build valid router and the fee for this payment,
263    /// it's useful for the sender to double check the payment before sending it to the network,
264    /// default is false
265    pub dry_run: Option<bool>,
266}
267
268/// A hop hint is a hint for a node to use a specific channel.
269#[serde_as]
270#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
271pub struct HopHint {
272    /// The public key of the node
273    pub pubkey: Pubkey,
274    /// The outpoint of the channel
275    #[serde_as(as = "EntityHex")]
276    #[schemars(schema_with = "schema_as_hex_bytes")]
277    pub channel_outpoint: OutPoint,
278
279    /// The fee rate to use this hop to forward the payment.
280    #[serde_as(as = "U64Hex")]
281    #[schemars(schema_with = "schema_as_uint_hex")]
282    pub fee_rate: u64,
283    /// The TLC expiry delta to use this hop to forward the payment.
284    #[serde_as(as = "U64Hex")]
285    #[schemars(schema_with = "schema_as_uint_hex")]
286    pub tlc_expiry_delta: u64,
287}
288
289/// Parameters for building a payment router.
290#[serde_as]
291#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
292pub struct BuildRouterParams {
293    /// the amount of the payment, the unit is Shannons for non UDT payment
294    /// If not set, the minimum routable amount `1` is used
295    #[serde_as(as = "Option<U128Hex>")]
296    #[schemars(schema_with = "schema_as_uint_hex_optional")]
297    pub amount: Option<u128>,
298
299    /// udt type script for the payment router
300    pub udt_type_script: Option<Script>,
301
302    /// A list of hops that defines the route. This does not include the source hop pubkey.
303    /// A hop info is a tuple of pubkey and the channel(specified by channel funding tx) will be used.
304    /// This is a strong restriction given on payment router, which means these specified hops and channels
305    /// must be adapted in the router. This is different from hop hints, which maybe ignored by find path.
306    /// If channel is not specified, find path algorithm will pick a channel within these two peers.
307    ///
308    /// An error will be returned if there is no router could be build from given hops and channels
309    pub hops_info: Vec<HopRequire>,
310
311    /// the TLC expiry delta should be used to set the timelock for the final hop, in milliseconds
312    #[serde_as(as = "Option<U64Hex>")]
313    #[schemars(schema_with = "schema_as_uint_hex_optional")]
314    pub final_tlc_expiry_delta: Option<u64>,
315}
316
317/// A hop requirement to meet when building a router. Does not include the source node;
318/// the last hop is the target node.
319#[serde_as]
320#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
321pub struct HopRequire {
322    /// The public key of the node
323    pub pubkey: Pubkey,
324    /// The outpoint for the channel, which means use channel with `channel_outpoint` to reach this node
325    #[serde_as(as = "Option<EntityHex>")]
326    #[schemars(schema_with = "schema_as_hex_bytes_optional")]
327    pub channel_outpoint: Option<OutPoint>,
328}
329
330/// A router hop information for a payment, a paymenter router is an array of RouterHop,
331/// a router hop generally implies hop `target` will receive `amount_received` with `channel_outpoint` of channel.
332#[serde_as]
333#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
334pub struct RouterHop {
335    /// The node that is sending the TLC to the next node.
336    pub target: Pubkey,
337    /// The channel of this hop used to receive TLC
338    #[serde_as(as = "EntityHex")]
339    #[schemars(schema_with = "schema_as_hex_bytes")]
340    pub channel_outpoint: OutPoint,
341    /// The amount that the source node will transfer to the target node.
342    #[serde_as(as = "U128Hex")]
343    #[schemars(schema_with = "schema_as_uint_hex")]
344    pub amount_received: u128,
345    /// The expiry for the TLC that the source node sends to the target node.
346    #[serde_as(as = "U64Hex")]
347    #[schemars(schema_with = "schema_as_uint_hex")]
348    pub incoming_tlc_expiry: u64,
349}
350
351/// The router returned by build_router.
352#[serde_as]
353#[derive(Serialize, Deserialize, Debug, Clone, JsonSchema)]
354pub struct BuildPaymentRouterResult {
355    /// The hops information for router
356    pub router_hops: Vec<RouterHop>,
357}
358
359/// Parameters for sending a payment with a specified router.
360#[serde_as]
361#[derive(Serialize, Deserialize, Debug, JsonSchema)]
362pub struct SendPaymentWithRouterParams {
363    /// the hash to use within the payment's HTLC.
364    /// If not set and `keysend` is set to true, a random hash will be generated.
365    /// If not set and there is a `payment_hash` in the invoice, it will be used.
366    /// Otherwise, `payment_hash` need to be set.
367    pub payment_hash: Option<Hash256>,
368
369    /// The router to use for the payment
370    pub router: Vec<RouterHop>,
371
372    /// the encoded invoice to send to the recipient
373    pub invoice: Option<String>,
374
375    /// Some custom records for the payment which contains a map of u32 to Vec<u8>
376    /// The key is the record type, and the value is the serialized data.
377    /// Limits: the sum size of values can not exceed 2048 bytes.
378    ///
379    /// For example:
380    /// ```json
381    /// "custom_records": {
382    ///    "0x1": "0x01020304",
383    ///    "0x2": "0x05060708",
384    ///    "0x3": "0x090a0b0c",
385    ///    "0x4": "0x0d0e0f10010d090a0b0c"
386    ///  }
387    /// ```
388    pub custom_records: Option<PaymentCustomRecords>,
389
390    /// keysend payment
391    pub keysend: Option<bool>,
392
393    /// udt type script for the payment
394    pub udt_type_script: Option<Script>,
395
396    /// dry_run for payment, used for check whether we can build valid router and the fee for this payment,
397    /// it's useful for the sender to double check the payment before sending it to the network,
398    /// default is false
399    pub dry_run: Option<bool>,
400}