balanceofsatoshis 10.16.2 → 10.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,32 @@
1
1
  # Versions
2
2
 
3
+ ## Version 10.19.0
4
+
5
+ - `balance`: Included locked UTXO value as on-chain value in `--detailed` balance output
6
+ - `increase-inbound-liquidity|pay|probe|rebalance|send`: Add `AGE` to avoid formulas
7
+ - `peers`: Avoid errors when network name is unknown
8
+ - `push`: Add `--message-omit-from-key` to send messages without including "from" key
9
+
10
+ ## Version 10.18.1
11
+
12
+ - `open`: In final tx id indication use original external tx id when available
13
+
14
+ ## Version 10.18.0
15
+
16
+ - `call`: Add support for `broadcastChainTransaction`, `cancelHodlInvoice`
17
+ `cancelPendingChannel`, `createChainAddress`, `createHodlInvoice`, `deletePayments`,
18
+ `settleHodlInvoice`, `subscribeToBackups`, `subscribeToBlocks`,
19
+ `subscribeToChannels`, `subscribeToForwards`, `subscribeToGraph`,
20
+ `subscribeToInvoice`, `subscribeToInvoices`, `subscribeToPeers`,
21
+ `subscribeToTransactions`.
22
+ - `services`: Add service `--invoice` to create invoices on request
23
+ - `services`: Automatically retry on `relay` service if destination payment fails
24
+
25
+ ## Version 10.17.0
26
+
27
+ - `chart-fees-paid`: Add tag icons to nodes in table view
28
+ - `telegram`: Add `/costs` command to report rebalance and chain fees
29
+
3
30
  ## Version 10.16.2
4
31
 
5
32
  - `chart-chain-fees`: Add mempool space chain fee lookup redundancy
package/README.md CHANGED
@@ -12,8 +12,8 @@ Commands for working with LND balances.
12
12
  If you want to try out any command without npm install, you can also do `npx
13
13
  balanceofsatoshis` to run a command directly.
14
14
 
