paid-services 3.4.0 → 3.7.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.
Files changed (38) hide show
  1. package/.prettierignore +2 -0
  2. package/CHANGELOG.md +16 -0
  3. package/capacity/accept_capacity_change.js +2 -0
  4. package/capacity/ask_for_change_details.js +41 -9
  5. package/capacity/ask_for_decrease.js +167 -49
  6. package/capacity/capacity_change_requests.js +9 -0
  7. package/capacity/change_channel_capacity.js +7 -1
  8. package/capacity/encode_change_request.js +8 -1
  9. package/capacity/fee_for_replacement.js +3 -7
  10. package/capacity/get_capacity_change_requests.js +1 -0
  11. package/capacity/get_capacity_replacement.js +56 -7
  12. package/capacity/initiate_capacity_change.js +1 -2
  13. package/capacity/parse_capacity_change_request.js +8 -1
  14. package/capacity/propose_capacity_change.js +208 -92
  15. package/capacity/propose_channel_open.js +54 -0
  16. package/package.json +9 -9
  17. package/services/response_for_relay.js +0 -1
  18. package/test/capacity/test_capacity_change_requests.js +1 -0
  19. package/test/capacity/test_encode_change_request.js +5 -0
  20. package/test/capacity/test_parse_capacity_change_request.js +1 -0
  21. package/test/integration/test_accept_capacity_change.js +3 -4
  22. package/test/integration/test_change_channel_capacity.js +8 -1
  23. package/test/integration/test_decrease_channel_capacity.js +23 -8
  24. package/test/integration/test_increase_channel_capacity.js +4 -1
  25. package/test/integration/test_split_channel_capacity.js +241 -0
  26. package/trades/accept_trade.js +12 -3
  27. package/trades/create_trade.js +82 -50
  28. package/trades/decode_anchored_trade.js +56 -0
  29. package/trades/encode_anchored_trade.js +35 -0
  30. package/trades/finalize_trade_secret.js +7 -0
  31. package/trades/find_trade.js +28 -3
  32. package/trades/manage_trade.js +15 -4
  33. package/trades/manage_trades.js +209 -2
  34. package/trades/request_trade_by_id.js +7 -1
  35. package/trades/service_anchored_trades.js +181 -0
  36. package/trades/service_open_trade.js +172 -0
  37. package/trades/service_trade_requests.js +106 -35
  38. package/trades/trade_from_invoice.js +51 -0
@@ -0,0 +1,2 @@
1
+ bos
2
+ *.js
package/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Versions
2
2
 
3
+ ## Version 3.7.0
4
+
5
+ - `changeChannelCapacity`: Add support for decreasing funds into a new channel
6
+
7
+ ## Version 3.6.0
8
+
9
+ - `manageTrades`: Add support for persistent open trades
10
+ - `manageTrades`: Add expiration dates to open trades
11
+ - `manageTrades`: Support longer-lived open trade scenarios
12
+ - `manageTrades`: Show final encoded trade when requesting open trade
13
+ - `manageTrades`: Check for RPC signer support before trading
14
+
15
+ ## Version 3.5.1
16
+
17
+ - `changeChannelCapacity`: Allow changing private/public status of channel
18
+
3
19
  ## Version 3.4.0
4
20
 
5
21
  - `changeChannelCapacity`: Fix broken preservation of channel announce status
@@ -212,6 +212,8 @@ module.exports = ({channel, from, id, increase, lnd, logger}, cbk) => {
212
212
  return failure([503, 'FailedToParseSignChangeRequest']);
213
213
  }
214
214
 
215
+ logger.info({closing_and_reopening_channel: true});
216
+
215
217
  // Trigger the replacement flow and sign the unsigned tx
