paid-services 6.1.6 → 6.2.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,6 +1,10 @@
1
1
  # Versions
2
2
 
3
- ## Version 6.1.6
3
+ ## Version 6.2.0
4
+
5
+ - `createGroupFanout`, `joinGroupFanout`: Add methods to make and join fanouts
6
+
7
+ ## Version 6.1.7
4
8
 
5
9
  - `manageSwap`: Add support for Loop Out to external address
6
10
 
@@ -208,7 +208,7 @@ module.exports = ({capacity, count, ecp, identity, lnd, members, rate}) => {
208
208
  return res.success({records});
209
209
  });
210
210
 
211
- // Listen for and respond to pending open registrations
211
+ // Listen for and respond to fanout proposal registrations
212
212
  service.request({type: serviceTypeRegisterPendingFanout}, (req, res) => {
213
213
  if (!isArray(req.records)) {
214
214
  return res.failure([400, 'ExpectedArrayOfRecordsForPendingFanout']);
@@ -121,12 +121,14 @@ module.exports = (args, cbk) => {
121
121
  return getChainBalance({lnd: args.lnd}, cbk);
122
122
  }],
123
123
 
124
+ // Get identity public key to include self in the group
125
+ getIdentity: ['validate', ({}, cbk) => {
126
+ return getIdentity({lnd: args.lnd}, cbk);
127
+ }],
128
+
124
129
  // Get UTXOs to use for input selection and final fee rate calculation
125
130
  getUtxos: ['validate', ({}, cbk) => getUtxos({lnd: args.lnd}, cbk)],
126
131
 
127
- // Get identity public key
128
- getIdentity: ['validate', ({}, cbk) => getIdentity({lnd: args.lnd}, cbk)],
129
-
130
132
  // Get methods to confim partial signing is supported
131
133
  getMethods: ['validate', ({}, cbk) => getMethods({lnd: args.lnd}, cbk)],
132
134
 
@@ -150,7 +152,7 @@ module.exports = (args, cbk) => {
150
152
  return cbk();
151
153
  }],
152
154
 
153
- // Select inputs to spend
155
+ // Interactively select inputs to spend
154
156
  utxos: ['getUtxos', ({getUtxos}, cbk) => {
155
157
  // Exit early when UTXOs are all specified already
156
158
  if (!!args.inputs.length) {
@@ -162,7 +164,7 @@ module.exports = (args, cbk) => {
162
164
  return cbk(null, []);
163
165
  }
164
166
 
165
- // Only selecting confirmed utxos is supported
167
+ // Only selecting confirmed P2TR or P2WPKH UTXOs is supported
166
168
  const utxos = getUtxos.utxos
167
169
  .filter(n => !!n.confirmation_count)
168
170
  .filter(n => allowedAddressFormats.includes(n.address_format));
@@ -178,6 +180,7 @@ module.exports = (args, cbk) => {
178
180
  value: asOutpoint(utxo),
179
181
  })),
180
182
  loop: false,
183
+ message: 'Select UTXOs to spend',
181
184
  name: 'inputs',
182
185
  type: 'checkbox',
183
186
  validate: input => {
@@ -128,6 +128,7 @@ module.exports = ({capacity, inputs, lnd, outputs, rate}, cbk) => {
128
128
  fund: ['getAddresses', 'spend', ({getAddresses, spend}, cbk) => {
129
129
  return fundPsbt({
130
130
  lnd,
131
+ change_format: format,
131
132
  inputs: spend.map(input => ({
132
133
  transaction_id: input.transaction_id,
133
134
  transaction_vout: input.transaction_vout,
@@ -89,8 +89,23 @@ module.exports = (args, cbk) => {
89
89
  return cbk();
90
90
  }],
91
91
 
92
+ // Decode the group invite code and get group details
93
+ getJoinDetails: ['confirmSigner', ({}, cbk) => {
94
+ return confirmFanoutJoin({
95
+ code: args.code,
96
+ count: args.output_count,
97
+ lnd: args.lnd,
98
+ logger: args.logger,
99
+ },
100
+ cbk);
101
+ }],
102
+
92
103
  // Select inputs to spend
93
- utxos: ['getUtxos', ({getUtxos}, cbk) => {
104
+ utxos: [
105
+ 'getJoinDetails',
106
+ 'getUtxos',
107
+ ({getJoinDetails, getUtxos}, cbk) =>
108
+ {
94
109
  // Exit early when UTXOs are all specified already
95
110
  if (!!args.inputs.length) {
96
111
  return cbk(null, args.inputs);
@@ -117,6 +132,7 @@ module.exports = (args, cbk) => {
117
132
  value: asOutpoint(utxo),
118
133
  })),
119
134
  loop: false,
135
+ message: 'Select UTXOs to spend',
120
136
  name: 'inputs',
121
137
  type: 'checkbox',
122
138
  validate: input => {
@@ -129,7 +145,7 @@ module.exports = (args, cbk) => {
129
145
  return utxos.find(n => asOutpoint(n) === utxo.value).tokens;
130
146
  }));
131
147
 
132
- const capacity = args.capacity * args.output_count;
148
+ const capacity = getJoinDetails.capacity * args.output_count;
133
149
 
134
150
  const missingTok = asBigUnit(capacity - tokens);
135
151
 
@@ -143,17 +159,6 @@ module.exports = (args, cbk) => {
143
159
  ({inputs}) => cbk(null, inputs));
144
160
  }],
145
161
 
146
- // Decode the group invite code and get group details
147
- getJoinDetails: ['confirmSigner', 'utxos', ({}, cbk) => {
148
- return confirmFanoutJoin({
149
- code: args.code,
150
- count: args.output_count,
151
- lnd: args.lnd,
152
- logger: args.logger,
153
- },
154
- cbk);
155
- }],
156
-
157
162
  // Join the fanout group
158
163
  join: [
159
164
  'confirmSigner',
package/groups/index.js CHANGED
@@ -1,5 +1,13 @@
1
1
  const createGroupChannel = require('./create_group_channel');
2
+ const {createGroupFanout} = require('./fanout');
2
3
  const joinGroupChannel = require('./join_group_channel');
4
+ const {joinGroupFanout} = require('./fanout');
3
5
  const manageGroupJoin = require('./manage_group_join');
4
6
 
5
- module.exports = {createGroupChannel, joinGroupChannel, manageGroupJoin};
7
+ module.exports = {
8
+ createGroupChannel,
9
+ createGroupFanout,
10
+ joinGroupChannel,
11
+ joinGroupFanout,
12
+ manageGroupJoin,
13
+ };
package/package.json CHANGED
@@ -15,9 +15,9 @@
15
15
  "bolt01": "2.0.0",
16
16
  "bolt07": "1.9.4",
17
17
  "ecpair": "2.1.0",
18
- "goldengate": "14.0.8",
18
+ "goldengate": "14.0.9",
19
19
  "invoices": "3.0.0",
20
- "ln-service": "57.20.2",
20
+ "ln-service": "57.22.0",
21
21
  "ln-sync": "6.4.0",
22
22
  "psbt": "3.0.0",
23
23
  "p2tr": "2.0.0",
@@ -48,5 +48,5 @@
48
48
  "integration-tests": "tap -j 2 --branches=1 --functions=1 --lines=1 --statements=1 -t 2700 test/integration/*.js",
49
49
  "test": "tap --branches=1 --functions=1 --lines=1 --statements=1 -t 60 test/actions/*.js test/balanced/*.js test/capacity/*.js test/client/*.js test/config/*.js test/p2p/*.js test/records/*.js test/respond/*.js test/server/*.js test/swaps/*.js test/services/*.js test/trades/*.js"
50
50
  },
51
- "version": "6.1.6"
51
+ "version": "6.2.0"
52
52
  }
@@ -1,8 +1,10 @@
1
1
  const {once} = require('events');
2
2
 
3
3
  const {addPeer} = require('ln-service');
4
+ const asyncEach = require('async/each');
4
5
  const asyncMap = require('async/map');
5
6
  const asyncRetry = require('async/retry');
7
+ const {componentsOfTransaction} = require('@alexbosworth/blockchain');
6
8
  const {createChainAddress} = require('ln-service');
7
9
  const {getChainTransactions} = require('ln-service');
8
10
  const {getNetwork} = require('ln-sync');
@@ -21,11 +23,14 @@ const asOutpoint = utxo => `${utxo.transaction_id}:${utxo.transaction_vout}`;
21
23
  const capacity = 1e5;
22
24
  const count = 101;
23
25
  const feeRate = 1;
26
+ const format = 'p2tr';
24
27
  const interval = 10;
25
28
  const outputCount = 2;
29
+ const outputCountControl = 4;
26
30
  const size = 3;
27
31
  const tokens = 1e6;
28
32
  const times = 2000;
33
+ const uniq = arr => Array.from(new Set(arr));
29
34
 
30
35
  // Make a joint transaction fanout group
31
36
  test(`Setup joint fanout group`, async ({end, equal, strictSame}) => {
@@ -52,10 +57,7 @@ test(`Setup joint fanout group`, async ({end, equal, strictSame}) => {
52
57
  await sendToChainAddress({lnd, tokens, address: targetAddress.address});
53
58
 
54
59
  // Create a remote chain address
55
- const remoteAddress = await createChainAddress({
56
- format: 'p2tr',
57
- lnd: remote.lnd,
58
- });
60
+ const remoteAddress = await createChainAddress({format, lnd: remote.lnd});
59
61
 
60
62
  // Send coins to remote
61
63
  await sendToChainAddress({lnd, tokens, address: remoteAddress.address});
@@ -102,15 +104,17 @@ test(`Setup joint fanout group`, async ({end, equal, strictSame}) => {
102
104
  // Get utxos of the coordinator
103
105
  const controlUtxos = await getUtxos({lnd: control.lnd});
104
106
 
107
+ const [utxoForControl] = controlUtxos.utxos.map(asOutpoint).reverse();
108
+
105
109
  // Start the coordination
106
110
  const assemble = assembleGroup({
107
111
  capacity,
108
112
  ecp,
109
113
  count: nodes.length,
110
114
  identity: control.id,
111
- inputs: controlUtxos.utxos.map(n => asOutpoint(n)),
115
+ inputs: [utxoForControl],
112
116
  lnd: control.lnd,
113
- outputs: outputCount,
117
+ outputs: outputCountControl,
114
118
  rate: feeRate,
115
119
  });
116
120
 
@@ -148,22 +152,60 @@ test(`Setup joint fanout group`, async ({end, equal, strictSame}) => {
148
152
  // Transaction ids of the open should be returned
149
153
  const ids = joins.map(n => n.id);
150
154
 
155
+ strictSame(uniq(ids).length, 1, 'Only one transaction id');
156
+
151
157
  // Finished, wait for confirmations on fanout utxos
152
158
  await generate({count});
153
159
 
160
+ const expected = [
161
+ {
162
+ lnd: control.lnd,
163
+ count: outputCountControl,
164
+ },
165
+ {
166
+ lnd: target.lnd,
167
+ count: outputCount,
168
+ },
169
+ {
170
+ lnd: remote.lnd,
171
+ count: outputCount,
172
+ },
173
+ ];
174
+
154
175
  // Check if the expected utxos are confirmed
155
176
  await asyncRetry({interval, times}, async () => {
156
- await Promise.all(nodes.map(async ({lnd}) => {
177
+ await asyncEach(expected, async ({count, lnd}) => {
178
+ const [txId] = ids;
157
179
  const {utxos} = await getUtxos({lnd, min_confirmations: 1});
158
180
 
159
- const utxosCount = utxos.filter(n => n.tokens === capacity).length;
181
+ const utxosCount = utxos
182
+ .filter(n => n.transaction_id === txId)
183
+ .filter(n => n.tokens === capacity)
184
+ .length;
160
185
 
161
- if (outputCount !== utxosCount) {
162
- throw new Error('ExpectedCorrectFanoutUtxoCount');
163
- }
164
- }));
186
+ strictSame(utxosCount, count, 'Got expected UTXOs count');
187
+ });
165
188
  });
166
189
 
190
+ const components = componentsOfTransaction({
191
+ transaction: events.broadcast.transaction,
192
+ });
193
+
194
+ const controlExtra = components.outputs.find(n => n.tokens === 4999599712);
195
+ const fundedOuts = components.outputs.filter(n => n.tokens === capacity);
196
+
197
+ const changeOutput1 = components.outputs
198
+ .find(n => n.tokens === 799798 || n.tokens === 799799);
199
+
200
+ const changeOutput2 = components.outputs
201
+ .find(n => n.tokens === 799809 || n.tokens === 799810);
202
+
203
+ strictSame(components.inputs.length, 3, 'Got expected inputs count');
204
+ strictSame(components.outputs.length, 11, 'Got expected outputs count');
205
+ strictSame(fundedOuts.length, 8, 'Got expected funded outputs count');
206
+ strictSame(!!changeOutput1, true, 'Got change output 1');
207
+ strictSame(!!changeOutput2, true, 'Got change output 2');
208
+ strictSame(!!controlExtra, true, 'Got control change output');
167
209
  strictSame(ids, [events.broadcast.id, events.broadcast.id], 'Got tx ids');
168
210
  strictSame(events.broadcast.id.length, 64, 'Got broadcast tx id');
169
211
  strictSame(!!events.broadcast.transaction, true, 'Got broadcast tx');