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