216
218
  return getReplacementSignature({
217
219
  channel,
@@ -24,6 +24,8 @@ const minNewLocalBalance = 0;
24
24
  const nonNegative = n => Math.max(0, n);
25
25
  const outputSize = 44;
26
26
  const positive = n => Math.max(1, n);
27
+ const privateType = 1;
28
+ const publicType = 0;
27
29
  const slowTarget = 1000;
28
30
  const sumOf = arr => arr.reduce((sum, n) => sum + n, 0);
29
31
  const sumOfTokens = arr => arr.reduce((sum, n) => sum + n.tokens, 0);
@@ -46,8 +48,9 @@ const weightBuffer = 150;
46
48
  cltv_delta: <Locktime Delta Number>
47
49
  coop_close_address: <Cooperative Close Address String>
48
50
  decrease: [{
49
- address: <Decrease Address String>
50
- output: <Output Script Hex String>
51
+ [address]: <Decrease Address String>
52
+ [node]: <Create Channel with Node With Public Key Hex String>
53
+ [output]: <Output Script Hex String>
51
54
  tokens: <Decrease Tokens Number>
52
55
  }]
53
56
  estimated_capacity: <Estimated Tokens For New Channel Capacity Number>
@@ -170,6 +173,7 @@ module.exports = ({ask, id, lnd}, cbk) => {
170
173
  const disabled = [
171
174
  !!channel.cooperative_close_address,
172
175
  !channel.is_active,
176
+ !!channel.pending_payments.length,
173
177
  ];
174
178
 
175
179
  return {
@@ -342,7 +346,7 @@ module.exports = ({ask, id, lnd}, cbk) => {
342
346
  return cbk(err);
343
347
  }
344
348
 
345
- if (decreases.find(n => n.address === res.address)) {
349
+ if (!!res.address && decreases.find(n => n.address === res.address)) {
346
350
  return cbk([400, 'ExpectedUniqueAddressForSpend']);
347
351
  }
348
352
 
@@ -354,11 +358,8 @@ module.exports = ({ask, id, lnd}, cbk) => {
354
358
  return cbk(err);
355
359
  }
356
360
 
357
- const final = decreases
358
- .filter(n => !!n.tokens)
359
- .map(({address, output, tokens}) => ({address, output, tokens}));
360
-
361
- return cbk(null, final);
361
+ // Only include decreases that spend funds
362
+ return cbk(null, decreases.filter(n => !!n.tokens));
362
363
  }
363
364
  );
364
365
  }],
@@ -395,10 +396,37 @@ module.exports = ({ask, id, lnd}, cbk) => {
395
396
  ({amount}) => cbk(null, Number(amount)));
396
397
  }],
397
398
 
399
+ // Confirm or change the announce status of the replacement channel
400
+ askForPublicPrivate: [
401
+ 'askForDecrease',
402
+ 'askForIncrease',
403
+ 'channel',
404
+ ({channel}, cbk) =>
405
+ {
406
+ return ask({
407
+ choices: ['Public', 'Private'].map(type => {
408
+ const isPrivate = type === 'Private';
409
+
410
+ // Exit early when the type would be different
411
+ if (isPrivate !== channel.is_private) {
412
+ return type;
413
+ }
414
+
415
+ return `${type} (keep current status)`;
416
+ }),
417
+ default: channel.is_private ? 'Private' : 'Public',
418
+ message: 'Replacement channel type?',
419
+ name: 'type',
420
+ type: 'list',
421
+ },
422
+ ({type}) => cbk(null, {is_private: type === 'Private'}));
423
+ }],
424
+
398
425
  // Estimate the chain fee