15
- If you have [Docker](https://docs.docker.com/get-docker/) installed, you can
16
- [run through Docker](#docker) instead.
15
+ If you have [Docker](https://docs.docker.com/get-docker/) installed or are using a Docker based
16
+ platform like Umbrel or BTCPayServer, you can [run through Docker](#docker) instead.
17
17
 
18
18
  ```shell
19
19
  npm install -g balanceofsatoshis
@@ -227,7 +227,12 @@ Use any shorthand you'd like when choosing this profile node name
227
227
 
228
228
  #### Umbrel Saved Node
229
229
 
230
- Note: Umbrel is not FOSS software, use at your own risk.
230
+ *Note: Umbrel is not FOSS software, use at your own risk.*
231
+
232
+ If you are using Umbrel and you have already installed but you get an error like
233
+ `Name resolution failed for target dns:umbrel.local:10009` then try adding umbrel.local
234
+ to your `/etc/hosts` file, like `sudo nano /etc/hosts` and add a line
235
+ `127.0.0.1 umbrel.local`
231
236
 
232
237
  1. Identify your Umbrel home dir, like /home/umbrel/umbrel
233
238
  2. Look in the .env file in that dir for the `LND_IP` to use as the socket to connect to
@@ -446,6 +451,17 @@ Or on Linux:
446
451
  --network="host" -v $HOME/.lnd:/home/node/.lnd:ro
447
452
  ```
448
453
 
454
+ On BTCpayServer:
455
+
456
+ Create the credential.json file as explained in the saved nodes section, and for socket put:
457
+ `"socket": "lnd_bitcoin:10009"`
458
+
459
+ For Docker network use the Docker bridged network:
460
+
461
+ ```
462
+ docker run -it --rm --network="generated_default" -v $HOME/.bos:/home/node/.bos alexbosworth/balanceofsatoshis balance --node SAVEDNODENAME
463
+ ```
464
+
449
465
  On Umbrel this would be:
450
466
 
451
467
  ```
@@ -31,6 +31,9 @@ const witnessSizeCounterVByteLength = 0.25;
31
31
  tokens: <Payment Size Tokens Number>
32
32
  }]
33
33
  }]
34
+ locked: [{
35
+ tokens: <Unspent Tokens Number>
36
+ }]
34
37
  pending: [{
35
38
  is_opening: <Channel is Pending Bool>
36
39
  is_partner_initiated: <Partner Responsible For Chain Fees Bool>
@@ -64,7 +67,7 @@ const witnessSizeCounterVByteLength = 0.25;
64
67
  onchain_vbytes: <Estimated Virtual Bytes to Spend On-Chain Funds Number>
65
68
  }
66
69
  */
67
- module.exports = ({channels, pending, transactions, utxos}) => {
70
+ module.exports = ({channels, locked, pending, transactions, utxos}) => {
68
71
  const channelBalances = channels.map(n => n.local_balance);
69
72
  const confirmedUtxos = utxos.filter(n => !!n.confirmation_count);
70
73
 
@@ -115,6 +118,7 @@ module.exports = ({channels, pending, transactions, utxos}) => {
115
118
  const chainBalance = sumOf([]
116
119
  .concat(confirmedUtxos)
117
120
  .concat(changeUtxos)
121
+ .concat(locked)
118
122
  .map(n => n.tokens)
119
123
  );
120
124
 
@@ -21,7 +21,7 @@ const none = 0;
21
21
  lnd: <Authenticated LND API Object>
22
22
  }
23
23
 
24
- @returns via cbk
24
+ @returns via cbk or Promise
25
25
  {
26
26
  balance: <Tokens Number>
27
27
  channel_balance: <Channel Balance Minus Commit Fees Tokens Number>
@@ -2,12 +2,16 @@ const asyncAuto = require('async/auto');
2
2
  const {formatTokens} = require('ln-sync');
3
3
  const {getChainTransactions} = require('ln-service');
4
4
  const {getChannels} = require('ln-service');
5
+ const {getLockedUtxos} = require('ln-service');
5
6
  const {getPendingChannels} = require('ln-service');
6
7
  const {getUtxos} = require('ln-service');
7
8
  const {returnResult} = require('asyncjs-util');
9
+ const {Transaction} = require('bitcoinjs-lib');
8
10
 
9
11
  const detailedBalances = require('./detailed_balances');
10
12
 
13
+ const {fromHex} = Transaction;
14
+
11
15
  /** Get a detailed balance that categorizes balance of tokens on the node
12
16
 
13
17
  {
@@ -39,6 +43,18 @@ module.exports = (args, cbk) => {
39
43
  return getChannels({lnd: args.lnd}, cbk);
40
44
  }],
41
45
 
46
+ // Get locked UTXOs
47
+ getLocked: ['validate', ({}, cbk) => {
48
+ return getLockedUtxos({lnd: args.lnd}, (err, res) => {
49
+ // Ignore errors
50
+ if (!!err) {
51
+ return cbk(null, []);
52
+ }
53
+
54
+ return cbk(null, res.utxos);
55
+ });
56
+ }],
57
+
42
58
  // Get pending channels
43
59
  getPending: ['validate', ({}, cbk) => {
44
60
  return getPendingChannels({lnd: args.lnd}, cbk);
@@ -52,17 +68,49 @@ module.exports = (args, cbk) => {
52
68
  // Get the UTXOs
53
69
  getUtxos: ['validate', ({}, cbk) => getUtxos({lnd: args.lnd}, cbk)],
54
70
 
71
+ // Cross reference locked transactions to UTXO data
72
+ locked: ['getLocked', 'getTx', ({getLocked, getTx}, cbk) => {
73
+ const {transactions} = getTx;
74
+
75
+ const utxos = getLocked.map(locked => {
76
+ // Exit early when the lock is expired
77
+ if (locked.lock_expires_at < new Date().toISOString()) {
78
+ return;
79
+ }
80
+
81
+ const tx = transactions.find(n => n.id === locked.transaction_id);
82
+
83
+ // Exit early when there is no related confirmed transaction
84
+ if (!tx || !tx.transaction || !tx.confirmation_count) {
85
+ return;
86
+ }
87
+
88
+ const output = fromHex(tx.transaction).outs[locked.transaction_vout];
89
+
90
+ // Exit early when the output is not found in the transaction
91
+ if (!output) {
92
+ return;
93
+ }
94
+
95
+ return {tokens: output.value};
96
+ });
97
+
98
+ return cbk(null, utxos.filter(n => !!n));
99
+ }],
100
+
55
101
  // Calculate balance
56
102
  balance: [
57
103
  'getChannels',
58
104
  'getPending',
59
105
  'getTx',
60
106
  'getUtxos',
61
- ({getChannels, getPending, getTx, getUtxos}, cbk) =>
107
+ 'locked',
108
+ ({getChannels, getPending, getTx, getUtxos, locked}, cbk) =>
62
109
  {
63
110
  const format = tokens => formatTokens({tokens}).display.trim();
64
111
 
65
112
  const balances = detailedBalances({
113
+ locked,
66
114
  channels: getChannels.channels,
67
115
  pending: getPending.pending_channels,
68
116
  transactions: getTx.transactions,
@@ -21,14 +21,14 @@ const topPercentile = 0.9;
21
21
  [below]: <Tokens Below Tokens Number>
22
22
  [is_outbound]: <Return Outbound Liquidity Bool>
23
23
  [is_top]: <Return Top Liquidity Bool>
24
- lnd: <Authenticated LND gRPC API Object>
24
+ lnd: <Authenticated LND API Object>
25
25
  [min_node_score]: <Minimum Node Score Number>
26
26
  [max_fee_rate]: <Max Inbound Fee Rate Parts Per Million Number>
27
27
  [request]: <Request Function>
28
28
  [with]: <Liquidity With Specific Node Public Key Hex String>
29
29
  }
30
30
 
31
- @returns via cbk
31
+ @returns via cbk or Promise
32
32
  {
33
33
  balance: <Liquid Tokens Number>
34
34
  }
package/bos CHANGED
@@ -216,6 +216,7 @@ prog
216
216
  return new Promise(async (resolve, reject) => {
217
217
  try {
218
218
  return commands.callRawApi({
219
+ logger,
219
220
  ask: (n, cbk) => inquirer.prompt([n]).then(n => cbk(null, n)),
220
221
  lnd: (await lndForNode(logger, options.node)).lnd,
221
222
  method: args.method,
@@ -358,6 +359,7 @@ prog
358
359
  try {
359
360
  return routing.getFeesPaid({
360
361
  days: options.days,
362
+ fs: {getFile: readFile},
361
363
  is_most_fees_table: options.mostFees,
362
364
  is_most_forwarded_table: options.mostForwarded,
363
365
  is_network: options.network,
@@ -950,7 +952,7 @@ prog
950
952
 
951
953
  // Open channels
952
954
  .command('open', 'Open channels, optionally using an external wallet')
953
- .help('Create channels from an external wallet. Note: do not self-broadcast')
955
+ .help('When creating channels from an external wallet do not self-broadcast')
954
956
  .argument('<peer_public_keys...>', 'With nodes with public keys')
955
957
  .option('--amount <channel_capacity>', 'Capacities to open', REPEATABLE)
956
958
  .option('--external-funding', 'Use external funds for the channel open')
@@ -1189,7 +1191,7 @@ prog
1189
1191
  .help('--avoid can take a channel id or a public key to avoid')
1190
1192
  .help('--avoid can take a public_key/public_key to avoid a directed pair')
1191
1193
  .help('--avoid can take a FORMULA/public_key to avoid inbound peers')
1192
- .help('--avoid FORMULA variables: FEE_RATE, BASE_FEE, HEIGHT')
1194
+ .help('--avoid FORMULA variables: FEE_RATE, BASE_FEE, HEIGHT, AGE')
1193
1195
  .help('--in decreases the inbound liquidity with a specific peer/tag')
1194
1196
  .help('--out increases the inbound liquidity with a specific peer/tag')
1195
1197
  .option('--amount <amount>', 'Maximum amount to rebalance')
@@ -1346,6 +1348,7 @@ prog
1346
1348
  .option('--in <pubkey_or_alias>', 'Route in through a specific node')
1347
1349
  .option('--max-fee <fee>', 'Maximum fee tokens', INT, 1337)
1348
1350
  .option('--message <message>', 'Message to include with payment')
1351
+ .option('--message-omit-from-key', 'Leave out the from key on messages')
1349
1352
  .option('--no-color', 'Mute all colors')
1350
1353
  .option('--node <name>', 'Node to send funds from')
1351
1354
  .option('--out <pubkey_or_alias>', 'Route out through a specific peer')
@@ -1366,6 +1369,7 @@ prog
1366
1369
  fs: {getFile: readFile},
1367
1370
  in_through: options.in,
1368
1371
  is_dry_run: options.dryrun,
1372
+ is_omitting_message_from: options.messageOmitFromKey,
1369
1373
  max_fee: options.maxFee,
1370
1374
  message: options.message,
1371
1375
  quiz_answers: flatten([options.quiz].filter(n => !!n)),
@@ -1393,6 +1397,7 @@ prog
1393
1397
  .option('--inbox-sms-to', 'Inbox service sms to number')
1394
1398
  .option('--inbox-sms-twilio-sid', 'Inbox service Twilio account sid')
1395
1399
  .option('--inbox-sms-twilio-auth', 'Inbox service Twilio auth token')
1400
+ .option('--invoice', 'Enable creating custom invoices on demand')
1396
1401
  .option('--node <node_name>', 'Saved node')
1397
1402
  .option('--payer <pay_with_node_name>', 'Node to pay request responses with')
1398
1403
  .option('--profile <profile>', 'Share a profile with info about your node')
@@ -1416,6 +1421,7 @@ prog
1416
1421
  inbox_twilio_account_sid: options.inboxSmsTwilioSid,
1417
1422
  inbox_twilio_auth_token: options.inboxSmsTwilioAuth,
1418
1423
  is_connect_enabled: !!options.connect || undefined,
1424
+ is_invoice_enabled: !!options.invoice || undefined,
1419
1425
  is_relay_enabled: !!options.relay || undefined,
1420
1426
  network_nodes: flatten([options.network].filter(n => !!n)),
1421
1427
  node: options.node,
package/commands/api.json CHANGED
@@ -14,6 +14,40 @@
14
14
  ],
15
15
  "method": "addPeer"
16
16
  },
17
+ {
18
+ "arguments": [
19
+ {
20
+ "description": "Raw hex encoded signed raw transaction",
21
+ "named": "transaction"
22
+ },
23
+ {
24
+ "description": "Transaction description label",
25
+ "named": "description",
26
+ "optional": true
27
+ }
28
+ ],
29
+ "method": "broadcastChainTransaction"
30
+ },
31
+ {
32
+ "arguments": [
33
+ {
34
+ "description": "Id of invoice to cancel",
35
+ "named": "id",
36
+ "type": "hash"
37
+ }
38
+ ],
39
+ "method": "cancelHodlInvoice"
40
+ },
41
+ {
42
+ "arguments": [
43
+ {
44
+ "description": "Id of pending channel to cancel",
45
+ "named": "id",
46
+ "type": "hash"
47
+ }
48
+ ],
49
+ "method": "cancelPendingChannel"
50
+ },
17
51
  {
18
52
  "arguments": [
19
53
  {
@@ -34,6 +68,42 @@
34
68
  ],
35
69
  "method": "closeChannel"
36
70
  },
71
+ {
72
+ "arguments": [
73
+ {
74
+ "description": "Chain address format, np2wpkh or p2wpkh",
75
+ "named": "format"
76
+ }
77
+ ],
78
+ "method": "createChainAddress"
79
+ },
80
+ {
81
+ "arguments": [
82
+ {
83
+ "description": "Final CLTV delta",
84
+ "named": "cltv_delta",
85
+ "optional": true,
86
+ "type": "number"
87
+ },
88
+ {
89
+ "description": "Description",
90
+ "named": "description",
91
+ "optional": true
92
+ },
93
+ {
94
+ "description": "Hash",
95
+ "named": "id",
96
+ "optional": true,
97
+ "type": "hash"
98
+ },
99
+ {
100
+ "description": "Millitokens to request",
101
+ "named": "mtokens",
102
+ "optional": true
103
+ }
104
+ ],
105
+ "method": "createHodlInvoice"
106
+ },
37
107
  {
38
108
  "arguments": [
39
109
  {
@@ -72,6 +142,9 @@
72
142
  {
73
143
  "method": "deleteForwardingReputations"
74
144
  },
145
+ {
146
+ "method": "deletePayments"
147
+ },
75
148
  {
76
149
  "arguments": [
77
150
  {
@@ -250,6 +323,16 @@
250
323
  {
251
324
  "method": "getIdentity"
252
325
  },
326
+ {
327
+ "arguments": [
328
+ {
329
+ "description": "Invoice hex encoded payment hash",
330
+ "named": "id",
331
+ "type": "hash"
332
+ }
333
+ ],
334
+ "method": "getInvoice"
335
+ },
253
336
  {
254
337
  "arguments": [
255
338
  {
@@ -266,16 +349,6 @@
266
349
  ],
267
350
  "method": "getInvoices"
268
351
  },
269
- {
270
- "arguments": [
271
- {
272
- "description": "Invoice hex encoded payment hash",
273
- "named": "id",
274
- "type": "hash"
275
- }
276
- ],
277
- "method": "getInvoice"
278
- },
279
352
  {
280
353
  "method": "getLockedUtxos"
281
354
  },
@@ -476,6 +549,15 @@
476
549
  ],
477
550
  "method": "requestChainFeeIncrease"
478
551
  },
552
+ {
553
+ "arguments": [
554
+ {
555
+ "description": "Hex encoded secret preimage",
556
+ "named": "secret"
557
+ }
558
+ ],
559
+ "method": "settleHodlInvoice"
560
+ },
479
561
  {
480
562
  "arguments": [{
481
563
  "description": "Message to sign",
@@ -486,6 +568,54 @@
486
568
  {
487
569
  "method": "stopDaemon"
488
570
  },
571
+ {
572
+ "events": ["backup"],
573
+ "method": "subscribeToBackups"
574
+ },
575
+ {
576
+ "events": ["block"],
577
+ "method": "subscribeToBlocks"
578
+ },
579
+ {
580
+ "events": [
581
+ "channel_active_changed",
582
+ "channel_closed",
583
+ "channel_opened",
584
+ "channel_opening"
585
+ ],
586
+ "method": "subscribeToChannels"
587
+ },
588
+ {
589
+ "events": ["forward"],
590
+ "method": "subscribeToForwards"
591
+ },
592
+ {
593
+ "events": ["channel_closed", "channel_updated", "node_updated"],
594
+ "method": "subscribeToGraph"
595
+ },
596
+ {
597
+ "arguments": [
598
+ {
599
+ "description": "Invoice preimage hash hex encoded",
600
+ "named": "id",
601
+ "type": "hash"
602
+ }
603
+ ],
604
+ "events": ["invoice_updated"],
605
+ "method": "subscribeToInvoice"
606
+ },
607
+ {
608
+ "events": ["invoice_updated"],
609
+ "method": "subscribeToInvoices"
610
+ },
611
+ {
612
+ "events": ["connected", "disconnected"],
613
+ "method": "subscribeToPeers"
614
+ },
615
+ {
616
+ "events": ["chain_transaction"],
617
+ "method": "subscribeToTransactions"
618
+ },
489
619
  {
490
620
  "arguments": [
491
621
  {
@@ -10,19 +10,21 @@ const isHash = n => !!n && /^[0-9A-F]{64}$/i.test(n);
10
10
  const isPublicKey = n => !!n && /^0[2-3][0-9A-F]{64}$/i.test(n);
11
11
  const {keys} = Object;
12
12
  const lower = n => n.toLowerCase();
13
+ const methodDetails = (calls, method) => calls.find(n => n.method === method);
13
14
 
14
15
  /** Call the raw API
15
16
 
16
17
  {
17
18
  ask: <Inquirer Function> ({message, name, type}, cbk) => {}
18
19
  lnd: <Authenticated LND API Object>
20
+ logger: <Winston Logger Object>
19
21
  [method]: <Method to Call String>
20
22
  }
21
23
 
22
24
  @returns via cbk or Promise
23
25
  <Result Object>
24
26
  */
25
- module.exports = ({ask, lnd, method}, cbk) => {
27
+ module.exports = ({ask, lnd, logger, method}, cbk) => {
26
28
  return new Promise((resolve, reject) => {
27
29
  return asyncAuto({
28
30
  // Check arguments
@@ -35,6 +37,10 @@ module.exports = ({ask, lnd, method}, cbk) => {
35
37
  return cbk([400, 'ExpectedAuthenticatedLndToCallApi']);
36
38
  }
37
39
 
40
+ if (!logger) {
41
+ return cbk([400, 'ExpectedLoggerToCallApi']);
42
+ }
43
+
38
44
  if (!!method && !calls.find(n => lower(n.method) === lower(method))) {
39
45
  return cbk([404, 'UnrecognizedMethod']);
40
46
  }
@@ -118,8 +124,8 @@ module.exports = ({ask, lnd, method}, cbk) => {
118
124
  cbk);
119
125
  }],
120
126
 
121
- // Call API
122
- call: ['getArguments', 'getMethod', ({getArguments, getMethod}, cbk) => {
127
+ // Derive arguments
128
+ arguments: ['getArguments', ({getArguments}, cbk) => {
123
129
  const arguments = getArguments.reduce((sum, answer) => {
124
130
  keys(answer).forEach(key => {
125
131
  if (answer[key] === Number()) {
@@ -133,6 +139,34 @@ module.exports = ({ask, lnd, method}, cbk) => {
133
139
  },
134
140
  {lnd});
135
141
 
142
+ return cbk(null, arguments);
143
+ }],
144
+
145
+ // Set up subscription
146
+ subscribe: ['arguments', 'getMethod', ({arguments, getMethod}, cbk) => {
147
+ // Exit early when this is a request/response API
148
+ if (!methodDetails(calls, getMethod.method).events) {
149
+ return cbk();
150
+ }
151
+
152
+ const sub = lnService[getMethod.method](arguments);
153
+
154
+ sub.on('error', err => cbk([503, 'ApiSubscriptionError', {err}]));
155
+
156
+ const {events} = methodDetails(calls, getMethod.method);
157
+
158
+ logger.info({listening_for: events});
159
+
160
+ events.forEach(n => sub.on(n, data => logger.info({[n]: data})));
161
+ }],
162
+
163
+ // Call API
164
+ call: ['arguments', 'getMethod', ({arguments, getMethod}, cbk) => {
165
+ // Exit early when this is an event-based API
166
+ if (!!methodDetails(calls, getMethod.method).events) {
167
+ return cbk();
168
+ }
169
+
136
170
  return lnService[getMethod.method](arguments, cbk);
137
171
  }],
138
172
  },
@@ -1,5 +1,6 @@
1
1
  const asyncAuto = require('async/auto');
2
2
  const asyncMap = require('async/map');
3
+ const asyncReflect = require('async/reflect');
3
4
  const asyncUntil = require('async/until');
4
5
  const {bold} = require('colorette');
5
6
  const {decodeChanId} = require('bolt07');
@@ -191,6 +192,11 @@ module.exports = (args, cbk) => {
191
192
  );
192
193
  }],
193
194
 
195
+ // Get the network name
196
+ getNetwork: ['validate', asyncReflect(({}, cbk) => {
197
+ return getNetwork({lnd: args.lnd}, cbk);
198
+ })],
199
+
194
200
  // Get payments
195
201
  getPayments: ['validate', ({}, cbk) => {
196
202
  // Exit early and skip long payments lookup when idle days not needed
@@ -330,6 +336,7 @@ module.exports = (args, cbk) => {
330
336
  'forwards',
331
337
  'getChannels',
332
338
  'getInvoices',
339
+ 'getNetwork',
333
340
  'getPayments',
334
341
  'getPeers',
335
342
  'getPending',
@@ -339,6 +346,7 @@ module.exports = (args, cbk) => {
339
346
  forwards,
340
347
  getChannels,
341
348
  getInvoices,
349
+ getNetwork,
342
350
  getPayments,
343
351
  getPeers,
344
352
  getPending,
@@ -400,7 +408,7 @@ module.exports = (args, cbk) => {
400
408
 
401
409
  const maxInbound = args.inbound_liquidity_below;
402
410
  const maxOutbound = args.outbound_liquidity_below;
403
- const {network} = await getNetwork({lnd: args.lnd});
411
+ const {network} = getNetwork.value || {};
404
412
  const peerKeys = getChannels.channels.map(n => n.partner_public_key);
405
413
  const wallet = await getHeight({lnd: args.lnd});
406
414
 
@@ -53,6 +53,7 @@ const tokAsMtok = tokens => (BigInt(tokens || 0) * BigInt(1e3)).toString();
53
53
  [to_public_key]: <Avoid Routing To Node With Public Key Hex String>
54
54
  }]
55
55
  [in_through]: <Pay In Through Public Key Hex String>
56
+ [is_omitting_message_from]: <Omit Message From Fields Bool>
56
57
  [is_push]: <Is Push Payment Bool>
57
58
  [is_real_payment]: <Pay the Request after Probing Bool> // default: false
58
59
  [is_strict_max_fee]: <Avoid Probing Too-High Fee Routes Bool>
@@ -238,14 +239,17 @@ module.exports = (args, cbk) => {
238
239
 
239
240
  date.writeUIntBE(now(), Number(), datePrecisionLength);
240
241
 
242
+ // Add message
241
243
  if (!!args.message) {
242
- messages.push({type: dateType, value: date.toString('hex')});
243
-
244
244
  messages.push({
245
245
  type: messageType,
246
246
  value: Buffer.from(args.message).toString('hex'),
247
247
  });
248
+ }
248
249
 
250
+ // Add message from fields
251
+ if (!!args.message && !args.is_omitting_message_from) {
252
+ messages.push({type: dateType, value: date.toString('hex')});
249
253
  messages.push({type: fromKeyType, value: getIdentity.public_key});
250
254
 
251
255
  const preimage = Buffer.concat([
@@ -39,6 +39,7 @@ const utf8AsHex = n => Buffer.from(n, 'utf8').toString('hex');
39
39
  }
40
40
  [in_through]: <Pay In Through Peer String>
41
41
  [is_dry_run]: <Do Not Push Payment Bool>
42
+ [is_omitting_message_from]: <Do Not Include From Key In Message Bool>
42
43
  lnd: <Authenticated LND API Object>
43
44
  logger: <Winston Logger Object>
44
45
  max_fee: <Maximum Fee Tokens Number>
@@ -74,6 +75,10 @@ module.exports = (args, cbk) => {
74
75
  return cbk([400, 'MultipleInboundPeersNotSupported']);
75
76
  }
76
77
 
78
+ if (!!args.is_omitting_message_from && !args.message) {
79
+ return cbk([400, 'ExpectedMessageToSendWhenSpecifyingOmitFromKey']);
80
+ }
81
+
77
82
  if (!args.lnd) {
78
83
  return cbk([400, 'ExpectedAuthenticatedLndToPushPayment']);
79
84
  }
@@ -365,6 +370,7 @@ module.exports = (args, cbk) => {
365
370
  lnd: args.lnd,
366
371
  logger: args.logger,
367
372
  in_through: getInKey,
373
+ is_omitting_message_from: args.is_omitting_message_from,
368
374
  is_push: true,
369
375
  is_real_payment: true,
370
376
  max_fee: args.max_fee,