@@ -191,6 +191,13 @@ static struct command_result *xpay_core(struct command *cmd,
191191 u32 maxdelay ,
192192 bool as_pay );
193193
194+ static struct command_result *
195+ sendamount_core (struct command * cmd , const char * invstring TAKES ,
196+ const struct amount_msat sendamount_msat ,
197+ const struct amount_msat invoiceamount_msat ,
198+ const struct amount_msat * maxfee , const char * * layers ,
199+ u32 retryfor , u32 maxdelay );
200+
194201/* Wrapper for pending commands (ignores return) */
195202static void was_pending (const struct command_result * res )
196203{
@@ -1862,10 +1869,10 @@ check_offer_sendamount_payable(struct command *cmd, const char *offerstr)
18621869 "Cannot pay offer in different currency %s" ,
18631870 b12offer -> offer_currency );
18641871 /* Can only be applied to *any amount* offers. */
1865- if (b12offer -> offer_amount ) {
1872+ if (b12offer -> offer_amount )
18661873 return command_fail (cmd , JSONRPC2_INVALID_PARAMS ,
1867- "Offer does not allow any amount." );
1868- }
1874+ "Expecting an offer with no amount." );
1875+
18691876 /* Not recurrence, one time only. */
18701877 if (offer_recurrence (b12offer ))
18711878 return command_fail (cmd , JSONRPC2_INVALID_PARAMS ,
@@ -1892,10 +1899,17 @@ invoice_fetched(struct command *cmd,
18921899 char * inv ;
18931900
18941901 inv = json_strdup (NULL , buf , json_get_member (buf , result , "invoice" ));
1895- return xpay_core (cmd , take (to_canonical_invstr (NULL , take (inv ))),
1896- NULL , params -> maxfee , params -> layers ,
1897- params -> retryfor , params -> partial , params -> maxdelay ,
1898- false);
1902+ if (params -> includefees_msat ) {
1903+ return sendamount_core (
1904+ cmd , take (to_canonical_invstr (NULL , take (inv ))),
1905+ * params -> includefees_msat , * params -> msat , params -> maxfee ,
1906+ params -> layers , params -> retryfor , params -> maxdelay );
1907+ } else {
1908+ return xpay_core (
1909+ cmd , take (to_canonical_invstr (NULL , take (inv ))), NULL ,
1910+ params -> maxfee , params -> layers , params -> retryfor ,
1911+ params -> partial , params -> maxdelay , false);
1912+ }
18991913}
19001914
19011915static struct command_result *
@@ -2223,6 +2237,187 @@ static struct command_result *xpay_core(struct command *cmd,
22232237 return send_outreq (req );
22242238}
22252239
2240+ /* Same pattern as xpay_core, but specific to sendamount. */
2241+ static struct command_result *
2242+ sendamount_core (struct command * cmd , const char * invstring TAKES ,
2243+ const struct amount_msat sendamount_msat ,
2244+ const struct amount_msat invoiceamount_msat ,
2245+ const struct amount_msat * maxfee , const char * * layers ,
2246+ u32 retryfor , u32 maxdelay )
2247+ {
2248+ struct payment * payment = tal (cmd , struct payment );
2249+ struct xpay * xpay = xpay_of (cmd -> plugin );
2250+ struct gossmap * gossmap = get_gossmap (xpay );
2251+ struct amount_msat diff_msat ;
2252+ char * err ;
2253+ struct out_req * req ;
2254+ u64 now , invexpiry ;
2255+
2256+ list_head_init (& payment -> current_attempts );
2257+ list_head_init (& payment -> past_attempts );
2258+ payment -> plugin = cmd -> plugin ;
2259+ payment -> cmd = cmd ;
2260+ payment -> amount_being_routed = AMOUNT_MSAT (0 );
2261+ payment -> group_id = pseudorand (INT64_MAX );
2262+ payment -> total_num_attempts = payment -> num_failures = 0 ;
2263+ payment -> requests = tal_arr (payment , struct out_req * , 0 );
2264+ payment -> prior_results = tal_strdup (payment , "" );
2265+ payment -> deadline = timemono_add (time_mono (), time_from_sec (retryfor ));
2266+ payment -> start_time = clock_time ();
2267+ payment -> start_blockheight = xpay -> blockheight ;
2268+ payment -> pay_compat = false;
2269+ payment -> invstring = tal_strdup (payment , invstring );
2270+ payment -> includefees = true;
2271+ payment -> maxdelay = maxdelay ;
2272+ payment -> disable_mpp = true;
2273+ payment -> maxparts = 1 ;
2274+ if (layers )
2275+ payment -> layers = tal_dup_talarr (payment , const char * , layers );
2276+ else
2277+ payment -> layers = NULL ;
2278+
2279+ payment -> amount = sendamount_msat ;
2280+ payment -> mpp_amount = AMOUNT_MSAT (0 );
2281+
2282+ if (amount_msat_is_zero (sendamount_msat ))
2283+ return command_fail (cmd , JSONRPC2_INVALID_PARAMS ,
2284+ "Cannot send zero amount" );
2285+
2286+ if (!maxfee ) {
2287+ /* The default maximum fee function is piecewise linear and
2288+ * continuous. It always satisfies maxfee <= sendamount/2. */
2289+ if (amount_msat_less_eq (sendamount_msat , AMOUNT_MSAT (10000 ))) {
2290+ /* Very small amounts (<=10sats) we use a very high
2291+ * relative fee but never above 50%. */
2292+ payment -> maxfee = amount_msat_div (sendamount_msat , 2 );
2293+ } else if (amount_msat_less_eq (sendamount_msat ,
2294+ AMOUNT_MSAT (500000 ))) {
2295+ /* In this medium range we fix the maximum fee to 5sats.
2296+ */
2297+ payment -> maxfee = AMOUNT_MSAT (5000 );
2298+ } else {
2299+ /* For high value payments (>=500sat), the default is
2300+ * 1%.*/
2301+ payment -> maxfee = amount_msat_div (sendamount_msat , 100 );
2302+ }
2303+ } else
2304+ payment -> maxfee = * maxfee ;
2305+
2306+ if (amount_msat_sub (& diff_msat , sendamount_msat , invoiceamount_msat )) {
2307+ /* Even if maxfee is specified, we cap it at half_amount because
2308+ * we cannot pay more than half_amount in fees otherwise the
2309+ * received amount will be smaller than the invoice amount. */
2310+ payment -> maxfee = amount_msat_min (payment -> maxfee , diff_msat );
2311+ } else {
2312+ return command_fail (
2313+ cmd , JSONRPC2_INVALID_PARAMS ,
2314+ "Invoice amount (%s) is greater than send amount (%s)." ,
2315+ fmt_amount_msat (tmpctx , invoiceamount_msat ),
2316+ fmt_amount_msat (tmpctx , sendamount_msat ));
2317+ }
2318+
2319+ if (bolt12_has_prefix (payment -> invstring )) {
2320+ // bolt12 invoice
2321+ struct tlv_invoice * b12inv = invoice_decode (
2322+ tmpctx , payment -> invstring , strlen (payment -> invstring ),
2323+ plugin_feature_set (cmd -> plugin ), chainparams , & err );
2324+ if (!b12inv )
2325+ return command_fail (cmd , JSONRPC2_INVALID_PARAMS ,
2326+ "Invalid bolt12 invoice: %s" , err );
2327+
2328+ invexpiry = invoice_expiry (b12inv );
2329+ if (!amount_msat_eq (invoiceamount_msat ,
2330+ amount_msat (* b12inv -> invoice_amount )))
2331+ return command_fail (
2332+ cmd , JSONRPC2_INVALID_PARAMS ,
2333+ "Expecting a bolt12 invoice with amount %s, got %s "
2334+ "instead" ,
2335+ fmt_amount_msat (tmpctx , invoiceamount_msat ),
2336+ fmt_amount_msat (
2337+ tmpctx , amount_msat (* b12inv -> invoice_amount )));
2338+
2339+ payment -> route_hints = NULL ;
2340+ payment -> payment_secret = NULL ;
2341+ payment -> payment_metadata = NULL ;
2342+ payment -> paths = tal_steal (payment , b12inv -> invoice_paths );
2343+ payment -> payinfos =
2344+ tal_steal (payment , b12inv -> invoice_blindedpay );
2345+ payment -> payment_hash = * b12inv -> invoice_payment_hash ;
2346+ payment -> destination = * b12inv -> invoice_node_id ;
2347+ /* Resolve introduction points if possible */
2348+ for (size_t i = 0 ; i < tal_count (payment -> paths ); i ++ ) {
2349+ if (!gossmap_scidd_pubkey (
2350+ gossmap , & payment -> paths [i ]-> first_node_id )) {
2351+ payment_log (
2352+ payment , LOG_UNUSUAL ,
2353+ "Could not resolve blinded path start %s: "
2354+ "discarding" ,
2355+ fmt_sciddir_or_pubkey (
2356+ tmpctx ,
2357+ & payment -> paths [i ]-> first_node_id ));
2358+ tal_arr_remove (& payment -> paths , i );
2359+ tal_arr_remove (& payment -> payinfos , i );
2360+ i -- ;
2361+ }
2362+ }
2363+ /* In case we remove them all! */
2364+ if (tal_count (payment -> paths ) == 0 )
2365+ return command_fail (cmd , JSONRPC2_INVALID_PARAMS ,
2366+ "Could not resolve any paths: "
2367+ "unknown short_channel_id" );
2368+
2369+ /* We don't actually know the final_cltv for blinded
2370+ * paths, we just know the cltv we use to enter the
2371+ * final hop. */
2372+ payment -> final_cltv = 0 ;
2373+ } else {
2374+ // bolt11 invoice
2375+ struct bolt11 * b11 = bolt11_decode (
2376+ tmpctx , payment -> invstring , plugin_feature_set (cmd -> plugin ),
2377+ NULL , chainparams , & err );
2378+ if (!b11 )
2379+ return command_fail (cmd , JSONRPC2_INVALID_PARAMS ,
2380+ "Invalid bolt11 invoice: %s" , err );
2381+ payment -> route_hints = tal_steal (payment , b11 -> routes );
2382+ payment -> paths = NULL ;
2383+ payment -> payinfos = NULL ;
2384+ if (!pubkey_from_node_id (& payment -> destination ,
2385+ & b11 -> receiver_id ))
2386+ return command_fail (
2387+ cmd , JSONRPC2_INVALID_PARAMS ,
2388+ "Invalid destination id %s" ,
2389+ fmt_node_id (tmpctx , & b11 -> receiver_id ));
2390+
2391+ payment -> final_cltv = b11 -> min_final_cltv_expiry ;
2392+ payment -> payment_hash = b11 -> payment_hash ;
2393+ payment -> payment_secret =
2394+ tal_steal (payment , b11 -> payment_secret );
2395+ if (!b11 -> payment_secret )
2396+ return command_fail (cmd , JSONRPC2_INVALID_PARAMS ,
2397+ "need payment_secret" );
2398+ payment -> payment_metadata = tal_steal (payment , b11 -> metadata );
2399+ if (b11 -> msat )
2400+ return command_fail (
2401+ cmd , JSONRPC2_INVALID_PARAMS ,
2402+ "Expecting a Bolt11 invoice with no amount." );
2403+
2404+ invexpiry = b11 -> timestamp + b11 -> expiry ;
2405+ }
2406+
2407+ now = clock_time ().ts .tv_sec ;
2408+ if (now > invexpiry )
2409+ return command_fail (cmd , PAY_INVOICE_EXPIRED ,
2410+ "Invoice expired %" PRIu64 " seconds ago" ,
2411+ now - invexpiry );
2412+
2413+ /* Now preapprove, then start payment. */
2414+ req = jsonrpc_request_start (cmd , "preapproveinvoice" ,
2415+ & preapproveinvoice_succeed , & forward_error ,
2416+ payment );
2417+ json_add_string (req -> js , "bolt11" , payment -> invstring );
2418+ return send_outreq (req );
2419+ }
2420+
22262421static struct command_result * json_xpay (struct command * cmd ,
22272422 const char * buffer ,
22282423 const jsmntok_t * params )
@@ -2237,6 +2432,94 @@ static struct command_result *json_xpay_as_pay(struct command *cmd,
22372432 return json_xpay_params (cmd , buffer , params , true);
22382433}
22392434
2435+ /* When to use this?
2436+ * If we want to be specific about the amount we send and not about the amount
2437+ * the other end receives.
2438+ * Same pattern as json_xpay. */
2439+ static struct command_result * json_sendamount (struct command * cmd ,
2440+ const char * buffer ,
2441+ const jsmntok_t * params )
2442+ {
2443+ struct amount_msat * send_msat , * maxfee ;
2444+ struct amount_msat invoice_msat ;
2445+ const char * invstring ;
2446+ const char * * layers ;
2447+ u32 * maxdelay ;
2448+ const char * payer_note ;
2449+ unsigned int * retryfor ;
2450+ struct xpay_params * xparams ;
2451+ struct out_req * req ;
2452+
2453+ if (!param_check (cmd , buffer , params ,
2454+ p_req ("invstring" , param_invstring , & invstring ),
2455+ p_req ("sendamount_msat" , param_msat , & send_msat ),
2456+ p_opt ("maxfee" , param_msat , & maxfee ),
2457+ p_opt ("layers" , param_string_array , & layers ),
2458+ p_opt_def ("retry_for" , param_number , & retryfor , 60 ),
2459+ p_opt_def ("maxdelay" , param_u32 , & maxdelay , 2016 ),
2460+ p_opt ("payer_note" , param_string , & payer_note ), NULL ))
2461+ return command_param_failed ();
2462+
2463+ // FIXME: why does xpay returns this only after
2464+ // preapproveinvoice_succeed?
2465+ if (command_check_only (cmd ))
2466+ return command_check_done (cmd );
2467+
2468+ /* We need the recepient to generate an invoice for send_msat/2
2469+ * so that we can deliver any value from send_msat/2 up to
2470+ * send_msat. We don't know the fees in advance. We could use
2471+ * getroutes to estimate some fees though, but the use of
2472+ * blinded paths already invalidates this procedure: we can't
2473+ * use getroutes until we have an invoice. */
2474+ invoice_msat = amount_msat_div_ceil (* send_msat , 2 );
2475+ // FIXME: could this work with invoice_msat = 0?
2476+
2477+ /* Bolt12 offer */
2478+ if (bolt12_has_prefix (invstring )) {
2479+ struct command_result * ret ;
2480+ ret = check_offer_sendamount_payable (cmd , invstring );
2481+ if (ret )
2482+ return ret ;
2483+ xparams = tal (cmd , struct xpay_params );
2484+ xparams -> msat =
2485+ tal_dup (xparams , struct amount_msat , & invoice_msat );
2486+ xparams -> maxfee = maxfee ;
2487+ xparams -> partial = NULL ;
2488+ xparams -> includefees_msat = send_msat ;
2489+ xparams -> layers = layers ;
2490+ xparams -> retryfor = * retryfor ;
2491+ xparams -> maxdelay = * maxdelay ;
2492+ xparams -> bip353 = NULL ;
2493+ xparams -> payer_note = payer_note ;
2494+
2495+ return do_fetchinvoice (cmd , invstring , xparams );
2496+ }
2497+
2498+ /* BIP353 */
2499+ if (strchr (invstring , '@' )) {
2500+ xparams = tal (cmd , struct xpay_params );
2501+ xparams -> msat =
2502+ tal_dup (xparams , struct amount_msat , & invoice_msat );
2503+ xparams -> maxfee = maxfee ;
2504+ xparams -> partial = NULL ;
2505+ xparams -> includefees_msat = send_msat ;
2506+ xparams -> layers = layers ;
2507+ xparams -> retryfor = * retryfor ;
2508+ xparams -> maxdelay = * maxdelay ;
2509+ xparams -> bip353 = invstring ;
2510+ xparams -> payer_note = payer_note ;
2511+
2512+ req = jsonrpc_request_start (cmd , "fetchbip353" , bip353_fetched ,
2513+ forward_error , xparams );
2514+ json_add_string (req -> js , "address" , invstring );
2515+ return send_outreq (req );
2516+ }
2517+
2518+ /* Probably a bolt11, an invoice already. */
2519+ return sendamount_core (cmd , invstring , * send_msat , invoice_msat , maxfee ,
2520+ layers , * retryfor , * maxdelay );
2521+ }
2522+
22402523static struct command_result * getchaininfo_done (struct command * aux_cmd ,
22412524 const char * method ,
22422525 const char * buf ,
@@ -2371,6 +2654,10 @@ static const struct plugin_command commands[] = {
23712654 "xpay-as-pay" ,
23722655 json_xpay_as_pay ,
23732656 },
2657+ {
2658+ "sendamount" ,
2659+ json_sendamount ,
2660+ },
23742661};
23752662
23762663static struct command_result * handle_block_added (struct command * cmd ,
0 commit comments