bolt07 1.8.3 → 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,6 +1,11 @@
1
1
  # Versions
2
2
 
3
- ## 1.8.3
3
+ ## 1.9.0
4
+
5
+ - `hopsFromChannels`, `routeFromChannels`, `routeFromHops`: Add support for
6
+ inbound discounts
7
+
8
+ ## 1.8.4
4
9
 
5
10
  - `decodeSocket`: Decode a connection socket from hex data
6
11
  - `encodeSocket`: Encode a connection socket to hex data
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2018 Alex Bosworth
3
+ Copyright (c) 2018-2023 Alex Bosworth
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -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
@@ -10,9 +10,6 @@
10
10
  "bn.js": "5.2.1"
11
11
  },
12
12
  "description": "Utilities for working with bolt07 data formats",
13
- "devDependencies": {
14
- "@alexbosworth/tap": "15.0.12"
15
- },
16
13
  "keywords": [
17
14
  "bolt",
18
15
  "channel-id",
@@ -29,7 +26,7 @@
29
26
  "url": "https://github.com/alexbosworth/bolt07.git"
30
27
  },
31
28
  "scripts": {
32
- "test": "tap --branches=1 --functions=1 --lines=1 --statements=1 test/addresses/*.js test/ids/*.js test/routing/*.js"
29
+ "test": "npx nyc@15.1 node --experimental-test-coverage --test"
33
30
  },
34
- "version": "1.8.3"
31
+ "version": "1.9.0"
35
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>
@@ -58,15 +60,13 @@ const minFee = 0;
58
60
  }
59
61
  */