399
426
  estimateChainFee: [
400
427
  'askForDecrease',
401
428
  'askForIncrease',
429
+ 'askForPublicPrivate',
402
430
  'channel',
403
431
  'getFeeRate',
404
432
  ({askForDecrease, askForIncrease, channel, getFeeRate}, cbk) =>
@@ -417,6 +445,7 @@ module.exports = ({ask, id, lnd}, cbk) => {
417
445
 
418
446
  // Confirm chain fee payment estimate
419
447
  confirmFeeEstimate: [
448
+ 'askForPublicPrivate',
420
449
  'channel',
421
450
  'estimateChainFee',
422
451
  ({channel, estimateChainFee}, cbk) =>
@@ -437,6 +466,7 @@ module.exports = ({ask, id, lnd}, cbk) => {
437
466
  details: [
438
467
  'askForDecrease',
439
468
  'askForIncrease',
469
+ 'askForPublicPrivate',
440
470
  'channel',
441
471
  'confirmFeeEstimate',
442
472
  'estimateChainFee',
@@ -444,6 +474,7 @@ module.exports = ({ask, id, lnd}, cbk) => {
444
474
  ({
445
475
  askForDecrease,
446
476
  askForIncrease,
477
+ askForPublicPrivate,
447
478
  channel,
448
479
  confirmFeeEstimate,
449
480
  estimateChainFee,
@@ -478,6 +509,7 @@ module.exports = ({ask, id, lnd}, cbk) => {
478
509
  channel: channel.id,
479
510
  decrease: !!askForDecrease ? sumOfTokens(askForDecrease) : undefined,
480
511
  increase: askForIncrease,
512
+ type: askForPublicPrivate.is_private ? privateType : publicType,
481
513
  });
482
514
 
483
515
  return cbk(null, {
@@ -491,7 +523,7 @@ module.exports = ({ask, id, lnd}, cbk) => {
491
523
  fee_rate: channel.fee_rate,
492
524
  id: channel.id,
493
525
  increase: askForIncrease,
494
- is_private: channel.is_private,
526
+ is_private: askForPublicPrivate.is_private,
495
527
  open_transaction: channel.open_transaction,
496
528
  partner_csv_delay: channel.partner_csv_delay,
497
529
  partner_public_key: channel.partner_public_key,
@@ -1,14 +1,28 @@
1
1
  const {address} = require('bitcoinjs-lib');
2
2
  const asyncAuto = require('async/auto');
3
3
  const {createChainAddress} = require('ln-service');
4
+ const {getIdentity} = require('ln-service');
5
+ const {acceptsChannelOpen} = require('ln-sync');
4
6
  const {getNetwork} = require('ln-sync');
5
7
  const {networks} = require('bitcoinjs-lib');
6
8
  const {returnResult} = require('asyncjs-util');
7
9
 
10
+ const proposeChannelOpen = require('./propose_channel_open');
11
+
12
+ const askForChanSize = max => `Capacity of the new channel? (max: ${max})`;
13
+ const askForSendSize = max => `Amount you want to send out? (max: ${max})`;
8
14
  const bufferAsHex = buffer => buffer.toString('hex');
9
15
  const dust = 550;
16
+ const {isInteger} = Number;
10
17
  const isNumber = n => !isNaN(n);
18
+ const isPublicKey = n => !!n && /^0[2-3][0-9A-F]{64}$/i.test(n);
19
+ const minChannelCapacity = 20000;
20
+ const minSpendTokens = 0;
21
+ const openChannelAction = 'open_channel';
22
+ const spendToExternalAddressAction = 'external_spend_funds';
23
+ const spendToInternalAddressAction = 'internal_spend_funds';
11
24
  const {toOutputScript} = address;
25
+ const tokensAsBigUnit = tokens => (tokens / 1e8).toFixed(8);
12
26
 
13
27
  /** Ask for details about a decrease
14
28
 
@@ -22,6 +36,7 @@ const {toOutputScript} = address;
22
36
  {
23
37
  [address]: <Send Funds to Address String>
24
38
  is_final: <Decrease is Final Decrease Bool>
39
+ [node]: <Create Channel with Node With Public Key Hex String>
25
40
  [output]: <Output Script Hex String>
26
41
  tokens: <Withdraw Tokens Number>
27
42
  }
@@ -46,66 +61,149 @@ module.exports = ({ask, lnd, max}, cbk) => {
46
61
  return cbk();
47
62
  },
48
63
 
49
- // Ask for the amount to decrease
50
- askForAmount: ['validate', ({}, cbk) => {
64
+ // Select the type of decrease
65
+ askForDecreaseType: ['validate', ({}, cbk) => {
51
66
  return ask({
52
- default: '0',
53
- name: 'amount',
54
- message: `How much do you want to spend out (max: ${max})?`,
67
+ choices: [
68
+ {
69
+ name: `Send decreased funds to the internal chain wallet`,
70
+ value: spendToInternalAddressAction,
71
+ },
72
+ {
73
+ name: `Send decreased funds to an external chain address`,
74
+ value: spendToExternalAddressAction,
75
+ },
76
+ {
77
+ disabled: max < minChannelCapacity,
78
+ name: `Spend decreased funds into new channel with another peer`,
79
+ value: openChannelAction,
80
+ },
81
+ ],
82
+ message: 'How do you want to change the channel capacity?',
83
+ name: 'decrease',
84
+ type: 'list',
85
+ },
86
+ ({decrease}) => cbk(null, decrease));
87
+ }],
88
+
89
+ // Get the node identity key to make sure a channel open isn't with self
90
+ getIdentity: ['validate', ({}, cbk) => getIdentity({lnd}, cbk)],
91
+
92
+ // Get network name to validate addresses against
93
+ getNetwork: ['validate', ({}, cbk) => getNetwork({lnd}, cbk)],
94
+
95
+ // Ask for the public key of the node to trade with
96
+ askForNodeId: [
97
+ 'askForDecreaseType',
98
+ 'getIdentity',
99
+ ({askForDecreaseType, getIdentity}, cbk) =>
100
+ {
101
+ // Exit early when not opening a new channel
102
+ if (askForDecreaseType !== openChannelAction) {
103
+ return cbk();
104
+ }
105
+
106
+ return ask({
107
+ name: 'key',
108
+ message: 'Public key of node to open channel with?',
55
109
  type: 'input',
56
110
  validate: input => {
57
- if (!isNumber(input) || !Number.isInteger(Number(input))) {
111
+ if (!input) {
58
112
  return false;
59
113
  }
60
114
 
61
- if (!!Number(input) && Number(input) < dust) {
62
- return false;
115
+ if (!isPublicKey(input)) {
116
+ return 'Expected public key of node to open channel with';
63
117
  }
64
118
 
65
- if (!!Number(input) && Number(input) > max) {
66
- return `The maximum possible to decrease is ${max}`;
119
+ if (input === getIdentity.public_key) {
120
+ return 'Expected public key of other node';
67
121
  }
68
122
 
69
123
  return true;
70
124
  },
71
125
  },
72
- ({amount}) => cbk(null, amount));
126
+ ({key}) => cbk(null, key));
73
127
  }],
74
128
 
75
- // Get network name
76
- getNetwork: ['validate', ({}, cbk) => getNetwork({lnd}, cbk)],
77
-
78
- // Ask if withdrawing to an external address
79
- askForExternal: ['askForAmount', ({askForAmount}, cbk) => {
80
- if (!Number(askForAmount)) {
129
+ // Create a decrease address to withdraw funds out to
130
+ createAddress: ['askForDecreaseType', ({askForDecreaseType}, cbk) => {
131
+ // Exit early when there is no need to create an internal address
132
+ if (askForDecreaseType !== spendToInternalAddressAction) {
81
133
  return cbk();
82
134
  }
83
135
 
136
+ return createChainAddress({lnd}, cbk);
137
+ }],
138
+
139
+ // Ask for the amount to decrease
140
+ askForAmount: ['askForNodeId', ({askForNodeId}, cbk) => {
84
141
  return ask({
85
- default: false,
86
- name: 'spend',
87
- message: `Spend ${askForAmount} to an external address?`,
88
- type: 'confirm',
142
+ default: !askForNodeId ? minSpendTokens : minChannelCapacity,
143
+ message: !askForNodeId ? askForSendSize(max) : askForChanSize(max),
144
+ name: 'amount',
145
+ validate: input => {
146
+ // A numeric input is required
147
+ if (!isNumber(input) || !isInteger(Number(input))) {
148
+ return false;
149
+ }
150
+
151
+ // Zero value is acceptable for a decrease when not opening channel
152
+ if (!askForNodeId && !Number(input)) {
153
+ return true;
154
+ }
155
+
156
+ // On-chain values must always be above dust
157
+ if (!!Number(input) && Number(input) < dust) {
158
+ return false;
159
+ }
160
+
161
+ // Channel opens must always be above the minimum channel size
162
+ if (!!askForNodeId && Number(input) < minChannelCapacity) {
163
+ return `The minimum channel capacity is ${minChannelCapacity}`;
164
+ }
165
+
166
+ // A decrease cannot spend more funds than are available
167
+ if (!!Number(input) && Number(input) > max) {
168
+ return `The maximum possible to decrease is ${max}`;
169
+ }
170
+
171
+ return true;
172
+ },
89
173
  },
90
- ({spend}) => cbk(null, spend));
174
+ ({amount}) => cbk(null, Number(amount)));
91
175
  }],
92
176
 
93
177
  // Ask for an external address
94
178
  askForAddress: [
95
179
  'askForAmount',
96
- 'askForExternal',
97
- ({askForAmount, askForExternal}, cbk) =>
180
+ 'askForDecreaseType',
181
+ 'getNetwork',
182
+ ({askForAmount, askForDecreaseType, getNetwork}, cbk) =>
98
183
  {
99
- // Exit early when the withdraw address is internal
100
- if (askForExternal !== true) {
184
+ // Exit early when the withdraw address is not external
185
+ if (askForDecreaseType !== spendToExternalAddressAction) {
101
186
  return cbk();
102
187
  }
103
188
 
104
189
  return ask({
105
190
  name: 'address',
106
- message: `Address to spend ${askForAmount} to?`,
191
+ message: `Address to spend ${tokensAsBigUnit(askForAmount)} to?`,
107
192
  type: 'input',
108
- validate: input => !!input,
193
+ validate: input => {
194
+ if (!input) {
195
+ return false;
196
+ }
197
+
198
+ // Make sure that the entered address can be derived to an output
199
+ try {
200
+ toOutputScript(input, networks[getNetwork.bitcoinjs]);
201
+ } catch (err) {
202
+ return 'Failed to parse address. Try a standard one?';
203
+ }
204
+
205
+ return true;
206
+ },
109
207
  },
110
208
  ({address}) => cbk(null, {address}));
111
209
  }],
@@ -113,31 +211,46 @@ module.exports = ({ask, lnd, max}, cbk) => {
113
211
  // Ask if this is the last output
114
212
  askForAddition: [
115
213
  'askForAddress',
116
- 'askForExternal',
117
- ({askForExternal}, cbk) =>
214
+ 'askForAmount',
215
+ 'askForDecreaseType',
216
+ ({askForAmount, askForDecreaseType}, cbk) =>
118
217
  {
119
- // Exit early when the spend was to an internal addess
120
- if (!askForExternal) {
218
+ // Exit early and only ask for addition when decrease is a "spend" type
219
+ if (askForDecreaseType === spendToInternalAddressAction) {
220
+ return cbk();
221
+ }
222
+
223
+ // Exit early when there are no more funds to spend
224
+ if (max - askForAmount < dust) {
121
225
  return cbk();
122
226
  }
123
227
 
124
228
  return ask({
125
229
  default: false,
126
230
  name: 'add',
127
- message: 'Add another spend to a different address?',
231
+ message: 'Spend additional funds from the channel capacity?',
128
232
  type: 'confirm',
129
233
  },
130
234
  ({add}) => cbk(null, add));
131
235
  }],
132
236
 
133
- // Create a decrease address to withdraw funds out to
134
- createAddress: ['askForExternal', ({askForExternal}, cbk) => {
135
- // Exit early when the withdraw address is external
136
- if (askForExternal !== false) {
237
+ // Propose a channel open to confirm the peer will accept the channel
238
+ checkChannelAcceptance: [
239
+ 'askForAmount',
240
+ 'askForNodeId',
241
+ ({askForAmount, askForNodeId}, cbk) =>
242
+ {
243
+ // Exit early if pubkey was not entered
244
+ if (!askForNodeId) {
137
245
  return cbk();
138
246
  }
139
247
 
140
- return createChainAddress({lnd}, cbk);
248
+ return proposeChannelOpen({
249
+ lnd,
250
+ capacity: askForAmount,
251
+ id: askForNodeId,
252
+ },
253
+ cbk);
141
254
  }],
142
255
 
143
256
  // Final decrease output details
@@ -145,38 +258,43 @@ module.exports = ({ask, lnd, max}, cbk) => {
145
258
  'askForAddition',
146
259
  'askForAddress',
147
260
  'askForAmount',
261
+ 'checkChannelAcceptance',
148
262
  'createAddress',
149
263
  'getNetwork',
150
264
  ({
151
265
  askForAddition,
152
266
  askForAddress,
153
267
  askForAmount,
268
+ askForNodeId,
269
+ checkChannelAcceptance,
154
270
  createAddress,
155
271
  getNetwork,
156
272
  },
157
273
  cbk) =>
158
274
  {
159
- const {address} = (createAddress || askForAddress || {});
160
-
161
- // Exit early when not decreasing to an address
162
- if (!address) {
163
- return cbk(null, {is_final: true, tokens: Number(askForAmount)});
275
+ // Make sure that a channel proposal didn't fail
276
+ if (!!checkChannelAcceptance && !checkChannelAcceptance.is_accepted) {
277
+ return cbk([503, 'RemoteNodeRejectedNewChannelProposal']);
164
278
  }
165
279
 
166
- // Make sure the address is valid
167
- try {
168
- toOutputScript(address, networks[getNetwork.bitcoinjs]);
169
- } catch (err) {
170
- return cbk([400, 'FailedToParseAddress', {err}]);
280
+ // Exit early when decreasing to a new channel
281
+ if (!!askForNodeId) {
282
+ return cbk(null, {
283
+ is_final: !askForAddition,
284
+ node: askForNodeId,
285
+ tokens: askForAmount,
286
+ });
171
287
  }
172
288
 
289
+ const {address} = (createAddress || askForAddress);
290
+
173
291
  const output = toOutputScript(address, networks[getNetwork.bitcoinjs]);
174
292
 
175
293
  return cbk(null, {
176
294
  address,
177
295
  is_final: !askForAddition,
178
296
  output: bufferAsHex(output),
179
- tokens: Number(askForAmount),
297
+ tokens: askForAmount,
180
298
  });
181
299
  }],
182
300
  },
@@ -1,3 +1,5 @@
1
+ const privateAsType = isPrivate => isPrivate ? 1 : 0;
2
+
1
3
  /** Map change requests to requests considering local channels
2
4
 
3
5
  {
@@ -13,6 +15,7 @@
13
15
  from: <From Node Public Key Id Hex String>
14
16
  id: <Change Request Id Hex String>
15
17
  [increase]: <Add Capacity Tokens Number>
18
+ [type]: <Intended Replacement Channel Channel Type Flags Number>
16
19
  }]
17
20
  }
18
21
 
@@ -26,6 +29,7 @@
26
29
  from: <From Node Public Key Id Hex String>
27
30
  id: <Change Request Id Hex String>
28
31
  [increase]: <Add Capacity Tokens Number>
32
+ [type]: <Change Channel Channel Type Flags Number>
29
33
  }]
30
34
  }
31
35
  */
@@ -61,6 +65,10 @@ module.exports = ({channels, requests}) => {
61
65
  .map(request => {
62
66
  const channel = channels.find(chan => chan.id === request.channel);
63
67
 
68
+ const currentType = privateAsType(channel.is_private);
69
+
70
+ const type = request.type !== undefined && request.type !== currentType;
71
+
64
72
  return {
65
73
  address: channel.cooperative_close_address,
66
74
  capacity: channel.capacity,
@@ -69,6 +77,7 @@ module.exports = ({channels, requests}) => {
69
77
  from: channel.partner_public_key,
70
78
  id: request.id,
71
79
  increase: request.increase,
80
+ type: type ? request.type : undefined,
72
81
  };
73
82
  });
74
83
 
@@ -10,6 +10,7 @@ const acceptCapacityChange = require('./accept_capacity_change');
10
10
  const getCapacityChangeRequests = require('./get_capacity_change_requests');
11
11
  const initiateCapacityChange = require('./initiate_capacity_change');
12
12
 
13
+ const describeType = type => !(type & 0) ? 'private' : 'public';
13
14
  const interval = 10 * 1000;
14
15
  const peerName = ({alias, id}) => `${alias} ${id.substring(0, 8)}`.trim();
15
16
  const times = 6 * 60 * 6;
@@ -89,17 +90,22 @@ module.exports = ({ask, delay, lnd, logger}, cbk) => {
89
90
 
90
91
  const change = !!request.increase ? 'Increase' : 'Decrease';
91
92
  const delta = request.decrease || request.increase;
93
+ const hasType = request.type !== undefined;
92
94
  const id = request.channel;
93
95
  const peer = peerName(res);
94
96
  const size = tokensAsBigUnit(request.capacity);
95
97
 
98
+
96
99
  const action = `${change} capacity ${size} channel ${id}`;
97
100
  const by = !!delta ? ` by ${tokensAsBigUnit(delta)}` : '';
101
+ const type = hasType ? describeType(request.type) : '';
102
+
103
+ const changeType = hasType ? ` and make channel ${type}` : '';
98
104
 
99
105
  return ask({
100
106
  type: 'confirm',
101
107
  name: 'accept',
102
- message: `${action} with ${peer}${by}?`,
108
+ message: `${action} with ${peer}${by}${changeType}?`,
103
109
  },
104
110
  ({accept}) => {
105
111
  if (!accept) {
@@ -1,10 +1,12 @@
1
1
  const {encodeBigSize} = require('bolt01');
2
2
  const {rawChanId} = require('bolt07');
3
3
 
4
+ const channelFlagsType = '5';
4
5
  const channelIdRecordType = '2';
5
6
  const decreaseRecordType = '3';
6
7
  const increaseRecordType = '4';
7
8
  const requestIdRecordType = '1';
9
+ const typeAsHex = type => Buffer.from([type]).toString('hex');
8
10
 
9
11
  /** Encode a request to change a channel capacity
10
12
 
@@ -13,6 +15,7 @@ const requestIdRecordType = '1';
13
15
  [decrease]: <Remove Channel Funds By Tokens Number>
14
16
  id: <Request Id Hex String>
15
17
  increase: <Add Channel Funds By Tokens Number>
18
+ type: <New Channel Type Number>
16
19
  }
17
20
 
18
21
  @returns
@@ -23,7 +26,7 @@ const requestIdRecordType = '1';
23
26
  }]
24
27
  }
25
28
  */
26
- module.exports = ({channel, decrease, id, increase}) => {
29
+ module.exports = ({channel, decrease, id, increase, type}) => {
27
30
  const records = [
28
31
  {
29
32
  type: requestIdRecordType,
@@ -33,6 +36,10 @@ module.exports = ({channel, decrease, id, increase}) => {
33
36
  type: channelIdRecordType,
34
37
  value: rawChanId({channel}).id,
35
38
  },
39
+ {
40
+ type: channelFlagsType,
41
+ value: typeAsHex(type),
42
+ },
36
43
  ];
37
44
 
38
45
  if (!!decrease) {
@@ -13,7 +13,7 @@ const dummySignature = Buffer.alloc(74);
13
13
  const dummyTokens = 0;
14
14
  const dummyVout = 0;
15
15
  const hexAsBuffer = hex => Buffer.from(hex, 'hex');
16
- const increaseBuffer = 150;
16
+ const increaseBuffer = 250;
17
17
  const {max} = Math;
18
18
  const weightAsVBytes = weight => weight / 4;
19
19
 
@@ -24,7 +24,7 @@ const weightAsVBytes = weight => weight / 4;
24
24
  commit_transaction_fee: <Commit Transaction Fee Tokens Number>
25
25
  commit_transaction_weight: <Commit Transaction Weight Units Number>
26
26
  decrease: [{
27
- output: <Output Script Hex String>
27
+ [output]: <Output Script Hex String>
28
28
  tokens: <Spend Value to Chain Address Tokens Number>
29
29
  }]
30
30
  [increase]: <Add Funds Tokens Number>
@@ -51,16 +51,12 @@ module.exports = args => {
51
51
 
52
52
  // Add the decreases as outputs
53
53
  args.decrease.forEach(({output, tokens}) => {
54
- return tx.addOutput(hexAsBuffer(output), tokens);
54
+ return tx.addOutput(hexAsBuffer(output || dummyP2wsh), tokens);
55
55
  });
56
56
 
57
57
  // Add an output to represent the new channel output
58
58
  tx.addOutput(dummyP2wsh, args.capacity);
59
59
 
60
- args.decrease.forEach(({output}) => {
61
- return tx.addOutput(hexAsBuffer(output), dummyTokens);
62
- });
63
-
64
60
  // Add an input to represent the old channel input
65
61
  tx.addInput(dummyHash, dummyVout);
66
62
 
@@ -28,6 +28,7 @@ const waitForRequestsTimeoutMs = 5000;
28
28
  from: <From Node Public Key Id Hex String>
29
29
  id: <Change Request Id Hex String>
30
30
  [increase]: <Add Capacity Tokens Number>
31
+ [type]: <Intended Replacement Channel Channel Type Flags Number>
31
32
  }]
32
33
  }
33
34
  */