paid-services 3.20.0 → 3.20.3

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,17 @@
1
1
  # Versions
2
2
 
3
+ ## Version 3.20.3
4
+
5
+ - `manageGroupJoin`: Allow coordinating pair when funds are below the capacity
6
+
7
+ ## Version 3.20.2
8
+
9
+ - `manageGroupJoin`: Allow opening a pair channel when funds are below capacity
10
+
11
+ ## Version 3.20.1
12
+
13
+ - `manageTrades`: Fix seller connection when not peered
14
+
3
15
  ## Version 3.20.0
4
16
 
5
17
  - `manageGroupJoin`: Add support for 2 person groups
@@ -6,6 +6,7 @@ const {returnResult} = require('asyncjs-util');
6
6
  const defaultChannelCapacity = 5e6;
7
7
  const defaultGroupSize = 3;
8
8
  const {floor} = Math;
9
+ const halfOf = input => Number(input) / 2;
9
10
  const isNumber = n => !isNaN(n);
10
11
  const isOdd = n => !!(n % 2);
11
12
  const maxChannelSize = 21e14;
@@ -47,76 +48,87 @@ module.exports = ({ask, lnd}, cbk) => {
47
48
  // Get the wallet balance to make sure there are enough funds to join
48
49
  getBalance: ['validate', ({}, cbk) => getChainBalance({lnd}, cbk)],
49
50
 
50
- // Ask for how big the channels should be
51
- askForCapacity: ['getBalance', ({getBalance}, cbk) => {
51
+ // Get the chain fee rate to use for a default in the chain fee query
52
+ getFeeRate: ['validate', ({}, cbk) => getChainFeeRate({lnd}, cbk)],
53
+
54
+ // Ask for how many group members there should be
55
+ askForCount: ['validate', ({}, cbk) => {
52
56
  return ask({
53
- default: defaultChannelCapacity,
54
- name: 'capacity',
55
- message: 'Channel capacity?',
57
+ default: defaultGroupSize,
58
+ name: 'size',
59
+ message: 'Total number of group members?',
56
60
  validate: input => {
57
61
  if (!input || !isNumber(input)) {
58
62
  return false;
59
63
  }
60
64
 
65
+ // Do not allow fractional members
61
66
  if (round(Number(input)) !== Number(input)) {
62
67
  return false;
63
68
  }
64
69
 
65
- if (Number(input) > getBalance.chain_balance) {
66
- return `Current chain balance is ${getBalance.chain_balance}`;
67
- }
68
-
69
- if (Number(input) < minChannelSize) {
70
- return `Minimum channel size is ${minChannelSize}`;
70
+ // Do not allow too many members
71
+ if (Number(input) > maxGroupSize) {
72
+ return `The maximum group size is ${maxGroupSize}`;
71
73
  }
72
74
 
73
- if (isOdd(Number(input))) {
74
- return 'Channel capacity must be even';
75
+ // Do not allow too few members
76
+ if (Number(input) < minGroupSize) {
77
+ return `The minimum group size is ${minGroupSize}`;
75
78
  }
76
79
 
77
80
  return true;
78
81
  },
79
82
  },
80
- ({capacity}) => cbk(null, Number(capacity)));
83
+ ({size}) => cbk(null, Number(size)));
81
84
  }],
82
85
 
83
- // Get the chain fee rate to use for a default in the chain fee query
84
- getFeeRate: ['validate', ({}, cbk) => getChainFeeRate({lnd}, cbk)],
86
+ // Ask for how big the channels should be
87
+ askForCapacity: [
88
+ 'askForCount',
89
+ 'getBalance',
90
+ ({askForCount, getBalance}, cbk) =>
91
+ {
92
+ const isPair = askForCount === minGroupSize;
85
93
 
86
- // Ask for how many group members there should be
87
- askForCount: ['askForCapacity', ({askForCapacity}, cbk) => {
88
94
  return ask({
89
- default: defaultGroupSize,
90
- name: 'size',
91
- message: 'Total number of group members?',
95
+ default: defaultChannelCapacity,
96
+ name: 'capacity',
97
+ message: 'Channel capacity?',
92
98
  validate: input => {
93
99
  if (!input || !isNumber(input)) {
94
100
  return false;
95
101
  }
96
102
 
97
- // Do not allow fractional members
98
103
  if (round(Number(input)) !== Number(input)) {
99
104
  return false;
100
105
  }
101
106
 
102
- // Do not allow too many members
103
- if (Number(input) > maxGroupSize) {
104
- return `The maximum group size is ${maxGroupSize}`;
107
+ if (!isPair && Number(input) > getBalance.chain_balance) {
108
+ return `Current chain balance is ${getBalance.chain_balance}`;
105
109
  }
106
110
 
107
- // Do not allow too few members
108
- if (Number(input) < minGroupSize) {
109
- return `The minimum group size is ${minGroupSize}`;
111
+ if (isPair && halfOf(input) > getBalance.chain_balance) {
112
+ return `Current chain balance is ${getBalance.chain_balance}`;
113
+ }
114
+
115
+ if (Number(input) < minChannelSize) {
116
+ return `Minimum channel size is ${minChannelSize}`;
117
+ }
118
+
119
+ if (isOdd(Number(input))) {
120
+ return 'Channel capacity must be even';
110
121
  }
111
122
 
112
123
  return true;
113
124
  },
114
125
  },
115
- ({size}) => cbk(null, size));
126
+ ({capacity}) => cbk(null, Number(capacity)));
116
127
  }],
117
128
 
118
129
  // Ask for a chain fee rate
119
130
  askForFeeRate: [
131
+ 'askForCapacity',
120
132
  'askForCount',
121
133
  'getFeeRate',
122
134
  ({askForCount, getFeeRate}, cbk) =>
@@ -105,7 +105,7 @@ module.exports = ({ask, lnd}, cbk) => {
105
105
  ({getAlias, getBalance, getDetails}, cbk) =>
106
106
  {
107
107
  // Check to make sure that there are on chain funds for this group
108
- if (getBalance.chain_balance < getDetails.capacity) {
108
+ if (getBalance.chain_balance < getDetails.funding) {
109
109
  return cbk([
110
110
  400,
111
111
  'InsufficientChainFundsAvailableToJoinGroup',
@@ -1,11 +1,13 @@
1
1
  const {decodeBigSize} = require('bolt01');
2
2
 
3
3
  const findRecord = (records, type) => records.find(n => n.type === type);
4
+ const funding = (capacity, count) => count === 2 ? capacity / 2 : capacity;
4
5
  const {isArray} = Array;
5
6
  const isOdd = n => !!(n % 2);
6
7
  const maxCapacityTokens = BigInt(7e14);
7
8
  const maxMembersCount = BigInt(650);
8
9
  const maxFeeRate = BigInt(1e5);
10
+ const minMembersCount = BigInt(2);
9
11
  const typeCapacity = '1';
10
12
  const typeCount = '2';
11
13
  const typeRate = '3';
@@ -28,6 +30,7 @@ const version = '1';
28
30
  {
29
31
  capacity: <Channel Capacity Tokens Number>
30
32
  count: <Target Members Count Number>
33
+ funding: <Amount Of Funding Required Tokens Number>
31
34
  rate: <Chain Fee Rate Number>
32
35
  }
33
36
  */
@@ -88,6 +91,10 @@ module.exports = ({records}) => {
88
91
  throw new Error('UnexpectedValueForCountInGroupRecords');
89
92
  }
90
93
 
94
+ if (BigInt(count) < minMembersCount) {
95
+ throw new Error('ExpectedHigherMembersCountInGroupDetails');
96
+ }
97
+
91
98
  const rateRecord = findRecord(records, typeRate);
92
99
 
93
100
  try {
@@ -105,6 +112,7 @@ module.exports = ({records}) => {
105
112
  return {
106
113
  capacity: Number(capacity),
107
114
  count: Number(count),
115
+ funding: funding(Number(capacity), Number(count)),
108
116
  rate: Number(rate),
109
117
  };
110
118
  };
@@ -24,6 +24,7 @@ const typeGroupChannelId = '1';
24
24
  {
25
25
  capacity: <Channel Capacity Tokens Number>
26
26
  count: <Target Members Count Number>
27
+ funding: <Amount Of Funding Required Tokens Number>
27
28
  rate: <Chain Fee Rate Number>
28
29
  }
29
30
  */
package/package.json CHANGED
@@ -16,7 +16,7 @@
16
16
  "ecpair": "2.0.1",
17
17
  "goldengate": "11.2.3",
18
18
  "invoices": "2.1.0",
19
- "ln-service": "53.17.5",
19
+ "ln-service": "53.20.0",
20
20
  "ln-sync": "3.13.1",
21
21
  "psbt": "2.7.1",
22
22
  "p2tr": "1.3.1",
@@ -25,8 +25,8 @@
25
25
  "description": "Lightning Paid Services library",
26
26
  "devDependencies": {
27
27
  "@alexbosworth/tap": "15.0.11",
28
- "ln-docker-daemons": "2.3.2",
29
- "mock-lnd": "1.4.1",
28
+ "ln-docker-daemons": "2.3.4",
29
+ "mock-lnd": "1.4.3",
30
30
  "secp256k1": "4.0.3"
31
31
  },
32
32
  "engines": {
@@ -47,5 +47,5 @@
47
47
  "integration-tests": "tap -j 2 --branches=1 --functions=1 --lines=1 --statements=1 -t 180 test/integration/*.js",
48
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/server/*.js test/services/*.js test/trades/*.js"
49
49
  },
50
- "version": "3.20.0"
50
+ "version": "3.20.3"
51
51
  }
@@ -66,6 +66,9 @@ module.exports = ({lnd, logger, nodes}, cbk) => {
66
66
  // Derive the self public key
67
67
  getIdentity: ['validate', ({}, cbk) => getIdentity({lnd}, cbk)],
68
68
 
69
+ // Get the actively connected peers
70
+ getPeered: ['validate', ({}, cbk) => getPeers({lnd}, cbk)],
71
+
69
72
  // Find node connect info to connect to
70
73
  getNodes: ['getIdentity', ({getIdentity}, cbk) => {
71
74
  return asyncMap(nodes, (connect, cbk) => {
@@ -144,7 +147,8 @@ module.exports = ({lnd, logger, nodes}, cbk) => {
144
147
  removePeer: [
145
148
  'getChannels',
146
149
  'getNodes',
147
- ({getChannels, getNodes}, cbk) =>
150
+ 'getPeered',
151
+ ({getChannels, getNodes, getPeered}, cbk) =>
148
152
  {
149
153
  const ids = getChannels.channels.map(n => n.partner_public_key);
150
154
 
@@ -154,6 +158,11 @@ module.exports = ({lnd, logger, nodes}, cbk) => {
154
158
  return cbk();
155
159
  }
156
160
 
161
+ // Exit early when already not peered
162
+ if (!getPeered.peers.map(n => n.public_key).includes(node.id)) {
163
+ return cbk();
164
+ }
165
+
157
166
  return removePeer({lnd, public_key: node.id}, (err, res) => {
158
167
  if (!!err) {
159
168
  return cbk(err);
@@ -181,7 +190,7 @@ module.exports = ({lnd, logger, nodes}, cbk) => {
181
190
  }],
182
191
 
183
192
  // Get the list of connected peers
184
- getPeers: ['removePeer', ({}, cbk) => getPeers({lnd}, cbk)],
193
+ getPeers: ['validate', ({}, cbk) => getPeers({lnd}, cbk)],
185
194
 
186
195
  // Try and connect to a node in order to do p2p messaging
187
196
  connect: [