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}