bolt07 1.8.4 → 1.9.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,10 @@
1
1
  # Versions
2
2
 
3
+ ## 1.9.0
4
+
5
+ - `hopsFromChannels`, `routeFromChannels`, `routeFromHops`: Add support for
6
+ inbound discounts
7
+
3
8
  ## 1.8.4
4
9
 
5
10
  - `decodeSocket`: Decode a connection socket from hex data
@@ -27,4 +27,3 @@ module.exports = ({channel, id}) => {
27
27
 
28
28
  return {number: new BN(Buffer.from(rawId, 'hex')).toString(decBase)};
29
29
  };
30
-
package/package.json CHANGED
@@ -28,5 +28,5 @@
28
28
  "scripts": {
29
29
  "test": "npx nyc@15.1 node --experimental-test-coverage --test"
30
30
  },
31
- "version": "1.8.4"
31
+ "version": "1.9.0"
32
32
  }
@@ -15,6 +15,8 @@ const payNodesCount = 2;
15
15
  base_fee_mtokens: <Base Fee Millitokens String>
16
16
  cltv_delta: <Locktime Delta Number>
17
17
  fee_rate: <Fees Charged Per Million Tokens Number>
18
+ [inbound_base_discount_mtokens]: <Source Base Fee Reduction String>
19
+ [inbound_rate_discount]: <Source Per Million Rate Reduction Number>
18
20
  is_disabled: <Channel Is Disabled Bool>
19
21
  min_htlc_mtokens: <Minimum HTLC Millitokens Value String>
20
22
  public_key: <Node Public Key String>
@@ -34,6 +36,8 @@ const payNodesCount = 2;
34
36
  channel_capacity: <Maximum Tokens Number>
35
37
  cltv_delta: <CLTV Delta Number>
36
38
  fee_rate: <Fee Rate In Millitokens Per Million Number>
39
+ [inbound_base_discount_mtokens]: <Source Base Fee Reduction String>
40
+ [inbound_rate_discount]: <Source Per Million Rate Reduction Number>
37
41
  public_key: <Public Key Hex String>
38
42
  }]
39
43
  }
@@ -74,7 +78,7 @@ module.exports = ({channels, destination}) => {
74
78
  const nextPolicy = chans[i + [channel].length];
75
79
  let overridePolicy;
76
80
 
77
- const peer = channel.policies.find(n => n.public_key === nextHop);
81
+ const peer = channel.policies.find(n => n.public_key === nextHop) || {};
78
82
  const policy = channel.policies.find(n => n.public_key !== nextHop);
79
83
 
80
84
  if (!policy) {
@@ -104,6 +108,8 @@ module.exports = ({channels, destination}) => {
104
108
  channel_capacity: channel.capacity,
105
109
  cltv_delta: cltvDelta || defaultCltvDelta,
106
110
  fee_rate: (overridePolicy || policy).fee_rate,
111
+ inbound_base_discount_mtokens: peer.inbound_base_discount_mtokens,
112
+ inbound_rate_discount: peer.inbound_rate_discount,
107
113
  public_key: nextHop,
108
114
  };
109
115
  });
@@ -1,3 +1,4 @@
1
+ const none = '0';
1
2
  const rateDivisor = BigInt(1e6);
2
3
 
