paid-services 3.20.3 → 4.0.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 +14 -0
- package/groups/create_group_channel.js +184 -0
- package/groups/get_join_details.js +135 -0
- package/groups/index.js +3 -1
- package/groups/join_group_channel.js +119 -0
- package/index.js +4 -0
- package/package.json +11 -11
- package/swaps/complete_off_to_on_swap.js +443 -59
- package/swaps/complete_on_to_off_swap.js +12 -3
- package/swaps/decode_loop_response.js +153 -0
- package/swaps/decode_off_to_on_recovery.js +2 -1
- package/swaps/decode_off_to_on_response.js +6 -2
- package/swaps/decode_off_to_on_restart.js +77 -0
- package/swaps/decode_swap_options.js +49 -0
- package/swaps/encode_loop_response.js +87 -0
- package/swaps/encode_off_to_on_restart.js +108 -0
- package/swaps/encode_swap_options.js +30 -0
- package/swaps/manage_swap.js +55 -2
- package/swaps/request_loop_out.js +262 -0
- package/swaps/request_swap_out.js +183 -60
- package/swaps/swap_field_types.json +25 -0
- package/test/integration/test_group_noninteractive.js +133 -0
- package/test/integration/test_swap_with_refund_path.js +14 -1
- package/test/swaps/test_decode_loop_response.js +45 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Versions
|
|
2
2
|
|
|
3
|
+
## Version 4.0.0
|
|
4
|
+
|
|
5
|
+
- `createGroupChannel`: Add method to coordinate a channel group
|
|
6
|
+
- `joinGroupChannel`: Add method to join a channel group
|
|
7
|
+
|
|
8
|
+
### Breaking Changes
|
|
9
|
+
|
|
10
|
+
- Node.js version 14 or higher is now required
|
|
11
|
+
|
|
12
|
+
## Version 3.21.0
|
|
13
|
+
|
|
14
|
+
- `manageSwap`: Add recovery for swap requests
|
|
15
|
+
- `manageSwap`: Add support for experimental Lightning Loop MuSig2 Taproot swap
|
|
16
|
+
|
|
3
17
|
## Version 3.20.3
|
|
4
18
|
|
|
5
19
|
- `manageGroupJoin`: Allow coordinating pair when funds are below the capacity
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
const asyncAuto = require('async/auto');
|
|
2
|
+
const asyncMap = require('async/map');
|
|
3
|
+
const {getChainBalance} = require('ln-service');
|
|
4
|
+
const {getIdentity} = require('ln-service');
|
|
5
|
+
const {getMethods} = require('ln-service');
|
|
6
|
+
const {getNodeAlias} = require('ln-sync');
|
|
7
|
+
const {returnResult} = require('asyncjs-util');
|
|
8
|
+
const tinysecp = require('tiny-secp256k1');
|
|
9
|
+
|
|
10
|
+
const assembleChannelGroup = require('./assemble_channel_group');
|
|
11
|
+
|
|
12
|
+
const halfOf = n => n / 2;
|
|
13
|
+
const isOdd = n => !!(n % 2);
|
|
14
|
+
const join = arr => arr.join(', ');
|
|
15
|
+
const maxGroupSize = 420;
|
|
16
|
+
const minChannelSize = 2e4;
|
|
17
|
+
const minGroupSize = 2;
|
|
18
|
+
const niceName = ({alias, id}) => `${alias} ${id}`.trim();
|
|
19
|
+
const signPsbtEndpoint = '/walletrpc.WalletKit/SignPsbt';
|
|
20
|
+
|
|
21
|
+
/** Join a channel group
|
|
22
|
+
|
|
23
|
+
{
|
|
24
|
+
capacity: <Channel Capacity Tokens Number>
|
|
25
|
+
count: <Group Member Count Number>
|
|
26
|
+
lnd: <Authenticated LND API Object>
|
|
27
|
+
logger: <Winston Logger Object>
|
|
28
|
+
rate: <Opening Chain Fee Tokens Per VByte Rate Number>
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
@returns via cbk or Promise
|
|
32
|
+
{
|
|
33
|
+
transaction_id: <Transaction Id Hex String>
|
|
34
|
+
}
|
|
35
|
+
*/
|
|
36
|
+
module.exports = (args, cbk) => {
|
|
37
|
+
return new Promise((resolve, reject) => {
|
|
38
|
+
return asyncAuto({
|
|
39
|
+
// Import ECPair library
|
|
40
|
+
ecp: async () => (await import('ecpair')).ECPairFactory(tinysecp),
|
|
41
|
+
|
|
42
|
+
// Check arguments
|
|
43
|
+
validate: cbk => {
|
|
44
|
+
if (!args.capacity) {
|
|
45
|
+
return cbk([400, 'ExpectedChannelCapacityToCreateChannelGroup']);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (args.capacity < minChannelSize) {
|
|
49
|
+
return cbk([400, 'ExpectedCapacityGreaterThanMinSizeToCreateGroup']);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (isOdd(args.capacity)) {
|
|
53
|
+
return cbk([400, 'ExpectedEvenChannelCapacityToCreateChannelGroup']);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (!args.count) {
|
|
57
|
+
return cbk([400, 'ExpectedGroupSizeToCreateChannelGroup']);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (args.count < minGroupSize || args.count > maxGroupSize) {
|
|
61
|
+
return cbk([400, 'ExpectedValidGroupSizeToCreateChannelGroup']);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (!args.lnd) {
|
|
65
|
+
return cbk([400, 'ExpectedAuthenticatedLndToCreateChannelGroup']);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (!args.logger) {
|
|
69
|
+
return cbk([400, 'ExpectedWinstonLoggerToCreateChannelGroup']);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (!args.rate) {
|
|
73
|
+
return cbk([400, 'ExpectedOpeningFeeRateToCreateChannelGroup']);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return cbk();
|
|
77
|
+
},
|
|
78
|
+
|
|
79
|
+
// Get the on-chain balance to sanity check group creation
|
|
80
|
+
getBalance: ['validate', ({}, cbk) => {
|
|
81
|
+
return getChainBalance({lnd: args.lnd}, cbk);
|
|
82
|
+
}],
|
|
83
|
+
|
|
84
|
+
// Get identity public key
|
|
85
|
+
getIdentity: ['validate', ({}, cbk) => getIdentity({lnd: args.lnd}, cbk)],
|
|
86
|
+
|
|
87
|
+
// Get methods to confim partial signing is supported
|
|
88
|
+
getMethods: ['validate', ({}, cbk) => getMethods({lnd: args.lnd}, cbk)],
|
|
89
|
+
|
|
90
|
+
// Sanity check the on-chain balance is reasonable to create a group
|
|
91
|
+
confirmBalance: ['getBalance', ({getBalance}, cbk) => {
|
|
92
|
+
// A pair group requires half the amount of capital
|
|
93
|
+
const isPair = args.count === minGroupSize;
|
|
94
|
+
|
|
95
|
+
if (!isPair && args.capacity > getBalance.chain_balance) {
|
|
96
|
+
return cbk([400, 'ExpectedCapacityLowerThanCurrentChainBalance']);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (isPair && halfOf(args.capacity) > getBalance.chain_balance) {
|
|
100
|
+
return cbk([400, 'ExpectedCapacityLowerThanCurrentChainBalance']);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return cbk();
|
|
104
|
+
}],
|
|
105
|
+
|
|
106
|
+
// Make sure that partially signing a PSBT is a known method
|
|
107
|
+
confirmSigner: ['getMethods', ({getMethods}, cbk) => {
|
|
108
|
+
if (!getMethods.methods.find(n => n.endpoint === signPsbtEndpoint)) {
|
|
109
|
+
return cbk([400, 'ExpectedLndSupportingPartialPsbtSigning']);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return cbk();
|
|
113
|
+
}],
|
|
114
|
+
|
|
115
|
+
// Fund and assemble the group
|
|
116
|
+
create: [
|
|
117
|
+
'ecp',
|
|
118
|
+
'confirmBalance',
|
|
119
|
+
'confirmSigner',
|
|
120
|
+
'getBalance',
|
|
121
|
+
'getIdentity',
|
|
122
|
+
({ecp, getIdentity}, cbk) =>
|
|
123
|
+
{
|
|
124
|
+
const coordinate = assembleChannelGroup({
|
|
125
|
+
ecp,
|
|
126
|
+
capacity: args.capacity,
|
|
127
|
+
count: args.count,
|
|
128
|
+
identity: getIdentity.public_key,
|
|
129
|
+
lnd: args.lnd,
|
|
130
|
+
rate: args.rate,
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
const code = getIdentity.public_key + coordinate.id;
|
|
134
|
+
|
|
135
|
+
args.logger.info({group_invite_code: code});
|
|
136
|
+
|
|
137
|
+
// The group must fill up with participants first
|
|
138
|
+
coordinate.events.once('filled', async ({ids}) => {
|
|
139
|
+
const members = ids.filter(n => n !== getIdentity.public_key);
|
|
140
|
+
|
|
141
|
+
const nodes = await asyncMap(members, async id => {
|
|
142
|
+
return niceName(await getNodeAlias({id, lnd: args.lnd}));
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
return args.logger.info({ready: join(nodes)});
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
// Once filled, members will connect with their partners
|
|
149
|
+
coordinate.events.once('connected', () => {
|
|
150
|
+
return args.logger.info({peered: true});
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
// Members will propose pending channels to each other
|
|
154
|
+
coordinate.events.once('proposed', () => {
|
|
155
|
+
return args.logger.info({proposed: true});
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
// Once all pending channels are in place, signatures will be received
|
|
159
|
+
coordinate.events.once('signed', () => {
|
|
160
|
+
return args.logger.info({signed: true});
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
// Finally the open channel tx will be broadcast
|
|
164
|
+
coordinate.events.once('broadcasting', broadcast => {
|
|
165
|
+
return args.logger.info({publishing: broadcast.transaction});
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
// After broadcasting the channels transaction needs to confirm
|
|
169
|
+
coordinate.events.once('broadcast', broadcast => {
|
|
170
|
+
coordinate.events.removeAllListeners();
|
|
171
|
+
|
|
172
|
+
return cbk(null, {transaction_id: broadcast.id});
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
coordinate.events.once('error', err => {
|
|
176
|
+
return cbk([503, 'UnexpectedErrorAssemblingChannelGroup', {err}]);
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
return;
|
|
180
|
+
}],
|
|
181
|
+
},
|
|
182
|
+
returnResult({reject, resolve, of: 'create'}, cbk));
|
|
183
|
+
});
|
|
184
|
+
};
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
const asyncAuto = require('async/auto');
|
|
2
|
+
const asyncRetry = require('async/retry');
|
|
3
|
+
const {connectPeer} = require('ln-sync');
|
|
4
|
+
const {getChainBalance} = require('ln-service');
|
|
5
|
+
const {getNodeAlias} = require('ln-sync');
|
|
6
|
+
const {returnResult} = require('asyncjs-util');
|
|
7
|
+
|
|
8
|
+
const {getGroupDetails} = require('./p2p');
|
|
9
|
+
|
|
10
|
+
const coordinatorFromJoinCode = n => n.slice(0, 66);
|
|
11
|
+
const groupIdFromJoinCode = n => n.slice(66);
|
|
12
|
+
const interval = 500;
|
|
13
|
+
const isCode = n => !!n && n.length === 98;
|
|
14
|
+
const isPublicKey = n => !!n && /^0[2-3][0-9A-F]{64}$/i.test(n);
|
|
15
|
+
const join = arr => arr.join(' ');
|
|
16
|
+
const niceName = n => `${n.alias} ${n.id}`.trim();
|
|
17
|
+
const times = 2 * 60;
|
|
18
|
+
const tokensAsBigUnit = tokens => (tokens / 1e8).toFixed(8);
|
|
19
|
+
|
|
20
|
+
/** Ask to confirm joining a group
|
|
21
|
+
|
|
22
|
+
{
|
|
23
|
+
code: <Group Invite Code String>
|
|
24
|
+
lnd: <Authenticated LND API Object>
|
|
25
|
+
logger: <Winston Logger Object>
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@returns via cbk or Promise
|
|
29
|
+
{
|
|
30
|
+
capacity: <Channel Capacity Tokens Number>
|
|
31
|
+
coordinator: <Group Coordinator Identity Public Key Hex String>
|
|
32
|
+
count: <Group Members Count>
|
|
33
|
+
id: <Group Id Hex String>
|
|
34
|
+
rate: <Chain Fee Tokens Per VByte Number>
|
|
35
|
+
}
|
|
36
|
+
*/
|
|
37
|
+
module.exports = ({code, lnd, logger}, cbk) => {
|
|
38
|
+
return new Promise((resolve, reject) => {
|
|
39
|
+
return asyncAuto({
|
|
40
|
+
// Check arguments
|
|
41
|
+
validate: cbk => {
|
|
42
|
+
if (!isCode(code)) {
|
|
43
|
+
return cbk([400, 'ExpectedChannelGroupInviteCodeToGetJoinDetails']);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (!lnd) {
|
|
47
|
+
return cbk([400, 'ExpectedAuthenticatedLndToGetJoinGroupDetails']);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (!logger) {
|
|
51
|
+
return cbk([400, 'ExpectedWinstonLoggerObjectToGetJoinDetails']);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return cbk();
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
// Get the wallet balance to make sure there are enough funds to join
|
|
58
|
+
getBalance: ['validate', ({}, cbk) => getChainBalance({lnd}, cbk)],
|
|
59
|
+
|
|
60
|
+
// Parse the group join code
|
|
61
|
+
group: ['validate', ({}, cbk) => {
|
|
62
|
+
const coordinator = coordinatorFromJoinCode(code);
|
|
63
|
+
|
|
64
|
+
if (!isPublicKey(coordinator)) {
|
|
65
|
+
return cbk([400, 'ExpectedValidGroupJoinCodeToRequestGroupDetails']);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const id = groupIdFromJoinCode(code);
|
|
69
|
+
|
|
70
|
+
return cbk(null, {id, coordinator})
|
|
71
|
+
}],
|
|
72
|
+
|
|
73
|
+
// Connect to the coordinator
|
|
74
|
+
connect: ['group', ({group}, cbk) => {
|
|
75
|
+
return asyncRetry({interval, times}, cbk => {
|
|
76
|
+
return connectPeer({lnd, id: group.coordinator}, cbk);
|
|
77
|
+
},
|
|
78
|
+
cbk);
|
|
79
|
+
}],
|
|
80
|
+
|
|
81
|
+
// Get the coordinator node alias to log it out
|
|
82
|
+
getAlias: ['group', ({group}, cbk) => {
|
|
83
|
+
return getNodeAlias({lnd, id: group.coordinator}, cbk);
|
|
84
|
+
}],
|
|
85
|
+
|
|
86
|
+
// Get the group details from the coordinator
|
|
87
|
+
getDetails: ['group', ({group}, cbk) => {
|
|
88
|
+
return getGroupDetails({
|
|
89
|
+
lnd,
|
|
90
|
+
coordinator: group.coordinator,
|
|
91
|
+
id: group.id,
|
|
92
|
+
},
|
|
93
|
+
cbk);
|
|
94
|
+
}],
|
|
95
|
+
|
|
96
|
+
// Log the details of the group being joined
|
|
97
|
+
log: [
|
|
98
|
+
'getAlias',
|
|
99
|
+
'getBalance',
|
|
100
|
+
'getDetails',
|
|
101
|
+
({getAlias, getBalance, getDetails}, cbk) =>
|
|
102
|
+
{
|
|
103
|
+
const coordinatedBy = `coordinated by ${niceName(getAlias)}`;
|
|
104
|
+
const members = `${getDetails.count} member group`;
|
|
105
|
+
const size = `with ${tokensAsBigUnit(getDetails.capacity)} channels`;
|
|
106
|
+
const rate = `and paying ${getDetails.rate}/vbyte chain fee`;
|
|
107
|
+
|
|
108
|
+
logger.info({joining: join([members, coordinatedBy, size, rate])});
|
|
109
|
+
|
|
110
|
+
// Check to make sure that there are on chain funds for this group
|
|
111
|
+
if (getBalance.chain_balance < getDetails.funding) {
|
|
112
|
+
return cbk([
|
|
113
|
+
400,
|
|
114
|
+
'InsufficientChainFundsAvailableToJoinGroup',
|
|
115
|
+
{chain_balance: getBalance.chain_balance},
|
|
116
|
+
]);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return cbk();
|
|
120
|
+
}],
|
|
121
|
+
|
|
122
|
+
// Go ahead with the group join
|
|
123
|
+
join: ['getDetails', 'group', 'log', ({getDetails, group}, cbk) => {
|
|
124
|
+
return cbk(null, {
|
|
125
|
+
capacity: getDetails.capacity,
|
|
126
|
+
coordinator: group.coordinator,
|
|
127
|
+
count: getDetails.count,
|
|
128
|
+
id: group.id,
|
|
129
|
+
rate: getDetails.rate,
|
|
130
|
+
});
|
|
131
|
+
}],
|
|
132
|
+
},
|
|
133
|
+
returnResult({reject, resolve, of: 'join'}, cbk));
|
|
134
|
+
});
|
|
135
|
+
};
|
package/groups/index.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
const createGroupChannel = require('./create_group_channel');
|
|
2
|
+
const joinGroupChannel = require('./join_group_channel');
|
|
1
3
|
const manageGroupJoin = require('./manage_group_join');
|
|
2
4
|
|
|
3
|
-
module.exports = {manageGroupJoin};
|
|
5
|
+
module.exports = {createGroupChannel, joinGroupChannel, manageGroupJoin};
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
const asyncAuto = require('async/auto');
|
|
2
|
+
const asyncMap = require('async/map');
|
|
3
|
+
const {getMethods} = require('ln-service');
|
|
4
|
+
const {getNodeAlias} = require('ln-sync');
|
|
5
|
+
const {returnResult} = require('asyncjs-util');
|
|
6
|
+
|
|
7
|
+
const joinChannelGroup = require('./join_channel_group');
|
|
8
|
+
const getJoinDetails = require('./get_join_details');
|
|
9
|
+
|
|
10
|
+
const formatNodes = arr => arr.join(', ');
|
|
11
|
+
const isCode = n => !!n && n.length === 98;
|
|
12
|
+
const niceName = ({alias, id}) => `${alias} ${id}`.trim();
|
|
13
|
+
const signPsbtEndpoint = '/walletrpc.WalletKit/SignPsbt';
|
|
14
|
+
|
|
15
|
+
/** Join a channel group
|
|
16
|
+
|
|
17
|
+
{
|
|
18
|
+
code: <Group Invite Code String>
|
|
19
|
+
lnd: <Authenticated LND API Object>
|
|
20
|
+
logger: <Winston Logger Object>
|
|
21
|
+
max_rate: <Max Opening Chain Fee Tokens Per VByte Fee Rate Number>
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@returns via cbk or Promise
|
|
25
|
+
{
|
|
26
|
+
transaction_id: <Channel Funding Transaction Id Hex String>
|
|
27
|
+
}
|
|
28
|
+
*/
|
|
29
|
+
module.exports = (args, cbk) => {
|
|
30
|
+
return new Promise((resolve, reject) => {
|
|
31
|
+
return asyncAuto({
|
|
32
|
+
// Check arguments
|
|
33
|
+
validate: cbk => {
|
|
34
|
+
if (!isCode(args.code)) {
|
|
35
|
+
return cbk([400, 'ExpectedValidJoinCodeToJoinGroup']);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (!args.lnd) {
|
|
39
|
+
return cbk([400, 'ExpectedAuthenticatedLndToJoinGroup']);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (!args.logger) {
|
|
43
|
+
return cbk([400, 'ExpectedWinstonLoggerToJoinGroupp']);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (!args.max_rate) {
|
|
47
|
+
return cbk([400, 'ExpectedMaxOpeningFeeRateToJoinGroup']);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return cbk();
|
|
51
|
+
},
|
|
52
|
+
|
|
53
|
+
// Get methods to confim partial signing is supported
|
|
54
|
+
getMethods: ['validate', ({}, cbk) => getMethods({lnd: args.lnd}, cbk)],
|
|
55
|
+
|
|
56
|
+
// Make sure that partially signing a PSBT is valid
|
|
57
|
+
confirmSigner: ['getMethods', ({getMethods}, cbk) => {
|
|
58
|
+
if (!getMethods.methods.find(n => n.endpoint === signPsbtEndpoint)) {
|
|
59
|
+
return cbk([400, 'ExpectedLndSupportingPartialPsbtSigningToJoin']);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return cbk();
|
|
63
|
+
}],
|
|
64
|
+
|
|
65
|
+
// Decode the group invite code and get group details
|
|
66
|
+
getJoinDetails: ['confirmSigner', ({}, cbk) => {
|
|
67
|
+
return getJoinDetails({
|
|
68
|
+
code: args.code,
|
|
69
|
+
lnd: args.lnd,
|
|
70
|
+
logger: args.logger,
|
|
71
|
+
},
|
|
72
|
+
cbk);
|
|
73
|
+
}],
|
|
74
|
+
|
|
75
|
+
// Join the channel group
|
|
76
|
+
join: [
|
|
77
|
+
'confirmSigner',
|
|
78
|
+
'getMethods',
|
|
79
|
+
'getJoinDetails',
|
|
80
|
+
({getJoinDetails}, cbk) =>
|
|
81
|
+
{
|
|
82
|
+
if (getJoinDetails.rate > args.max_rate) {
|
|
83
|
+
return cbk([400, 'ExpectedHigherMaxFeeRateToJoinGroup']);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
args.logger.info({waiting_for_other_members: true});
|
|
87
|
+
|
|
88
|
+
const join = joinChannelGroup({
|
|
89
|
+
capacity: getJoinDetails.capacity,
|
|
90
|
+
coordinator: getJoinDetails.coordinator,
|
|
91
|
+
count: getJoinDetails.count,
|
|
92
|
+
id: getJoinDetails.id,
|
|
93
|
+
lnd: args.lnd,
|
|
94
|
+
rate: getJoinDetails.rate,
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
join.once('end', ({id}) => cbk(null, {transaction_id: id}));
|
|
98
|
+
join.once('error', err => cbk(err));
|
|
99
|
+
|
|
100
|
+
// After the group is filled the members are matched and peer up
|
|
101
|
+
join.once('peering', async ({inbound, outbound}) => {
|
|
102
|
+
const nodes = await asyncMap([inbound, outbound], async id => {
|
|
103
|
+
return niceName(await getNodeAlias({id, lnd: args.lnd}));
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
return args.logger.info({peering_with: formatNodes(nodes)});
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
// Once everyone is peered then the channel tx is made
|
|
110
|
+
join.once('publishing', ({refund, signed}) => {
|
|
111
|
+
return args.logger.info({refund, signed});
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
return;
|
|
115
|
+
}],
|
|
116
|
+
},
|
|
117
|
+
returnResult({reject, resolve, of: 'join'}, cbk));
|
|
118
|
+
});
|
|
119
|
+
};
|
package/index.js
CHANGED
|
@@ -2,11 +2,13 @@ const {balancedOpenRequest} = require('./balanced');
|
|
|
2
2
|
const {changeChannelCapacity} = require('./capacity');
|
|
3
3
|
const {confirmServiceUse} = require('./client');
|
|
4
4
|
const {createAnchoredTrade} = require('./trades');
|
|
5
|
+
const {createGroupChannel} = require('./groups');
|
|
5
6
|
const {decodeTrade} = require('./trades');
|
|
6
7
|
const {encodeTrade} = require('./trades');
|
|
7
8
|
const {getAnchoredTrade} = require('./trades');
|
|
8
9
|
const {getServiceSchema} = require('./client');
|
|
9
10
|
const {getServicesList} = require('./client');
|
|
11
|
+
const {joinGroupChannel} = require('./groups');
|
|
10
12
|
const {makePeerRequest} = require('./p2p');
|
|
11
13
|
const {makeServiceRequest} = require('./client');
|
|
12
14
|
const {manageGroupJoin} = require('./groups');
|
|
@@ -24,11 +26,13 @@ module.exports = {
|
|
|
24
26
|
changeChannelCapacity,
|
|
25
27
|
confirmServiceUse,
|
|
26
28
|
createAnchoredTrade,
|
|
29
|
+
createGroupChannel,
|
|
27
30
|
decodeTrade,
|
|
28
31
|
encodeTrade,
|
|
29
32
|
getAnchoredTrade,
|
|
30
33
|
getServiceSchema,
|
|
31
34
|
getServicesList,
|
|
35
|
+
joinGroupChannel,
|
|
32
36
|
makePeerRequest,
|
|
33
37
|
makeServiceRequest,
|
|
34
38
|
manageGroupJoin,
|
package/package.json
CHANGED
|
@@ -13,24 +13,24 @@
|
|
|
13
13
|
"bech32": "2.0.0",
|
|
14
14
|
"bolt01": "1.2.5",
|
|
15
15
|
"bolt07": "1.8.2",
|
|
16
|
-
"ecpair": "2.0
|
|
17
|
-
"goldengate": "11.
|
|
18
|
-
"invoices": "2.
|
|
19
|
-
"ln-service": "
|
|
20
|
-
"ln-sync": "3.
|
|
16
|
+
"ecpair": "2.1.0",
|
|
17
|
+
"goldengate": "11.4.0",
|
|
18
|
+
"invoices": "2.2.0",
|
|
19
|
+
"ln-service": "54.2.0",
|
|
20
|
+
"ln-sync": "3.14.0",
|
|
21
21
|
"psbt": "2.7.1",
|
|
22
|
-
"p2tr": "1.3.
|
|
22
|
+
"p2tr": "1.3.2",
|
|
23
23
|
"tiny-secp256k1": "2.2.1"
|
|
24
24
|
},
|
|
25
25
|
"description": "Lightning Paid Services library",
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@alexbosworth/tap": "15.0.11",
|
|
28
|
-
"ln-docker-daemons": "
|
|
29
|
-
"mock-lnd": "1.4.
|
|
28
|
+
"ln-docker-daemons": "3.1.0",
|
|
29
|
+
"mock-lnd": "1.4.4",
|
|
30
30
|
"secp256k1": "4.0.3"
|
|
31
31
|
},
|
|
32
32
|
"engines": {
|
|
33
|
-
"node": ">=
|
|
33
|
+
"node": ">=14"
|
|
34
34
|
},
|
|
35
35
|
"keywords": [
|
|
36
36
|
"lightning",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
},
|
|
46
46
|
"scripts": {
|
|
47
47
|
"integration-tests": "tap -j 2 --branches=1 --functions=1 --lines=1 --statements=1 -t 180 test/integration/*.js",
|
|
48
|
-
"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/
|
|
48
|
+
"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"
|
|
49
49
|
},
|
|
50
|
-
"version": "
|
|
50
|
+
"version": "4.0.0"
|
|
51
51
|
}
|