github.com/decred/dcrlnd@v0.7.6/cmd/dcrlncli/invoicesrpc_active.go (about) 1 //go:build !no_invoicesrpc 2 // +build !no_invoicesrpc 3 4 package main 5 6 import ( 7 "encoding/hex" 8 "fmt" 9 "strconv" 10 11 "github.com/decred/dcrlnd/lnrpc/invoicesrpc" 12 13 "github.com/urfave/cli" 14 ) 15 16 // invoicesCommands will return nil for non-invoicesrpc builds. 17 func invoicesCommands() []cli.Command { 18 return []cli.Command{ 19 cancelInvoiceCommand, 20 addHoldInvoiceCommand, 21 settleInvoiceCommand, 22 } 23 } 24 25 func getInvoicesClient(ctx *cli.Context) (invoicesrpc.InvoicesClient, func()) { 26 conn := getClientConn(ctx, false) 27 28 cleanUp := func() { 29 conn.Close() 30 } 31 32 return invoicesrpc.NewInvoicesClient(conn), cleanUp 33 } 34 35 var settleInvoiceCommand = cli.Command{ 36 Name: "settleinvoice", 37 Category: "Invoices", 38 Usage: "Reveal a preimage and use it to settle the corresponding invoice.", 39 Description: ` 40 Todo.`, 41 ArgsUsage: "preimage", 42 Flags: []cli.Flag{ 43 cli.StringFlag{ 44 Name: "preimage", 45 Usage: "The hex-encoded preimage (32 byte) which will " + 46 "allow settling an incoming HTLC payable to this " + 47 "preimage.", 48 }, 49 }, 50 Action: actionDecorator(settleInvoice), 51 } 52 53 func settleInvoice(ctx *cli.Context) error { 54 var ( 55 preimage []byte 56 err error 57 ) 58 59 ctxc := getContext() 60 client, cleanUp := getInvoicesClient(ctx) 61 defer cleanUp() 62 63 args := ctx.Args() 64 65 switch { 66 case ctx.IsSet("preimage"): 67 preimage, err = hex.DecodeString(ctx.String("preimage")) 68 case args.Present(): 69 preimage, err = hex.DecodeString(args.First()) 70 } 71 72 if err != nil { 73 return fmt.Errorf("unable to parse preimage: %v", err) 74 } 75 76 invoice := &invoicesrpc.SettleInvoiceMsg{ 77 Preimage: preimage, 78 } 79 80 resp, err := client.SettleInvoice(ctxc, invoice) 81 if err != nil { 82 return err 83 } 84 85 printRespJSON(resp) 86 87 return nil 88 } 89 90 var cancelInvoiceCommand = cli.Command{ 91 Name: "cancelinvoice", 92 Category: "Invoices", 93 Usage: "Cancels a (hold) invoice.", 94 Description: ` 95 Todo.`, 96 ArgsUsage: "paymenthash", 97 Flags: []cli.Flag{ 98 cli.StringFlag{ 99 Name: "paymenthash", 100 Usage: "The hex-encoded payment hash (32 byte) for which the " + 101 "corresponding invoice will be canceled.", 102 }, 103 }, 104 Action: actionDecorator(cancelInvoice), 105 } 106 107 func cancelInvoice(ctx *cli.Context) error { 108 var ( 109 paymentHash []byte 110 err error 111 ) 112 113 ctxc := getContext() 114 client, cleanUp := getInvoicesClient(ctx) 115 defer cleanUp() 116 117 args := ctx.Args() 118 119 switch { 120 case ctx.IsSet("paymenthash"): 121 paymentHash, err = hex.DecodeString(ctx.String("paymenthash")) 122 case args.Present(): 123 paymentHash, err = hex.DecodeString(args.First()) 124 } 125 126 if err != nil { 127 return fmt.Errorf("unable to parse preimage: %v", err) 128 } 129 130 invoice := &invoicesrpc.CancelInvoiceMsg{ 131 PaymentHash: paymentHash, 132 } 133 134 resp, err := client.CancelInvoice(ctxc, invoice) 135 if err != nil { 136 return err 137 } 138 139 printRespJSON(resp) 140 141 return nil 142 } 143 144 var addHoldInvoiceCommand = cli.Command{ 145 Name: "addholdinvoice", 146 Category: "Invoices", 147 Usage: "Add a new hold invoice.", 148 Description: ` 149 Add a new invoice, expressing intent for a future payment. 150 151 Invoices without an amount can be created by not supplying any 152 parameters or providing an amount of 0. These invoices allow the payee 153 to specify the amount of atoms they wish to send.`, 154 ArgsUsage: "hash [amt]", 155 Flags: []cli.Flag{ 156 cli.StringFlag{ 157 Name: "memo", 158 Usage: "A description of the payment to attach along " + 159 "with the invoice (default=\"\")", 160 }, 161 cli.Int64Flag{ 162 Name: "amt", 163 Usage: "The amt of atoms in this invoice", 164 }, 165 cli.Int64Flag{ 166 Name: "amt_m_atoms", 167 Usage: "The amt of milliatoms in this invoice", 168 }, 169 cli.StringFlag{ 170 Name: "description_hash", 171 Usage: "SHA-256 hash of the description of the payment. " + 172 "Used if the purpose of payment cannot naturally " + 173 "fit within the memo. If provided this will be " + 174 "used instead of the description(memo) field in " + 175 "the encoded invoice.", 176 }, 177 cli.StringFlag{ 178 Name: "fallback_addr", 179 Usage: "Fallback on-chain address that can be used in " + 180 "case the lightning payment fails", 181 }, 182 cli.Int64Flag{ 183 Name: "expiry", 184 Usage: "The invoice's expiry time in seconds. If not " + 185 "specified, an expiry of 3600 seconds (1 hour) " + 186 "is implied.", 187 }, 188 cli.BoolTFlag{ 189 Name: "private", 190 Usage: "Encode routing hints in the invoice with " + 191 "private channels in order to assist the " + 192 "payer in reaching you", 193 }, 194 }, 195 Action: actionDecorator(addHoldInvoice), 196 } 197 198 func addHoldInvoice(ctx *cli.Context) error { 199 var ( 200 descHash []byte 201 err error 202 ) 203 204 ctxc := getContext() 205 client, cleanUp := getInvoicesClient(ctx) 206 defer cleanUp() 207 208 args := ctx.Args() 209 if ctx.NArg() == 0 { 210 cli.ShowCommandHelp(ctx, "addholdinvoice") 211 return nil 212 } 213 214 hash, err := hex.DecodeString(args.First()) 215 if err != nil { 216 return fmt.Errorf("unable to parse hash: %v", err) 217 } 218 219 args = args.Tail() 220 221 amt := ctx.Int64("amt") 222 amtMAtoms := ctx.Int64("amt_m_atoms") 223 224 if !ctx.IsSet("amt") && !ctx.IsSet("amt_m_atoms") && args.Present() { 225 amt, err = strconv.ParseInt(args.First(), 10, 64) 226 if err != nil { 227 return fmt.Errorf("unable to decode amt argument: %v", err) 228 } 229 } 230 231 descHash, err = hex.DecodeString(ctx.String("description_hash")) 232 if err != nil { 233 return fmt.Errorf("unable to parse description_hash: %v", err) 234 } 235 236 invoice := &invoicesrpc.AddHoldInvoiceRequest{ 237 Memo: ctx.String("memo"), 238 Hash: hash, 239 Value: amt, 240 ValueMAtoms: amtMAtoms, 241 DescriptionHash: descHash, 242 FallbackAddr: ctx.String("fallback_addr"), 243 Expiry: ctx.Int64("expiry"), 244 Private: ctx.Bool("private"), 245 } 246 247 resp, err := client.AddHoldInvoice(ctxc, invoice) 248 if err != nil { 249 return err 250 } 251 252 printRespJSON(resp) 253 254 return nil 255 }