60
62
  module.exports = args => {
61
- const {height, hops, mtokens} = args;
62
-
63
63
  const finalCltvDelta = args.cltv_delta || defaultCltvBuffer;
64
64
 
65
- if (height === undefined) {
65
+ if (args.height === undefined) {
66
66
  throw new Error('ExpectedChainHeightForRoute');
67
67
  }
68
68
 
69
- if (!isArray(hops) || !hops.length) {
69
+ if (!isArray(args.hops) || !args.hops.length) {
70
70
  throw new Error('ExpectedHopsToConstructRouteFrom');
71
71
  }
72
72
 
@@ -74,12 +74,12 @@ module.exports = args => {
74
74
  throw new Error('ExpectedInitialCltvDeltaToConstructRouteFromHops');
75
75
  }
76
76
 
77
- if (!mtokens) {
77
+ if (!args.mtokens) {
78
78
  throw new Error('ExpectedMillitokensToSendAcrossHops');
79
79
  }
80
80
 
81
81
  // Check hops for validity
82
- hops.forEach((hop, i) => {
82
+ args.hops.forEach((hop, i) => {
83
83
  if (hop.base_fee_mtokens === undefined) {
84
84
  throw new Error('ExpectedHopBaseFeeMillitokensForRouteConstruction');
85
85
  }
@@ -103,12 +103,12 @@ module.exports = args => {
103
103
  return;
104
104
  });
105
105
 
106
- let forwardMtokens = BigInt(mtokens);
107
- const [firstHop] = hops.slice();
108
- let timeoutHeight = height + finalCltvDelta;
106
+ let forwardMtokens = BigInt(args.mtokens);
107
+ const [firstHop] = args.hops.slice();
108
+ let timeoutHeight = args.height + finalCltvDelta;
109
109
 
110
110
  // To construct the route, we need to go backwards from the end
111
- const backwardsPath = hops.slice().reverse().map((hop, i, hops) => {
111
+ const backwardsPath = args.hops.slice().reverse().map((hop, i, hops) => {
112
112
  let feeMtokens = BigInt(minFee);
113
113
 
114
114
  if (!!i) {
@@ -138,9 +138,9 @@ module.exports = args => {
138
138
  .map(n => BigInt(n.fee_mtokens))
139
139
  .reduce((sum, n) => sum + n, BigInt(minFee));
140
140
 
141
- const totalMtokens = totalFeeMtokens + BigInt(mtokens);
141
+ const totalMtokens = totalFeeMtokens + BigInt(args.mtokens);
142
142
 
143
- if (hops.length === 1) {
143
+ if (args.hops.length === 1) {
144
144
  timeoutHeight -= args.initial_cltv;
145
145
  }
146
146
 
@@ -1,4 +1,6 @@
1
- const {test} = require('@alexbosworth/tap');
1
+ const strictSame = require('node:assert').strict.deepStrictEqual;
2
+ const test = require('node:test');
3
+ const {throws} = require('node:assert').strict;
2
4
 
3
5
  const {decodeSocket} = require('./../../');
4
6
 
@@ -53,7 +55,7 @@ const tests = [
53
55
  ];
54
56
 
55
57
  tests.forEach(({args, description, error, expected}) => {
56
- return test(description, ({end, strictSame, throws}) => {
58
+ return test(description, (t, end) => {
57
59
  if (!!error) {
58
60
  throws(() => decodeSocket(args), new Error(error), 'Got expected error');
59
61
  } else {
@@ -1,4 +1,6 @@
1
- const {test} = require('@alexbosworth/tap');
1
+ const strictSame = require('node:assert').strict.deepStrictEqual;
2
+ const test = require('node:test');
3
+ const {throws} = require('node:assert').strict;
2
4
 
3
5
  const encodeBase32 = require('./../../addresses/encode_base32');
4
6
 
@@ -25,7 +27,7 @@ const tests = [
25
27
  ];
26
28
 
27
29
  tests.forEach(({args, description, error, expected}) => {
28
- return test(description, ({end, strictSame, throws}) => {
30
+ return test(description, (t, end) => {
29
31
  if (!!error) {
30
32
  throws(() => encodeBase32(args), new Error(error), 'Got expected error');
31
33
  } else {
@@ -1,4 +1,6 @@
1
- const {test} = require('@alexbosworth/tap');
1
+ const strictSame = require('node:assert').strict.deepStrictEqual;
2
+ const test = require('node:test');
3
+ const {throws} = require('node:assert').strict;
2
4
 
3
5
  const {encodeSocket} = require('./../../');
4
6
 
@@ -40,7 +42,7 @@ const tests = [
40
42
  ];
41
43
 
42
44
  tests.forEach(({args, description, error, expected}) => {
43
- return test(description, ({end, strictSame, throws}) => {
45
+ return test(description, (t, end) => {
44
46
  if (!!error) {
45
47
  throws(() => encodeSocket(args), new Error(error), 'Got expected error');
46
48
  } else {
@@ -1,4 +1,6 @@
1
- const {test} = require('@alexbosworth/tap');
1
+ const strictSame = require('node:assert').strict.deepStrictEqual;
2
+ const test = require('node:test');
3
+ const {throws} = require('node:assert').strict;
2
4
 
3
5
  const {chanFormat} = require('./../../');
4
6
 
@@ -36,7 +38,7 @@ const tests = [
36
38
  ];
37
39
 
38
40
  tests.forEach(({args, description, error, expected}) => {
39
- return test(description, ({end, equal, throws}) => {
41
+ return test(description, (t, end) => {
40
42
  if (!!error) {
41
43
  throws(() => chanFormat(args), new Error(error), 'Got expected error');
42
44
 
@@ -45,7 +47,7 @@ tests.forEach(({args, description, error, expected}) => {
45
47
 
46
48
  const {channel} = chanFormat(args);
47
49
 
48
- equal(channel, expected.channel, 'Channel formatted returned');
50
+ strictSame(channel, expected.channel, 'Channel formatted returned');
49
51
 
50
52
  return end();
51
53
  });
@@ -1,4 +1,6 @@
1
- const {test} = require('@alexbosworth/tap');
1
+ const strictSame = require('node:assert').strict.deepStrictEqual;
2
+ const test = require('node:test');
3
+ const {throws} = require('node:assert').strict;
2
4
 
3
5
  const {chanNumber} = require('./../../');
4
6
 
@@ -36,7 +38,7 @@ const tests = [
36
38
  ];
37
39
 
38
40
  tests.forEach(({args, description, error, expected}) => {
39
- return test(description, ({end, equal, throws}) => {
41
+ return test(description, (t, end) => {
40
42
  if (!!error) {
41
43
  throws(() => chanNumber(args), new Error(error), 'Got expected error');
42
44
 
@@ -45,7 +47,7 @@ tests.forEach(({args, description, error, expected}) => {
45
47
 
46
48
  const {number} = chanNumber(args);
47
49
 
48
- equal(number, expected.number, 'Channel id number returned');
50
+ strictSame(number, expected.number, 'Channel id number returned');
49
51
 
50
52
  return end();
51
53
  });
@@ -1,4 +1,5 @@
1
- const {test} = require('@alexbosworth/tap');
1
+ const test = require('node:test');
2
+ const {throws} = require('node:assert').strict;
2
3
 
3
4
  const componentsFromBuffer = require('./../../ids/components_from_buffer');
4
5
 
@@ -16,7 +17,7 @@ const tests = [
16
17
  ];
17
18
 
18
19
  tests.forEach(({args, description, error, expected}) => {
19
- return test(description, ({end, equal, throws}) => {
20
+ return test(description, (t, end) => {
20
21
  if (!!error) {
21
22
  throws(() => componentsFromBuffer(args), new Error(error), 'Got error');
22
23
 
@@ -1,4 +1,6 @@
1
- const {test} = require('@alexbosworth/tap');
1
+ const strictSame = require('node:assert').strict.deepStrictEqual;
2
+ const test = require('node:test');
3
+ const {throws} = require('node:assert').strict;
2
4
 
3
5
  const {decodeChanId} = require('./../../');
4
6
 
@@ -51,7 +53,7 @@ const tests = [
51
53
  ];
52
54
 
53
55
  tests.forEach(({args, description, error, expected}) => {
54
- return test(description, ({equal, end, throws}) => {
56
+ return test(description, (t, end) => {
55
57
  if (!!error) {
56
58
  throws(() => decodeChanId(args), new Error(error), 'Got expected err');
57
59
 
@@ -60,9 +62,9 @@ tests.forEach(({args, description, error, expected}) => {
60
62
 
61
63
  const decoded = decodeChanId(args);
62
64
 
63
- equal(decoded.block_height, expected.block_height, 'Block height derived');
64
- equal(decoded.block_index, expected.block_index, 'Block index derived');
65
- equal(decoded.output_index, expected.output_index, 'Output index derived');
65
+ strictSame(decoded.block_height, expected.block_height, 'Block height');
66
+ strictSame(decoded.block_index, expected.block_index, 'Block index');
67
+ strictSame(decoded.output_index, expected.output_index, 'Output index');
66
68
 
67
69
  return end();
68
70
  });
@@ -1,4 +1,6 @@
1
- const {test} = require('@alexbosworth/tap');
1
+ const strictSame = require('node:assert').strict.deepStrictEqual;
2
+ const test = require('node:test');
3
+ const {throws} = require('node:assert').strict;
2
4
 
3
5
  const {encodeChanId} = require('./../../');
4
6
 
@@ -48,7 +50,7 @@ const tests = [
48
50
  ];
49
51
 
50
52
  tests.forEach(({args, description, error, expected}) => {
51
- return test(description, ({equal, end, throws}) => {
53
+ return test(description, (t, end) => {
52
54
  if (!!error) {
53
55
  throws(() => encodeChanId(args), new Error(error), 'Got expected err');
54
56
 
@@ -57,9 +59,9 @@ tests.forEach(({args, description, error, expected}) => {
57
59
 
58
60
  const encoded = encodeChanId(args);
59
61
 
60
- equal(encoded.channel, expected.channel, 'Channel components returned');
61
- equal(encoded.id, expected.id, 'Channel id returned');
62
- equal(encoded.number, expected.number, 'Channel number returned');
62
+ strictSame(encoded.channel, expected.channel, 'Channel components');
63
+ strictSame(encoded.id, expected.id, 'Channel id returned');
64
+ strictSame(encoded.number, expected.number, 'Channel number returned');
63
65
 
64
66
  return end();
65
67
  });
@@ -1,4 +1,6 @@
1
- const {test} = require('@alexbosworth/tap');
1
+ const strictSame = require('node:assert').strict.deepStrictEqual;
2
+ const test = require('node:test');
3
+ const {throws} = require('node:assert').strict;
2
4
 
3
5
  const {rawChanId} = require('./../../');
4
6
 
@@ -36,7 +38,7 @@ const tests = [
36
38
  ];
37
39
 
38
40
  tests.forEach(({args, description, error, expected}) => {
39
- return test(description, ({end, equal, throws}) => {
41
+ return test(description, (t, end) => {
40
42
  if (!!error) {
41
43
  throws(() => rawChanId(args), new Error(error), 'Got expected error');
42
44
 
@@ -45,7 +47,7 @@ tests.forEach(({args, description, error, expected}) => {
45
47
 
46
48
  const {id} = rawChanId(args);
47
49
 
48
- equal(id, expected.id, 'Raw channel id returned');
50
+ strictSame(id, expected.id, 'Raw channel id returned');
49
51
 
50
52
  return end();
51
53
  });
@@ -1,4 +1,6 @@
1
- const {test} = require('@alexbosworth/tap');
1
+ const strictSame = require('node:assert').strict.deepStrictEqual;
2
+ const test = require('node:test');
3
+ const {throws} = require('node:assert').strict;
2
4
 
3
5
  const betaChannels = require('./../fixtures/graph_beta').channels;
4
6
  const charlieChannels = require('./../fixtures/graph_charlie').channels;
@@ -108,6 +110,8 @@ const tests = [
108
110
  channel_capacity: 16777215,
109
111
  cltv_delta: 40,
110
112
  fee_rate: 2500,
113
+ inbound_base_discount_mtokens: undefined,
114
+ inbound_rate_discount: undefined,
111
115
  public_key: 'b',
112
116
  },
113
117
  {
@@ -116,6 +120,8 @@ const tests = [
116
120
  channel_capacity: 16777215,
117
121
  cltv_delta: 30,
118
122
  fee_rate: 2500,
123
+ inbound_base_discount_mtokens: undefined,
124
+ inbound_rate_discount: undefined,
119
125
  public_key: 'c',
120
126
  },
121
127
  {
@@ -124,6 +130,8 @@ const tests = [
124
130
  channel_capacity: 16777215,
125
131
  cltv_delta: 144,
126
132
  fee_rate: 1,
133
+ inbound_base_discount_mtokens: undefined,
134
+ inbound_rate_discount: undefined,
127
135
  public_key: 'd',
128
136
  },
129
137
  {
@@ -132,6 +140,8 @@ const tests = [
132
140
  channel_capacity: 16777215,
133
141
  cltv_delta: 144,
134
142
  fee_rate: 1,
143
+ inbound_base_discount_mtokens: undefined,
144
+ inbound_rate_discount: undefined,
135
145
  public_key: 'e',
136
146
  },
137
147
  ],
@@ -149,6 +159,8 @@ const tests = [
149
159
  channel_capacity: 8429350,
150
160
  cltv_delta: 40,
151
161
  fee_rate: 2500,
162
+ inbound_base_discount_mtokens: undefined,
163
+ inbound_rate_discount: undefined,
152
164
  public_key: '03e50492eab4107a773141bb419e107bda3de3d55652e6e1a41225f06a0bbf2d56',
153
165
  },
154
166
  {
@@ -157,6 +169,8 @@ const tests = [
157
169
  channel_capacity: 2000000,
158
170
  cltv_delta: 40,
159
171
  fee_rate: 2500,
172
+ inbound_base_discount_mtokens: undefined,
173
+ inbound_rate_discount: undefined,
160
174
  public_key: '03bb88ccc444534da7b5b64b4f7b15e1eccb18e102db0e400d4b9cfe93763aa26d',
161
175
  },
162
176
  {
@@ -165,6 +179,8 @@ const tests = [
165
179
  channel_capacity: 400000,
166
180
  cltv_delta: 40,
167
181
  fee_rate: 100,
182
+ inbound_base_discount_mtokens: undefined,
183
+ inbound_rate_discount: undefined,
168
184
  public_key: '028dcc199be86786818c8c32bffe9db8855c5fca98951eec99d1fa335d841605c2',
169
185
  },
170
186
  {
@@ -173,6 +189,8 @@ const tests = [
173
189
  channel_capacity: 364355,
174
190
  cltv_delta: 40,
175
191
  fee_rate: 1,
192
+ inbound_base_discount_mtokens: undefined,
193
+ inbound_rate_discount: undefined,
176
194
  public_key: '03277a99c297a53859b42a9bb8cb2c5c17b9eaa44509bae150e2ea35ca5aa29bd9',
177
195
  },
178
196
  ],
@@ -187,6 +205,8 @@ const tests = [
187
205
  channel_capacity: 1000,
188
206
  cltv_delta: 40,
189
207
  fee_rate: 7,
208
+ inbound_base_discount_mtokens: undefined,
209
+ inbound_rate_discount: undefined,
190
210
  public_key: 'alice',
191
211
  },
192
212
  {
@@ -195,6 +215,8 @@ const tests = [
195
215
  channel_capacity: 2000,
196
216
  cltv_delta: 40,
197
217
  fee_rate: 7,
218
+ inbound_base_discount_mtokens: undefined,
219
+ inbound_rate_discount: undefined,
198
220
  public_key: 'bob',
199
221
  },
200
222
  {
@@ -203,6 +225,8 @@ const tests = [
203
225
  channel_capacity: 3000,
204
226
  cltv_delta: 40,
205
227
  fee_rate: 9,
228
+ inbound_base_discount_mtokens: undefined,
229
+ inbound_rate_discount: undefined,
206
230
  public_key: 'charlie',
207
231
  },
208
232
  ],
@@ -238,6 +262,8 @@ const tests = [
238
262
  channel_capacity: 100,
239
263
  cltv_delta: 40,
240
264
  fee_rate: 1,
265
+ inbound_base_discount_mtokens: undefined,
266
+ inbound_rate_discount: undefined,
241
267
  public_key: Buffer.alloc(33).toString('hex'),
242
268
  }],
243
269
  },
@@ -271,10 +297,121 @@ const tests = [
271
297
  description: 'Mapping hops from channels requires hop channel ids',
272
298
  expected: [],
273
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
+ },
274
411
  ];
275
412
 
276
413
  tests.forEach(({args, description, error, expected}) => {
277
- return test(description, ({end, strictSame, throws}) => {
414
+ return test(description, (t, end) => {
278
415
  if (!!error) {
279
416
  throws(() => hopsFromChannels(args), new Error(error), 'Got error');
280
417
  } else {
@@ -1,4 +1,6 @@
1
- const {test} = require('@alexbosworth/tap');
1
+ const strictSame = require('node:assert').strict.deepStrictEqual;
2
+ const test = require('node:test');
3
+ const {throws} = require('node:assert').strict;
2
4
 
3
5
  const policyFee = require('./../../routing/policy_fee');
4
6
 
@@ -25,17 +27,43 @@ const tests = [
25
27
  },
26
28
  {
27
29
  args: {mtokens: '1000000', policy: {base_fee_mtokens: '1', fee_rate: 1}},
28
- description: 'Fee rate is required',
30
+ description: 'Fee is calculated',
29
31
  expected: {fee_mtokens: '2'},
30
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
+ },
31
59
  ];
32
60
 
33
61
  tests.forEach(({args, description, error, expected}) => {
34
- return test(description, ({end, equal, throws}) => {
62
+ return test(description, (t, end) => {
35
63
  if (!!error) {
36
64
  throws(() => policyFee(args), new Error(error), 'Got expected error');
37
65
  } else {
38
- equal(policyFee(args).fee_mtokens, expected.fee_mtokens, 'Got fee');
66
+ strictSame(policyFee(args).fee_mtokens, expected.fee_mtokens, 'Fee');
39
67
  }
40
68
 
41
69
  return end();
@@ -1,4 +1,6 @@
1
- const {test} = require('@alexbosworth/tap');
1
+ const strictSame = require('node:assert').strict.deepStrictEqual;
2
+ const test = require('node:test');
3
+ const {throws} = require('node:assert').strict;
2
4
 
3
5
  const {routeFromChannels} = require('./../../');
4
6
 
@@ -938,7 +940,7 @@ const tests = [
938
940
  ];
939
941
 
940
942
  tests.forEach(({args, description, error, expected}) => {
941
- return test(description, ({end, strictSame, throws}) => {
943
+ return test(description, (t, end) => {
942
944
  if (!!error) {
943
945
  throws(() => routeFromChannels(args), new Error(error), 'Got error');
944
946
  } else {
@@ -1,4 +1,6 @@
1
- const {test} = require('@alexbosworth/tap');
1
+ const strictSame = require('node:assert').strict.deepStrictEqual;
2
+ const test = require('node:test');
3
+ const {throws} = require('node:assert').strict;
2
4
 
3
5
  const {routeFromHops} = require('./../../');
4
6
 
@@ -340,7 +342,7 @@ const tests = [
340
342
  ];
341
343
 
342
344
  tests.forEach(({args, description, error, expected}) => {
343
- return test(description, ({end, strictSame, throws}) => {
345
+ return test(description, (t, end) => {
344
346
  if (!!error) {
345
347
  throws(() => routeFromHops(args), new Error(error), 'Got expected err');
346
348
  } else {