3
4
  /** Fee for policy
@@ -7,6 +8,8 @@ const rateDivisor = BigInt(1e6);
7
8
  policy: {
8
9
  base_fee_mtokens: <Base Fee Millitokens String>
9
10
  fee_rate: <Fee Rate Number>
11
+ [inbound_base_discount_mtokens]: <Source Base Fee Reduction String>
12
+ [inbound_rate_discount]: <Source Per Million Rate Reduction Number>
10
13
  }
11
14
  }
12
15
 
@@ -38,8 +41,16 @@ module.exports = ({mtokens, policy}) => {
38
41
  const baseFeeMtokens = BigInt(policy.base_fee_mtokens);
39
42
  const feeRate = BigInt(policy.fee_rate);
40
43
  const forwardMtokens = BigInt(mtokens);
44
+ const lowerBaseFee = BigInt(policy.inbound_base_discount_mtokens || none);
45
+ const lowerFeeRate = BigInt(policy.inbound_rate_discount || none);
41
46
 
47
+ const discount = lowerBaseFee + forwardMtokens * lowerFeeRate / rateDivisor;
42
48
  const fee = baseFeeMtokens + forwardMtokens * feeRate / rateDivisor;
43
49
 
44
- return {fee_mtokens: fee.toString()};
50
+ // Exit early when the discount drowns out the fee
51
+ if (-discount > fee) {
52
+ return {fee_mtokens: none};
53
+ }
54
+
55
+ return {fee_mtokens: (fee + discount).toString()};
45
56
  };
@@ -17,6 +17,8 @@ const {isArray} = Array;
17
17
  base_fee_mtokens: <Base Fee Millitokens String>
18
18
  cltv_delta: <Locktime Delta Number>
19
19
  fee_rate: <Fees Charged in Millitokens Per Million Number>
20
+ [inbound_base_discount_mtokens]: <Source Base Fee Reduction String>
21
+ [inbound_rate_discount]: <Source Per Million Rate Reduction Number>
20
22
  is_disabled: <Channel Is Disabled Bool>
21
23
  max_htlc_mtokens: <Maximum HTLC Millitokens Value String>
22
24
  min_htlc_mtokens: <Minimum HTLC Millitokens Value String>
@@ -17,6 +17,8 @@ const minFee = 0;
17
17
  [channel_capacity]: <Channel Capacity Tokens Number>
18
18
  cltv_delta: <CLTV Delta Number>
19
19
  fee_rate: <Fee Rate In Millitokens Per Million Number>
20
+ [inbound_base_discount_mtokens]: <Source Base Fee Reduction String>
21
+ [inbound_rate_discount]: <Source Per Million Rate Reduction Number>
20
22
  public_key: <Next Hop Public Key Hex String>
21
23
  }]
22
24
  initial_cltv: <Initial CLTV Delta Number>
@@ -110,6 +110,8 @@ const tests = [
110
110
  channel_capacity: 16777215,
111
111
  cltv_delta: 40,
112
112
  fee_rate: 2500,
113
+ inbound_base_discount_mtokens: undefined,
114
+ inbound_rate_discount: undefined,
113
115
  public_key: 'b',
114
116
  },
115
117
  {
@@ -118,6 +120,8 @@ const tests = [
118
120
  channel_capacity: 16777215,
119
121
  cltv_delta: 30,
120
122
  fee_rate: 2500,
123
+ inbound_base_discount_mtokens: undefined,
124
+ inbound_rate_discount: undefined,
121
125
  public_key: 'c',
122
126
  },
123
127
  {
@@ -126,6 +130,8 @@ const tests = [
126
130
  channel_capacity: 16777215,
127
131
  cltv_delta: 144,
128
132
  fee_rate: 1,
133
+ inbound_base_discount_mtokens: undefined,
134
+ inbound_rate_discount: undefined,
129
135
  public_key: 'd',
130
136
  },
131
137
  {
@@ -134,6 +140,8 @@ const tests = [
134
140
  channel_capacity: 16777215,
135
141
  cltv_delta: 144,
136
142
  fee_rate: 1,
143
+ inbound_base_discount_mtokens: undefined,
144
+ inbound_rate_discount: undefined,
137
145
  public_key: 'e',
138
146
  },
139
147
  ],
@@ -151,6 +159,8 @@ const tests = [
151
159
  channel_capacity: 8429350,
152
160
  cltv_delta: 40,
153
161
  fee_rate: 2500,
162
+ inbound_base_discount_mtokens: undefined,
163
+ inbound_rate_discount: undefined,
154
164
  public_key: '03e50492eab4107a773141bb419e107bda3de3d55652e6e1a41225f06a0bbf2d56',
155
165
  },
156
166
  {
@@ -159,6 +169,8 @@ const tests = [
159
169
  channel_capacity: 2000000,
160
170
  cltv_delta: 40,
161
171
  fee_rate: 2500,
172
+ inbound_base_discount_mtokens: undefined,
173
+ inbound_rate_discount: undefined,
162
174
  public_key: '03bb88ccc444534da7b5b64b4f7b15e1eccb18e102db0e400d4b9cfe93763aa26d',
163
175
  },
164
176
  {
@@ -167,6 +179,8 @@ const tests = [
167
179
  channel_capacity: 400000,
168
180
  cltv_delta: 40,
169
181
  fee_rate: 100,
182
+ inbound_base_discount_mtokens: undefined,
183
+ inbound_rate_discount: undefined,
170
184
  public_key: '028dcc199be86786818c8c32bffe9db8855c5fca98951eec99d1fa335d841605c2',
171
185
  },
172
186
  {
@@ -175,6 +189,8 @@ const tests = [
175
189
  channel_capacity: 364355,
176
190
  cltv_delta: 40,
177
191
  fee_rate: 1,
192
+ inbound_base_discount_mtokens: undefined,
193
+ inbound_rate_discount: undefined,
178
194
  public_key: '03277a99c297a53859b42a9bb8cb2c5c17b9eaa44509bae150e2ea35ca5aa29bd9',
179
195
  },
180
196
  ],
@@ -189,6 +205,8 @@ const tests = [
189
205
  channel_capacity: 1000,
190
206
  cltv_delta: 40,
191
207
  fee_rate: 7,
208
+ inbound_base_discount_mtokens: undefined,
209
+ inbound_rate_discount: undefined,
192
210
  public_key: 'alice',
193
211
  },
194
212
  {
@@ -197,6 +215,8 @@ const tests = [
197
215
  channel_capacity: 2000,
198
216
  cltv_delta: 40,
199
217
  fee_rate: 7,
218
+ inbound_base_discount_mtokens: undefined,
219
+ inbound_rate_discount: undefined,
200
220
  public_key: 'bob',
201
221
  },
202
222
  {
@@ -205,6 +225,8 @@ const tests = [
205
225
  channel_capacity: 3000,
206
226
  cltv_delta: 40,
207
227
  fee_rate: 9,
228
+ inbound_base_discount_mtokens: undefined,
229
+ inbound_rate_discount: undefined,
208
230
  public_key: 'charlie',
209
231
  },
210
232
  ],
@@ -240,6 +262,8 @@ const tests = [
240
262
  channel_capacity: 100,
241
263
  cltv_delta: 40,
242
264
  fee_rate: 1,
265
+ inbound_base_discount_mtokens: undefined,
266
+ inbound_rate_discount: undefined,
243
267
  public_key: Buffer.alloc(33).toString('hex'),
244
268
  }],
245
269
  },
@@ -273,6 +297,117 @@ const tests = [
273
297
  description: 'Mapping hops from channels requires hop channel ids',
274
298
  expected: [],
275
299
  },
300
+ {
301
+ args: {
302
+ channels: [
303
+ {
304
+ capacity: 16777215,
305
+ destination: 'b',
306
+ id: '1x1x1',
307
+ policies: [
308
+ {
309
+ _policy_a_has_to_b: true,
310
+ base_fee_mtokens: '0',
311
+ fee_rate: 5000,
312
+ is_disabled: false,
313
+ min_htlc_mtokens: '2000',
314
+ public_key: 'a',
315
+ },
316
+ {
317
+ _policy_b_has_to_a: true,
318
+ base_fee_mtokens: '0',
319
+ fee_rate: 0,
320
+ inbound_base_discount_mtokens: '-5000',
321
+ inbound_rate_discount: 0,
322
+ is_disabled: false,
323
+ public_key: 'b',
324
+ },
325
+ ],
326
+ },
327
+ {
328
+ capacity: 16777215,
329
+ destination: 'c',
330
+ id: '2x2x2',
331
+ policies: [
332
+ {
333
+ _policy_b_has_to_c: true,
334
+ base_fee_mtokens: '0',
335
+ fee_rate: 50000,
336
+ is_disabled: false,
337
+ min_htlc_mtokens: '2000',
338
+ public_key: 'b',
339
+ },
340
+ {
341
+ _policy_c_has_to_b: true,
342
+ base_fee_mtokens: '0',
343
+ fee_rate: 0,
344
+ inbound_base_discount_mtokens: '8000',
345
+ inbound_rate_discount: 200000,
346
+ is_disabled: false,
347
+ public_key: 'c',
348
+ },
349
+ ],
350
+ },
351
+ {
352
+ capacity: 16777215,
353
+ destination: 'd',
354
+ id: '3x3x3',
355
+ policies: [
356
+ {
357
+ _policy_c_has_to_d: true,
358
+ base_fee_mtokens: '9000',
359
+ fee_rate: 100000,
360
+ is_disabled: false,
361
+ min_htlc_mtokens: '2000',
362
+ public_key: 'c',
363
+ },
364
+ {
365
+ _policy_d_has_to_c: true,
366
+ base_fee_mtokens: '0',
367
+ fee_rate: 0,
368
+ inbound_base_discount_mtokens: '-2000',
369
+ inbound_rate_discount: -80000,
370
+ is_disabled: false,
371
+ public_key: 'd',
372
+ },
373
+ ],
374
+ },
375
+ ],
376
+ },
377
+ description: 'Map channels with inbound fee rates',
378
+ expected: [
379
+ {
380
+ base_fee_mtokens: '0',
381
+ channel: '1x1x1',
382
+ channel_capacity: 16777215,
383
+ cltv_delta: 40,
384
+ fee_rate: 50000,
385
+ inbound_base_discount_mtokens: '-5000',
386
+ inbound_rate_discount: 0,
387
+ public_key: 'b',
388
+ },
389
+ {
390
+ base_fee_mtokens: '0',
391
+ channel: '2x2x2',
392
+ channel_capacity: 16777215,
393
+ cltv_delta: 40,
394
+ fee_rate: 50000,
395
+ inbound_base_discount_mtokens: '8000',
396
+ inbound_rate_discount: 200000,
397
+ public_key: 'c',
398
+ },
399
+ {
400
+ base_fee_mtokens: '9000',
401
+ channel: '3x3x3',
402
+ channel_capacity: 16777215,
403
+ cltv_delta: 40,
404
+ fee_rate: 100000,
405
+ inbound_base_discount_mtokens: '-2000',
406
+ inbound_rate_discount: -80000,
407
+ public_key: 'd',
408
+ },
409
+ ],
410
+ },
276
411
  ];
277
412
 
278
413
  tests.forEach(({args, description, error, expected}) => {
@@ -27,9 +27,35 @@ const tests = [
27
27
  },
28
28
  {
29
29
  args: {mtokens: '1000000', policy: {base_fee_mtokens: '1', fee_rate: 1}},
30
- description: 'Fee rate is required',
30
+ description: 'Fee is calculated',
31
31
  expected: {fee_mtokens: '2'},
32
32
  },
33
+ {
34
+ args: {
35
+ mtokens: '1000000',
36
+ policy: {
37
+ base_fee_mtokens: '1',
38
+ fee_rate: 1,
39
+ inbound_base_discount_mtokens: '-1',
40
+ inbound_rate_discount: -1,
41
+ },
42
+ },
43
+ description: 'Fee rate with discount is calculated',
44
+ expected: {fee_mtokens: '0'},
45
+ },
46
+ {
47
+ args: {
48
+ mtokens: '1000000',
49
+ policy: {
50
+ base_fee_mtokens: '1',
51
+ fee_rate: 1,
52
+ inbound_base_discount_mtokens: '-10',
53
+ inbound_rate_discount: -1,
54
+ },
55
+ },
56
+ description: 'Fee rate with big discount is calculated',
57
+ expected: {fee_mtokens: '0'},
58
+ },
33
59
  ];
34
60
 
35
61
  tests.forEach(({args, description, error, expected}) => {