paid-services 3.8.0 → 3.11.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,18 @@
1
1
  # Versions
2
2
 
3
+ ## Version 3.11.0
4
+
5
+ - `changeChannelCapacity`: Add `nodes` to allow moving channel to another node
6
+
7
+ ## Version 3.10.0
8
+
9
+ - `createAnchoredTrade`: Add method to create an anchored open trade
10
+ - `getAnchoredTrade`: Add method to get an anchored open trade
11
+
12
+ ## Version 3.9.1
13
+
14
+ - `decodeTrade`: Add method to decode a trade-secret
15
+
3
16
  ## Version 3.8.0
4
17
 
5
18
  - `encodeTrade`: Add method to encode a trade-secret
@@ -32,6 +32,7 @@ const openTxType = '1';
32
32
  [increase]: <Increase Tokens Number>
33
33
  lnd: <Authenticated LND API Object>
34
34
  logger: <Winston Logger Object>
35
+ to: <Expect Channel from Public Key Hex String>
35
36
  }
36
37
 
37
38
  @returns via cbk or Promise
@@ -43,7 +44,7 @@ const openTxType = '1';
43
44
  transaction_vout: <Replacement Channel Transaction Output Index Number>
44
45
  }
45
46
  */
46
- module.exports = ({channel, from, id, increase, lnd, logger}, cbk) => {
47
+ module.exports = ({channel, from, id, increase, lnd, logger, to}, cbk) => {
47
48
  return new Promise((resolve, reject) => {
48
49
  return asyncAuto({
49
50
  // Check arguments
@@ -68,6 +69,10 @@ module.exports = ({channel, from, id, increase, lnd, logger}, cbk) => {
68
69
  return cbk([400, 'ExpectedLoggerObjectToAcceptCapacityChange']);
69
70
  }
70
71
 
72
+ if (!to) {
73
+ return cbk([400, 'ExpectedToPublicKeyToAcceptCapacityChange']);
74
+ }
75
+
71
76
  return cbk();
72
77
  },
73
78
 
@@ -219,6 +224,7 @@ module.exports = ({channel, from, id, increase, lnd, logger}, cbk) => {
219
224
  channel,
220
225
  lnd,
221
226
  output,
227
+ to,
222
228
  id: parameters.id,
223
229
  unsigned: parseSignCapacityRequest(parameters).unsigned,
224
230
  vout: parameters.vout,
@@ -1,10 +1,12 @@
1
1
  const asyncAuto = require('async/auto');
2
2
  const asyncUntil = require('async/until');
3
+ const {connectPeer} = require('ln-sync');
3
4
  const {findKey} = require('ln-sync');
4
5
  const {getChainFeeRate} = require('ln-service');
5
6
  const {getChainTransactions} = require('ln-service');
6
7
  const {getChannel} = require('ln-service');
7
8
  const {getChannels} = require('ln-service');
9
+ const {getNodeAlias} = require('ln-sync');
8
10
  const {getPeers} = require('ln-service');
9
11
  const {returnResult} = require('asyncjs-util');
10
12
  const {sendMessageToPeer} = require('ln-service');
@@ -16,6 +18,7 @@ const feeForReplacement = require('./fee_for_replacement');
16
18
  const {ceil} = Math;
17
19
  const dust = 550;
18
20
  const dustBuffer = 750;
21
+ const {isArray} = Array;
19
22
  const isNumber = n => !isNaN(n);
20
23
  const largeChannelsBit = 19;
21
24
  const maxSats = 21e6 * 1e8;
@@ -40,6 +43,11 @@ const weightBuffer = 150;
40
43
  ask: <Ask Function>
41
44
  id: <Request Identifier Hex String>
42
45
  lnd: <Authenticated LND API Object>
46
+ nodes: [{
47
+ lnd: <Potential Move Node LND API Object>
48
+ node_name: <Potential Move Node Name String>
49
+ public_key: <Potential Move Node Public Key Hex String>
50
+ }]
43
51
  }
44
52
 
45
53
  @returns via cbk or Promise
@@ -59,6 +67,8 @@ const weightBuffer = 150;
59
67
  id: <Standard Format Channel Id String>
60
68
  increase: <Channel Capacity Increase Tokens Number>
61
69
  is_private: <Channel is Private Bool>
70
+ [open_from]: <Open Replacement Channel From Node with Public Key String>
71
+ open_lnd: <Open Replacement Channel with LND API Object>
62
72
  [open_transaction]: <Channel Open Transaction Hex String>
63
73
  partner_csv_delay: <Peer CSV Delay Number>
64
74
  partner_public_key: <Node to Ask For Capacity Change Public Key Hex String>
@@ -70,7 +80,7 @@ const weightBuffer = 150;
70
80
  transaction_id: <Channel Funding Transaction Id Hex String>
71
81
  }
72
82
  */
73
- module.exports = ({ask, id, lnd}, cbk) => {
83
+ module.exports = ({ask, id, lnd, nodes}, cbk) => {
74
84
  return new Promise((resolve, reject) => {
75
85
  return asyncAuto({
76
86
  // Check arguments
@@ -87,6 +97,10 @@ module.exports = ({ask, id, lnd}, cbk) => {
87
97
  return cbk([400, 'ExpectedLndToAskForChangeDetails']);
88
98
  }
89
99
 
100
+ if (!isArray(nodes)) {
101
+ return cbk([400, 'ExpectedArrayOfPotentialMoveNodesToAskForChange']);
102
+ }
103
+
90
104
  return cbk();
91
105
  },
92
106
 
@@ -112,7 +126,7 @@ module.exports = ({ask, id, lnd}, cbk) => {
112
126
  return getChainFeeRate({lnd, confirmation_target: slowTarget}, cbk);
113
127
  }],
114
128
 
115
- // Find the public key or alias entered
129
+ // Find the node with the public key or alias entered
116
130
  findKey: [
117
131
  'askForPeer',
118
132
  'getChannels',
@@ -126,6 +140,11 @@ module.exports = ({ask, id, lnd}, cbk) => {
126
140
  cbk);
127
141
  }],
128
142
 
143
+ // Get the alias of the peer
144
+ getAlias: ['findKey', ({findKey}, cbk) => {
145
+ return getNodeAlias({lnd, id: findKey.public_key}, cbk);
146
+ }],
147
+
129
148
  // Send a test message to the selected peer to confirm they are connected
130
149
  testPeer: ['findKey', 'getChannels', ({findKey, getChannels}, cbk) => {
131
150
  const hasPeer = !!getChannels.channels.find(channel => {
@@ -190,7 +209,7 @@ module.exports = ({ask, id, lnd}, cbk) => {
190
209
  return ask({
191
210
  choices,
192
211
  loop: false,
193
- message: 'Channel to change capacity?',
212
+ message: 'Channel to change?',
194
213
  name: 'id',
195
214
  type: 'list',
196
215
  },
@@ -294,20 +313,32 @@ module.exports = ({ask, id, lnd}, cbk) => {
294
313
  }],
295
314
 
296
315
  // Choose whether to add or remove coins
297
- askForDirection: ['channel', ({channel}, cbk) => {
316
+ askForDirection: ['channel', 'getAlias', ({channel, getAlias}, cbk) => {
317
+ const {alias} = getAlias;
318
+
319
+ const choices = [
320
+ {
321
+ disabled: !channel.max_increase_tokens,
322
+ name: `Increase capacity (currently ${channel.capacity})`,
323
+ value: 'increase',
324
+ },
325
+ {
326
+ disabled: !channel.max_decrease_tokens,
327
+ name: `Decrease capacity (limit ${channel.max_decrease_tokens})`,
328
+ value: 'decrease',
329
+ },
330
+ ];
331
+
332
+ if (!!nodes.filter(n => n.public_key !== getAlias.id).length) {
333
+ choices.push({
334
+ disabled: !channel.max_decrease_tokens,
335
+ name: `Move the channel with ${alias} to another of your nodes?`,
336
+ value: 'migrate',
337
+ });
338
+ }
339
+
298
340
  return ask({
299
- choices: [
300
- {
301
- disabled: !channel.max_increase_tokens,
302
- name: `Increase capacity (currently ${channel.capacity})`,
303
- value: 'increase',
304
- },
305
- {
306
- disabled: !channel.max_decrease_tokens,
307
- name: `Decrease capacity (limit ${channel.max_decrease_tokens})`,
308
- value: 'decrease',
309
- },
310
- ],
341
+ choices,
311
342
  message: 'How do you want to change the channel capacity?',
312
343
  name: 'direction',
313
344
  type: 'list',
@@ -315,6 +346,51 @@ module.exports = ({ask, id, lnd}, cbk) => {
315
346
  ({direction}) => cbk(null, direction));
316
347
  }],
317
348
 
349
+ // Ask for migration
350
+ askForMigration: [
351
+ 'askForDirection',
352
+ 'channel',
353
+ ({askForDirection, channel}, cbk) =>
354
+ {
355
+ // Exit early if not decrease or no saved nodes
356
+ if (askForDirection !== 'migrate') {
357
+ return cbk();
358
+ }
359
+
360
+ const peer = channel.partner_public_key;
361
+
362
+ const potentialNodes = nodes.filter(n => n.public_key !== peer);
363
+
364
+ return ask({
365
+ choices: potentialNodes.map((node, i) => ({
366
+ name: `${node.node_name} ${node.public_key}`,
367
+ value: i,
368
+ })),
369
+ message: 'Move channel to?',
370
+ name: 'migration',
371
+ type: 'list',
372
+ },
373
+ ({migration}) => cbk(null, potentialNodes[migration]));
374
+ }],
375
+
376
+ // Add peer from migrating node
377
+ connect: [
378
+ 'askForMigration',
379
+ 'findKey',
380
+ ({askForMigration, findKey}, cbk) =>
381
+ {
382
+ // Exit early if its there is no migration
383
+ if (!askForMigration) {
384
+ return cbk();
385
+ }
386
+
387
+ return connectPeer({
388
+ id: findKey.public_key,
389
+ lnd: askForMigration.lnd,
390
+ },
391
+ cbk);
392
+ }],
393
+
318
394
  // Ask for how much to decrease
319
395
  askForDecrease: [
320
396
  'askForDirection',
@@ -400,6 +476,7 @@ module.exports = ({ask, id, lnd}, cbk) => {
400
476
  askForPublicPrivate: [
401
477
  'askForDecrease',
402
478
  'askForIncrease',
479
+ 'askForMigration',
403
480
  'channel',
404
481
  ({channel}, cbk) =>
405
482
  {
@@ -452,12 +529,10 @@ module.exports = ({ask, id, lnd}, cbk) => {
452
529
  {
453
530
  const {fee} = estimateChainFee;
454
531
 
455
- const pay = `Pay estimated on-chain channel replacement fee: ${fee}`;
456
-
457
532
  return ask({
458
533
  type: 'confirm',
459
534
  name: 'proceed',
460
- message: `${pay} for capacity change?`,
535
+ message: `Pay estimated channel replacement chain-fee: ${fee}?`,
461
536
  },
462
537
  ({proceed}) => cbk(null, proceed));
463
538
  }],
@@ -466,16 +541,20 @@ module.exports = ({ask, id, lnd}, cbk) => {
466
541
  details: [
467
542
  'askForDecrease',
468
543
  'askForIncrease',
544
+ 'askForMigration',
469
545
  'askForPublicPrivate',
470
546
  'channel',
547
+ 'connect',
471
548
  'confirmFeeEstimate',
472
549
  'estimateChainFee',
473
550
  'getTx',
474
551
  ({
475
552
  askForDecrease,
476
553
  askForIncrease,
554
+ askForMigration,
477
555
  askForPublicPrivate,
478
556
  channel,
557
+ connect,
479
558
  confirmFeeEstimate,
480
559
  estimateChainFee,
481
560
  getTx,
@@ -509,6 +588,7 @@ module.exports = ({ask, id, lnd}, cbk) => {
509
588
  channel: channel.id,
510
589
  decrease: !!askForDecrease ? sumOfTokens(askForDecrease) : undefined,
511
590
  increase: askForIncrease,
591
+ to: !!askForMigration ? askForMigration.public_key : undefined,
512
592
  type: askForPublicPrivate.is_private ? privateType : publicType,
513
593
  });
514
594
 
@@ -524,6 +604,8 @@ module.exports = ({ask, id, lnd}, cbk) => {
524
604
  id: channel.id,
525
605
  increase: askForIncrease,
526
606
  is_private: askForPublicPrivate.is_private,
607
+ open_from: !!askForMigration ? askForMigration.public_key : null,
608
+ open_lnd: !!askForMigration ? askForMigration.lnd : lnd,
527
609
  open_transaction: channel.open_transaction,
528
610
  partner_csv_delay: channel.partner_csv_delay,
529
611
  partner_public_key: channel.partner_public_key,
@@ -0,0 +1,109 @@
1
+ const asyncAuto = require('async/auto');
2
+ const {getNodeAlias} = require('ln-sync');
3
+ const {returnResult} = require('asyncjs-util');
4
+
5
+ const describeCapacityChange = require('./describe_capacity_change');
6
+
7
+ /** Ask to select a change
8
+
9
+ {
10
+ ask: <Inquirer Ask Function>
11
+ [address]: <Cooperative Close Address String>
12
+ capacity: <Channel Capacity Tokens Number>
13
+ channel: <Change Channel Id String>
14
+ [decrease]: <Capacity Change Decrease Tokens Number>
15
+ from_id: <Peer Public Key Hex String>
16
+ [increase]: <Capacity Change Increase Tokens Number>
17
+ lnd: <Authenticated LND API Object>
18
+ [to_id]: <Node Public Key Hex String>
19
+ [type]: <Channel Type String>
20
+ }
21
+
22
+ @returns via cbk or Promise
23
+ {
24
+ is_selected: <Request to Change Channel is Selected Bool>
25
+ }
26
+ */
27
+ module.exports = (args, cbk) => {
28
+ return new Promise((resolve, reject) => {
29
+ return asyncAuto({
30
+ // Check arguments
31
+ validate: cbk => {
32
+ if (!args.ask) {
33
+ return cbk([400, 'ExpectedAskFunctionToAskToSelectChange']);
34
+ }
35
+
36
+ if (!args.capacity) {
37
+ return cbk([400, 'ExpectedChannelCapacityToAskToSelectChange']);
38
+ }
39
+
40
+ if (!args.channel) {
41
+ return cbk([400, 'ExpectedChannelIdToAskToSelectAChangeFor']);
42
+ }
43
+
44
+ if (!args.from_id) {
45
+ return cbk([400, 'ExpectedChannelPartnerPublicKeyToSelectChange']);
46
+ }
47
+
48
+ if (!args.lnd) {
49
+ return cbk([400, 'ExpectedLndApiToAskToSelectChange']);
50
+ }
51
+
52
+ return cbk();
53
+ },
54
+
55
+ // Get the peer alias
56
+ getPeerAlias: ['validate', ({}, cbk) => {
57
+ return getNodeAlias({id: args.from_id, lnd: args.lnd}, cbk);
58
+ }],
59
+
60
+ // Get the alias of the node to move to
61
+ getNodeAlias: ['validate', ({}, cbk) => {
62
+ // Exit early when there is no new node to move to
63
+ if (!args.to_id) {
64
+ return cbk(null, {});
65
+ }
66
+
67
+ return getNodeAlias({id: args.to_id, lnd: args.lnd}, cbk);
68
+ }],
69
+
70
+ // Confirm acceptance of the change
71
+ confirm: [
72
+ 'getNodeAlias',
73
+ 'getPeerAlias',
74
+ ({getNodeAlias, getPeerAlias}, cbk) =>
75
+ {
76
+ const message = describeCapacityChange({
77
+ capacity: args.capacity,
78
+ channel: args.channel,
79
+ decrease: args.decrease,
80
+ from_alias: getPeerAlias.alias,
81
+ from_id: args.from_id,
82
+ increase: args.increase,
83
+ to_alias: getNodeAlias.alias,
84
+ to_id: args.to_id,
85
+ type: args.type,
86
+ });
87
+
88
+ return args.ask({
89
+ message,
90
+ name: 'accept',
91
+ type: 'confirm',
92
+ },
93
+ ({accept}) => {
94
+ if (!accept) {
95
+ return cbk(null, {is_selected: false});
96
+ }
97
+
98
+ // Fail changing when cooperative_close_address is set
99
+ if (!!args.address && !args.increase) {
100
+ return cbk([400, 'ChannelHasLockedCoopCloseAddressSet']);
101
+ }
102
+
103
+ return cbk(null, {is_selected: true});
104
+ });
105
+ }],
106
+ },
107
+ returnResult({reject, resolve, of: 'confirm'}, cbk));
108
+ });
109
+ };
@@ -29,6 +29,7 @@ const privateAsType = isPrivate => isPrivate ? 1 : 0;
29
29
  from: <From Node Public Key Id Hex String>
30
30
  id: <Change Request Id Hex String>
31
31
  [increase]: <Add Capacity Tokens Number>
32
+ [to]: <Switch Channel to Node with Identity Public Key Hex String>
32
33
  [type]: <Change Channel Channel Type Flags Number>
33
34
  }]
34
35
  }
@@ -77,6 +78,7 @@ module.exports = ({channels, requests}) => {
77
78
  from: channel.partner_public_key,
78
79
  id: request.id,
79
80
  increase: request.increase,
81
+ to: request.to,
80
82
  type: type ? request.type : undefined,
81
83
  };
82
84
  });
@@ -2,20 +2,17 @@ const asyncAuto = require('async/auto');
2
2
  const asyncDetectSeries = require('async/detectSeries');
3
3
  const asyncRetry = require('async/retry');
4
4
  const {getIdentity} = require('ln-service');
5
- const {getNodeAlias} = require('ln-sync');
6
5
  const {returnResult} = require('asyncjs-util');
7
6
  const {updateChannelFee} = require('ln-sync');
8
7
 
9
8
  const acceptCapacityChange = require('./accept_capacity_change');
9
+ const askToSelectChange = require('./ask_to_select_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';
14
- const interval = 10 * 1000;
15
- const peerName = ({alias, id}) => `${alias} ${id.substring(0, 8)}`.trim();
13
+ const interval = 1000 * 10;
14
+ const {isArray} = Array;
16
15
  const times = 6 * 60 * 6;
17
- const tokensAsBigUnit = tokens => (tokens / 1e8).toFixed(8);
18
- const waitForCloseInterval = 1000 * 3;
19
16
 
20
17
  /** Change a channel's capacity
21
18
 
@@ -24,9 +21,14 @@ const waitForCloseInterval = 1000 * 3;
24
21
  [delay]: <Wait Time For Incoming Capacity Requests Milliseconds Number>
25
22
  lnd: <Authenticated LND API Object>
26
23
  logger: <Winston Logger Object>
24
+ [nodes]: [{
25
+ lnd: <Authenticated LND API Object>
26
+ named: <Node Named String.
27
+ public_key: <Node Identity Public Key Hex String>
28
+ }]
27
29
  }
28
30
  */
29
- module.exports = ({ask, delay, lnd, logger}, cbk) => {
31
+ module.exports = ({ask, delay, lnd, logger, nodes}, cbk) => {
30
32
  return new Promise((resolve, reject) => {
31
33
  return asyncAuto({
32
34
  // Check arguments
@@ -43,6 +45,10 @@ module.exports = ({ask, delay, lnd, logger}, cbk) => {
43
45
  return cbk([400, 'ExpectedLoggerObjectToChangeCapacity']);
44
46
  }
45
47
 
48
+ if (!!nodes && !isArray(nodes)) {
49
+ return cbk([400, 'ExpectedArrayOfControlledNodesToChangeCapacity']);
50
+ }
51
+
46
52
  return cbk();
47
53
  },
48
54
 
@@ -83,42 +89,24 @@ module.exports = ({ask, delay, lnd, logger}, cbk) => {
83
89
  ({waitForProposal}, cbk) =>
84
90
  {
85
91
  return asyncDetectSeries(waitForProposal.requests, (request, cbk) => {
86
- return getNodeAlias({lnd, id: request.from}, (err, res) => {
92
+ return askToSelectChange({
93
+ ask,
94
+ lnd,
95
+ address: request.address,
96
+ capacity: request.capacity,
97
+ channel: request.channel,
98
+ decrease: request.decrease,
99
+ from_id: request.from,
100
+ increase: request.increase,
101
+ to_id: request.to,
102
+ type: request.type,
103
+ },
104
+ (err, res) => {
87
105
  if (!!err) {
88
106
  return cbk(err);
89
107
  }
90
108
 
91
- const change = !!request.increase ? 'Increase' : 'Decrease';
92
- const delta = request.decrease || request.increase;
93
- const hasType = request.type !== undefined;
94
- const id = request.channel;
95
- const peer = peerName(res);
96
- const size = tokensAsBigUnit(request.capacity);
97
-
98
-
99
- const action = `${change} capacity ${size} channel ${id}`;
100
- const by = !!delta ? ` by ${tokensAsBigUnit(delta)}` : '';
101
- const type = hasType ? describeType(request.type) : '';
102
-
103
- const changeType = hasType ? ` and make channel ${type}` : '';
104
-
105
- return ask({
106
- type: 'confirm',
107
- name: 'accept',
108
- message: `${action} with ${peer}${by}${changeType}?`,
109
- },
110
- ({accept}) => {
111
- if (!accept) {
112
- return cbk(null, false);
113
- }
114
-
115
- // Fail changing when cooperative_close_address is set
116
- if (!!request.address && !!request.increase) {
117
- return cbk([400, 'ChannelHasLockedCoopCloseAddressSet']);
118
- }
119
-
120
- return cbk(null, true);
121
- });
109
+ return cbk(null, res.is_selected);
122
110
  });
123
111
  },
124
112
  cbk);
@@ -138,17 +126,30 @@ module.exports = ({ask, delay, lnd, logger}, cbk) => {
138
126
  from: askToSelectChange.from,
139
127
  id: askToSelectChange.id,
140
128
  increase: askToSelectChange.increase,
129
+ to: askToSelectChange.to || askToSelectChange.from,
141
130
  },
142
131
  cbk);
143
132
  }],
144
133
 
145
134
  // Initiate a capacity change
146
- initiateChange: ['askToSelectChange', ({askToSelectChange}, cbk) => {
135
+ initiateChange: [
136
+ 'askToSelectChange',
137
+ 'getIdentity',
138
+ ({askToSelectChange, getIdentity}, cbk) =>
139
+ {
147
140
  if (!!askToSelectChange) {
148
141
  return cbk();
149
142
  }
150
143
 
151
- return initiateCapacityChange({ask, lnd, logger}, cbk);
144
+ return initiateCapacityChange({
145
+ ask,
146
+ lnd,
147
+ logger,
148
+ nodes: (nodes || []).filter(node => {
149
+ return node.public_key !== getIdentity.public_key;
150
+ }),
151
+ },
152
+ cbk);
152
153
  }],
153
154
 
154
155
  // Reset the channel routing policies
@@ -164,11 +165,11 @@ module.exports = ({ask, delay, lnd, logger}, cbk) => {
164
165
 
165
166
  return asyncRetry({interval, times}, cbk => {
166
167
  return updateChannelFee({
167
- lnd,
168
168
  base_fee_mtokens: policy.base_fee_mtokens,
169
169
  cltv_delta: policy.cltv_delta,
170
170
  fee_rate: policy.fee_rate,
171
- from: getIdentity.public_key,
171
+ from: policy.open_from || getIdentity.public_key,
172
+ lnd: policy.open_lnd || lnd,
172
173
  transaction_id: policy.transaction_id,
173
174
  transaction_vout: policy.transaction_vout,
174
175
  },
@@ -0,0 +1,38 @@
1
+ const describeType = type => !(type & 1) ? 'private' : 'public';
2
+ const peerName = ({alias, id}) => `${alias} ${id.substring(0, 8)}`.trim();
3
+ const tokensAsBigUnit = tokens => (tokens / 1e8).toFixed(8);
4
+
5
+ /** Describe a capacity change
6
+
7
+ {
8
+ capacity: <Channel Capacity Tokens Number>
9
+ channel: <Change Channel Id String>
10
+ [decrease]: <Capacity Change Decrease Tokens Number>
11
+ from_alias: <Peer Alias String>
12
+ from_id: <Peer Public Key Hex String>
13
+ [increase]: <Capacity Change Increase Tokens Number>
14
+ [to_alias]: <Node Alias String>
15
+ [to_id]: <Node Public Key Hex String>
16
+ [type]: <Channel Type String>
17
+ }
18
+
19
+ @returns
20
+ <Capacity Change Description String>
21
+ */
22
+ module.exports = args => {
23
+ const change = !!args.increase ? 'Increase' : 'Decrease';
24
+ const delta = args.decrease || args.increase;
25
+ const hasType = args.type !== undefined;
26
+ const newPeer = peerName({alias: args.to_alias, id: args.to_id || ''});
27
+ const peer = peerName({alias: args.from_alias, id: args.from_id});
28
+ const size = tokensAsBigUnit(args.capacity);
29
+
30
+ const action = `${change} capacity ${size} channel ${args.channel}`;
31
+ const by = !!delta ? ` by ${tokensAsBigUnit(delta)}` : '';
32
+ const move = !!args.to_id ? ` and move channel to ${newPeer}` : '';
33
+ const type = hasType ? describeType(args.type) : '';
34
+
35
+ const changeType = hasType ? ` and make channel ${type}` : '';
36
+
37
+ return `${action} with ${peer}${by}${move}${changeType}?`;
38
+ };
@@ -1,12 +1,16 @@
1
1
  const {encodeBigSize} = require('bolt01');
2
+ const {encodeTlvRecord} = require('bolt01');
2
3
  const {rawChanId} = require('bolt07');
3
4
 
4
5
  const channelFlagsType = '5';
5
6
  const channelIdRecordType = '2';
7
+ const currentVersion = '1';
6
8
  const decreaseRecordType = '3';
7
9
  const increaseRecordType = '4';
10
+ const migrateRecordType = '6';
8
11
  const requestIdRecordType = '1';
9
12
  const typeAsHex = type => Buffer.from([type]).toString('hex');
13
+ const versionRecordType = '0';
10
14
 
11
15
  /** Encode a request to change a channel capacity
12
16
 
@@ -15,6 +19,7 @@ const typeAsHex = type => Buffer.from([type]).toString('hex');
15
19
  [decrease]: <Remove Channel Funds By Tokens Number>
16
20
  id: <Request Id Hex String>
17
21
  increase: <Add Channel Funds By Tokens Number>
22
+ [to]: <Move Channel to Different Node with Public Key Hex String>
18
23
  type: <New Channel Type Number>
19
24
  }
20
25
 
@@ -26,8 +31,12 @@ const typeAsHex = type => Buffer.from([type]).toString('hex');
26
31
  }]
27
32
  }
28
33
  */
29
- module.exports = ({channel, decrease, id, increase, type}) => {
34
+ module.exports = ({channel, decrease, id, increase, to, type}) => {
30
35
  const records = [
36
+ {
37
+ type: versionRecordType,
38
+ value: encodeBigSize({number: currentVersion}).encoded,
39
+ },
31
40
  {
32
41
  type: requestIdRecordType,
33
42
  value: id,
@@ -42,21 +51,26 @@ module.exports = ({channel, decrease, id, increase, type}) => {
42
51
  },
43
52
  ];
44
53
 
54
+ // Add a record reflecting the decrease in the capacity
45
55
  if (!!decrease) {
46
- // Add a record reflecting the decrease in the capacity
47
56
  records.push({
48
57
  type: decreaseRecordType,
49
58
  value: encodeBigSize({number: decrease.toString()}).encoded,
50
59
  });
51
60
  }
52
61
 
62
+ // Add a record reflecting the increase in the capacity
53
63
  if (!!increase) {
54
- // Add a record reflecting the increase in the capacity
55
64
  records.push({
56
65
  type: increaseRecordType,
57
66
  value: encodeBigSize({number: increase.toString()}).encoded,
58
67
  });
59
68
  }
60
69
 
70
+ // Add a record reflecting the migration of channel to a different peer
71
+ if (!!to) {
72
+ records.push({type: migrateRecordType, value: to});
73
+ }
74
+
61
75
  return {records};
62
76
  };
@@ -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
+ [to]: <Switch Channel to Node with Identity Public Key Hex String>
31
32
  [type]: <Intended Replacement Channel Channel Type Flags Number>
32
33
  }]
33
34
  }