paid-services 3.2.0 → 3.3.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 +4 -0
- package/capacity/accept_capacity_change.js +284 -0
- package/capacity/ask_for_change_details.js +505 -0
- package/capacity/ask_for_decrease.js +185 -0
- package/capacity/assemble_replacement_tx.js +171 -0
- package/capacity/capacity_change_requests.js +76 -0
- package/capacity/change_channel_capacity.js +183 -0
- package/capacity/encode_change_request.js +55 -0
- package/capacity/encode_sign_capacity_response.js +32 -0
- package/capacity/fee_for_replacement.js +108 -0
- package/capacity/finalize_capacity_replacement.js +67 -0
- package/capacity/get_capacity_change_requests.js +98 -0
- package/capacity/get_capacity_replacement.js +371 -0
- package/capacity/get_replacement_signature.js +232 -0
- package/capacity/index.js +4 -0
- package/capacity/initiate_capacity_change.js +506 -0
- package/capacity/interim_replacement_psbt.js +57 -0
- package/capacity/is_open_witness_script.js +40 -0
- package/capacity/parse_accept_request.js +58 -0
- package/capacity/parse_accept_response.js +52 -0
- package/capacity/parse_capacity_change_request.js +101 -0
- package/capacity/parse_sign_capacity_request.js +59 -0
- package/capacity/propose_capacity_change.js +361 -0
- package/capacity/service_types.json +6 -0
- package/capacity/sign_capacity_replacement.js +119 -0
- package/capacity/witness_script_from_close_txs.js +50 -0
- package/index.js +2 -0
- package/p2p/encode_peer_response.js +0 -1
- package/p2p/make_peer_request.js +3 -3
- package/package.json +6 -4
- package/test/capacity/test_assemble_replacement_tx.js +46 -0
- package/test/capacity/test_capacity_change_requests.js +54 -0
- package/test/capacity/test_encode_change_request.js +49 -0
- package/test/capacity/test_encode_sign_capacity_response.js +47 -0
- package/test/capacity/test_fee_for_replacement.js +40 -0
- package/test/capacity/test_finalize_capacity_replacement.js +45 -0
- package/test/capacity/test_interim_replacement_psbt.js +44 -0
- package/test/capacity/test_is_open_witness_script.js +40 -0
- package/test/capacity/test_parse_accept_request.js +42 -0
- package/test/capacity/test_parse_capacity_change_request.js +51 -0
- package/test/capacity/test_parse_sign_capacity_request.js +49 -0
- package/test/capacity/test_witness_script_from_close_txs.js +53 -0
- package/test/integration/test_accept_capacity_change.js +152 -0
- package/test/integration/test_change_channel_capacity.js +196 -0
- package/test/integration/test_decrease_channel_capacity.js +206 -0
- package/test/integration/test_increase_channel_capacity.js +197 -0
- package/test/integration/test_sign_capacity_replacement.js +142 -0
- package/test/p2p/test_encode_peer_request.js +53 -0
- package/test/p2p/test_encode_peer_response.js +38 -0
- package/test/p2p/test_encode_response_code.js +48 -0
- package/trades/network_from_network_record.js +6 -0
- package/trades/network_record_from_request.js +5 -0
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
const {address} = require('bitcoinjs-lib');
|
|
2
|
+
const asyncAuto = require('async/auto');
|
|
3
|
+
const asyncMap = require('async/map');
|
|
4
|
+
const asyncRetry = require('async/retry');
|
|
5
|
+
const {broadcastChainTransaction} = require('ln-service');
|
|
6
|
+
const {closeChannel} = require('ln-service');
|
|
7
|
+
const {createChainAddress} = require('ln-service');
|
|
8
|
+
const {getChainTransactions} = require('ln-service');
|
|
9
|
+
const {getChannel} = require('ln-service');
|
|
10
|
+
const {getChannels} = require('ln-service');
|
|
11
|
+
const {getNetwork} = require('ln-sync');
|
|
12
|
+
const {networks} = require('bitcoinjs-lib');
|
|
13
|
+
const {openChannel} = require('ln-service');
|
|
14
|
+
const {spawnLightningCluster} = require('ln-docker-daemons');
|
|
15
|
+
const {test} = require('@alexbosworth/tap');
|
|
16
|
+
const {Transaction} = require('bitcoinjs-lib');
|
|
17
|
+
|
|
18
|
+
const {changeChannelCapacity} = require('./../../capacity');
|
|
19
|
+
const {getCapacityChangeRequests} = require('./../../capacity');
|
|
20
|
+
|
|
21
|
+
const bufferAsHex = buffer => buffer.toString('hex');
|
|
22
|
+
const capacity = 1e6;
|
|
23
|
+
const {fromHex} = Transaction;
|
|
24
|
+
const id = Buffer.alloc(32).toString('hex');
|
|
25
|
+
const interval = 10;
|
|
26
|
+
const logger = {error: () => {}, info: () => {}};
|
|
27
|
+
const maturity = 100;
|
|
28
|
+
const size = 2;
|
|
29
|
+
const sumOf = arr => arr.reduce((sum, n) => sum + n, 0);
|
|
30
|
+
const times = 2000;
|
|
31
|
+
const {toOutputScript} = address;
|
|
32
|
+
const weightAsVBytes = n => Math.ceil(n / 4);
|
|
33
|
+
|
|
34
|
+
// A capacity replacement proposal should be counter signed and accepted
|
|
35
|
+
test(`Accept capacity replacement`, async ({end, equal, strictSame}) => {
|
|
36
|
+
const {kill, nodes} = await spawnLightningCluster({size});
|
|
37
|
+
|
|
38
|
+
const [control, target] = nodes;
|
|
39
|
+
|
|
40
|
+
const {generate, lnd} = control;
|
|
41
|
+
|
|
42
|
+
const network = networks[(await getNetwork({lnd})).bitcoinjs];
|
|
43
|
+
|
|
44
|
+
// Make some funds
|
|
45
|
+
await generate({count: maturity});
|
|
46
|
+
|
|
47
|
+
try {
|
|
48
|
+
// Open up a new channel
|
|
49
|
+
const channelOpen = await openChannel({
|
|
50
|
+
lnd,
|
|
51
|
+
local_tokens: capacity,
|
|
52
|
+
partner_public_key: target.id,
|
|
53
|
+
partner_socket: target.socket,
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// Wait for the channel to be active
|
|
57
|
+
const channel = await asyncRetry({interval, times}, async () => {
|
|
58
|
+
const [channel] = (await getChannels({lnd, is_active: true})).channels;
|
|
59
|
+
|
|
60
|
+
if (!channel) {
|
|
61
|
+
await generate({});
|
|
62
|
+
|
|
63
|
+
throw new Error('ExpectedChannelActivation');
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const {policies} = await getChannel({lnd, id: channel.id});
|
|
67
|
+
|
|
68
|
+
const noPolicy = policies.find(n => !n.cltv_delta);
|
|
69
|
+
|
|
70
|
+
if (!!channel && !noPolicy) {
|
|
71
|
+
return channel;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
await generate({});
|
|
75
|
+
|
|
76
|
+
throw new Error('ExpectedChannelActivation');
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
await asyncAuto({
|
|
80
|
+
// Propose the channel
|
|
81
|
+
propose: async () => {
|
|
82
|
+
await changeChannelCapacity({
|
|
83
|
+
lnd,
|
|
84
|
+
logger,
|
|
85
|
+
ask: (args, cbk) => {
|
|
86
|
+
if (args.name === 'amount') {
|
|
87
|
+
return cbk({amount: '200000'});
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (args.name === 'direction') {
|
|
91
|
+
return cbk({direction: 'increase'});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (args.name === 'internal') {
|
|
95
|
+
return cbk({internal: true});
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (args.name === 'ok') {
|
|
99
|
+
return cbk({ok: true});
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (args.name === 'proceed') {
|
|
103
|
+
return cbk({proceed: true});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (args.name === 'rate') {
|
|
107
|
+
return cbk({rate: args.default});
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (args.name === 'query') {
|
|
111
|
+
return cbk({query: target.id});
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
throw new Error('UnexpectedQueryNameForProposingSide');
|
|
115
|
+
},
|
|
116
|
+
});
|
|
117
|
+
},
|
|
118
|
+
|
|
119
|
+
// Wait to see the inbound proposal
|
|
120
|
+
waitForProposal: async () => {
|
|
121
|
+
await asyncRetry({interval, times}, async () => {
|
|
122
|
+
const {requests} = await getCapacityChangeRequests({lnd: target.lnd});
|
|
123
|
+
|
|
124
|
+
if (!requests.length) {
|
|
125
|
+
throw new Error('FailedToFindChangeRequest');
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
},
|
|
129
|
+
|
|
130
|
+
// Accept the channel
|
|
131
|
+
accept: ['waitForProposal', async ({}) => {
|
|
132
|
+
await changeChannelCapacity({
|
|
133
|
+
logger,
|
|
134
|
+
ask: (args, cbk) => {
|
|
135
|
+
if (args.name === 'accept') {
|
|
136
|
+
return cbk({accept: true});
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (args.name === 'ok') {
|
|
140
|
+
return cbk({ok: true});
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
throw new Error('UnexpectedQueryNameForAcceptingSide');
|
|
144
|
+
},
|
|
145
|
+
lnd: target.lnd,
|
|
146
|
+
});
|
|
147
|
+
}],
|
|
148
|
+
|
|
149
|
+
// Generate to confirm the change
|
|
150
|
+
generate: ['waitForProposal', async ({}) => {
|
|
151
|
+
// Wait for the new channel to be active
|
|
152
|
+
const recreated = await asyncRetry({interval: 3000, times}, async () => {
|
|
153
|
+
const [channel] = (await getChannels({lnd, is_active: true})).channels.filter(n => n.capacity > capacity);
|
|
154
|
+
|
|
155
|
+
await generate({});
|
|
156
|
+
|
|
157
|
+
if (!channel) {
|
|
158
|
+
throw new Error('ExpectedChannelActivation');
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
{
|
|
162
|
+
const {policies} = await getChannel({lnd, id: channel.id});
|
|
163
|
+
|
|
164
|
+
const noPolicy = policies.find(n => !n.cltv_delta);
|
|
165
|
+
|
|
166
|
+
if (!!noPolicy) {
|
|
167
|
+
throw new Error('ExpectedChannelPolicy');
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
{
|
|
172
|
+
const {policies} = await getChannel({
|
|
173
|
+
lnd: target.lnd,
|
|
174
|
+
id: channel.id,
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
const noPolicy = policies.find(n => !n.cltv_delta);
|
|
178
|
+
|
|
179
|
+
if (!!noPolicy) {
|
|
180
|
+
throw new Error('ExpectedChannelPolicy');
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
return;
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
return;
|
|
188
|
+
}],
|
|
189
|
+
});
|
|
190
|
+
} catch (err) {
|
|
191
|
+
strictSame(err, null, 'Expected no failure');
|
|
192
|
+
} finally {
|
|
193
|
+
await kill({});
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return end();
|
|
197
|
+
});
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
const {address} = require('bitcoinjs-lib');
|
|
2
|
+
const asyncMap = require('async/map');
|
|
3
|
+
const asyncRetry = require('async/retry');
|
|
4
|
+
const {broadcastChainTransaction} = require('ln-service');
|
|
5
|
+
const {closeChannel} = require('ln-service');
|
|
6
|
+
const {createChainAddress} = require('ln-service');
|
|
7
|
+
const {getChainTransactions} = require('ln-service');
|
|
8
|
+
const {getChannels} = require('ln-service');
|
|
9
|
+
const {networks} = require('bitcoinjs-lib');
|
|
10
|
+
const {openChannel} = require('ln-service');
|
|
11
|
+
const {spawnLightningCluster} = require('ln-docker-daemons');
|
|
12
|
+
const {test} = require('@alexbosworth/tap');
|
|
13
|
+
const {Transaction} = require('bitcoinjs-lib');
|
|
14
|
+
|
|
15
|
+
const finalize = require('./../../capacity/finalize_capacity_replacement');
|
|
16
|
+
const method = require('./../../capacity/sign_capacity_replacement');
|
|
17
|
+
|
|
18
|
+
const bufferAsHex = buffer => buffer.toString('hex');
|
|
19
|
+
const capacity = 1e6;
|
|
20
|
+
const finalizeCapacityReplacement = finalize;
|
|
21
|
+
const {fromHex} = Transaction;
|
|
22
|
+
const interval = 10;
|
|
23
|
+
const maturity = 100;
|
|
24
|
+
const network = networks.regtest;
|
|
25
|
+
const sequence = 0;
|
|
26
|
+
const signCapacityReplacement = method;
|
|
27
|
+
const size = 2;
|
|
28
|
+
const sumOf = arr => arr.reduce((sum, n) => sum + n, 0);
|
|
29
|
+
const times = 2000;
|
|
30
|
+
const {toOutputScript} = address;
|
|
31
|
+
const weightAsVBytes = n => Math.ceil(n / 4);
|
|
32
|
+
|
|
33
|
+
// Signing a capacity replacement transaction should result in a valid sig
|
|
34
|
+
test(`Sign capacity replacement`, async ({end, equal, strictSame}) => {
|
|
35
|
+
const {kill, nodes} = await spawnLightningCluster({size});
|
|
36
|
+
|
|
37
|
+
const [{generate, lnd}, target] = nodes;
|
|
38
|
+
|
|
39
|
+
await generate({count: maturity});
|
|
40
|
+
|
|
41
|
+
try {
|
|
42
|
+
// Open up a new channel
|
|
43
|
+
const channelOpen = await openChannel({
|
|
44
|
+
lnd,
|
|
45
|
+
local_tokens: capacity,
|
|
46
|
+
partner_public_key: target.id,
|
|
47
|
+
partner_socket: target.socket,
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
// Wait for the channel to be active
|
|
51
|
+
const channel = await asyncRetry({interval, times}, async () => {
|
|
52
|
+
const [channel] = (await getChannels({lnd, is_active: true})).channels;
|
|
53
|
+
|
|
54
|
+
if (!!channel) {
|
|
55
|
+
return channel;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
await generate({});
|
|
59
|
+
|
|
60
|
+
throw new Error('ExpectedChannelActivation');
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
// Find the open tx
|
|
64
|
+
const tx = (await getChainTransactions({lnd})).transactions.find(tx => {
|
|
65
|
+
return tx.id === channel.transaction_id;
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
// Get the open tx output
|
|
69
|
+
const output = fromHex(tx.transaction).outs[channel.transaction_vout];
|
|
70
|
+
|
|
71
|
+
// Close the channel
|
|
72
|
+
const channelClose = await closeChannel({
|
|
73
|
+
lnd,
|
|
74
|
+
id: channel.id,
|
|
75
|
+
is_force_close: true,
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// Find the open tx
|
|
79
|
+
const endTx = (await getChainTransactions({lnd})).transactions.find(tx => {
|
|
80
|
+
return tx.id === channelClose.transaction_id;
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
// Get the witness spending the channel funds
|
|
84
|
+
const [{witness}] = fromHex(endTx.transaction).ins;
|
|
85
|
+
|
|
86
|
+
const replacement = new Transaction();
|
|
87
|
+
|
|
88
|
+
const openTxHash = fromHex(tx.transaction).getHash();
|
|
89
|
+
|
|
90
|
+
replacement.addInput(openTxHash, channel.transaction_vout, sequence);
|
|
91
|
+
|
|
92
|
+
const spendIdx = replacement.ins.findIndex(n => n.hash.equals(openTxHash));
|
|
93
|
+
|
|
94
|
+
const fee = sumOf([
|
|
95
|
+
channel.commit_transaction_fee,
|
|
96
|
+
weightAsVBytes(channel.commit_transaction_weight),
|
|
97
|
+
]);
|
|
98
|
+
|
|
99
|
+
replacement.addOutput(
|
|
100
|
+
toOutputScript((await createChainAddress({lnd})).address, network),
|
|
101
|
+
channel.capacity - fee,
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
// Gather the replacement signatures
|
|
105
|
+
const [local, remote] = await asyncMap([lnd, target.lnd], async lnd => {
|
|
106
|
+
return await signCapacityReplacement({
|
|
107
|
+
lnd,
|
|
108
|
+
capacity: channel.capacity,
|
|
109
|
+
output: bufferAsHex(output.script),
|
|
110
|
+
script: bufferAsHex(witness.slice().pop()),
|
|
111
|
+
transaction: replacement.toHex(),
|
|
112
|
+
vin: replacement.ins.findIndex(n => n.hash.equals(openTxHash)),
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
// Add the signature to the replacement transaction
|
|
117
|
+
const {transaction} = finalizeCapacityReplacement({
|
|
118
|
+
local_public_key: local.key,
|
|
119
|
+
local_signature: local.signature,
|
|
120
|
+
funding_spend_vin: spendIdx,
|
|
121
|
+
remote_signature: remote.signature,
|
|
122
|
+
transaction: replacement.toHex(),
|
|
123
|
+
witness_script: bufferAsHex(witness.slice().pop()),
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
await broadcastChainTransaction({transaction, lnd});
|
|
127
|
+
|
|
128
|
+
await generate({count: maturity});
|
|
129
|
+
|
|
130
|
+
const done = (await getChainTransactions({lnd})).transactions.find(tx => {
|
|
131
|
+
return tx.id === fromHex(transaction).getId();
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
strictSame(done.is_confirmed, true, 'Signed replacement is confirmed');
|
|
135
|
+
} catch (err) {
|
|
136
|
+
strictSame(err, null, 'Expected no failure');
|
|
137
|
+
} finally {
|
|
138
|
+
await kill({});
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return end();
|
|
142
|
+
});
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
const {test} = require('@alexbosworth/tap');
|
|
2
|
+
|
|
3
|
+
const method = require('./../../p2p/encode_peer_request');
|
|
4
|
+
|
|
5
|
+
const makeArgs = overrides => {
|
|
6
|
+
const args = {id: '00', type: '0'};
|
|
7
|
+
|
|
8
|
+
Object.keys(overrides).forEach(k => args[k] = overrides[k]);
|
|
9
|
+
|
|
10
|
+
return args;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const tests = [
|
|
14
|
+
{
|
|
15
|
+
args: makeArgs({id: undefined}),
|
|
16
|
+
description: 'A request id is required',
|
|
17
|
+
error: 'ExpectedRequestIdHexStringToEncodePeerRequest',
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
args: makeArgs({records: '00'}),
|
|
21
|
+
description: 'Records array is required',
|
|
22
|
+
error: 'ExpectedRecordsArrayToEncodePeerRequest',
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
args: makeArgs({type: undefined}),
|
|
26
|
+
description: 'A type is required',
|
|
27
|
+
error: 'ExpectedRequestTypeToEncodePeerRequest',
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
args: makeArgs({}),
|
|
31
|
+
description: 'Peer request is encoded',
|
|
32
|
+
expected: {message: '626f73ff010100030100'},
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
args: makeArgs({records: [{type: '0', value: '00'}]}),
|
|
36
|
+
description: 'Peer request with records is encoded',
|
|
37
|
+
expected: {message: '626f73ff0101000301000503000100'},
|
|
38
|
+
},
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
tests.forEach(({args, description, error, expected}) => {
|
|
42
|
+
return test(description, async ({end, strictSame, throws}) => {
|
|
43
|
+
if (!!error) {
|
|
44
|
+
throws(() => method(args), new Error(error), 'Got error');
|
|
45
|
+
} else {
|
|
46
|
+
const res = method(args);
|
|
47
|
+
|
|
48
|
+
strictSame(res, expected, 'Got expected result');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return end();
|
|
52
|
+
});
|
|
53
|
+
});
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
const {test} = require('@alexbosworth/tap');
|
|
2
|
+
|
|
3
|
+
const method = require('./../../p2p/encode_peer_response');
|
|
4
|
+
|
|
5
|
+
const makeArgs = overrides => {
|
|
6
|
+
const args = {id: '00'};
|
|
7
|
+
|
|
8
|
+
Object.keys(overrides).forEach(k => args[k] = overrides[k]);
|
|
9
|
+
|
|
10
|
+
return args;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const tests = [
|
|
14
|
+
{
|
|
15
|
+
args: makeArgs({}),
|
|
16
|
+
description: 'Peer response is encoded',
|
|
17
|
+
expected: {message: '626f73ff01010002030001c8'},
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
args: makeArgs({records: [{type: '0', value: '00'}]}),
|
|
21
|
+
description: 'Peer response with records is encoded',
|
|
22
|
+
expected: {message: '626f73ff01010002030001c80503000100'},
|
|
23
|
+
},
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
tests.forEach(({args, description, error, expected}) => {
|
|
27
|
+
return test(description, async ({end, strictSame, throws}) => {
|
|
28
|
+
if (!!error) {
|
|
29
|
+
throws(() => method(args), new Error(error), 'Got error');
|
|
30
|
+
} else {
|
|
31
|
+
const res = method(args);
|
|
32
|
+
|
|
33
|
+
strictSame(res, expected, 'Got expected result');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return end();
|
|
37
|
+
});
|
|
38
|
+
});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
const {test} = require('@alexbosworth/tap');
|
|
2
|
+
|
|
3
|
+
const method = require('./../../p2p/encode_response_code');
|
|
4
|
+
|
|
5
|
+
const makeArgs = overrides => {
|
|
6
|
+
const args = {};
|
|
7
|
+
|
|
8
|
+
Object.keys(overrides).forEach(k => args[k] = overrides[k]);
|
|
9
|
+
|
|
10
|
+
return args;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const tests = [
|
|
14
|
+
{
|
|
15
|
+
args: makeArgs({failure: '00'}),
|
|
16
|
+
description: 'A failure array is expected',
|
|
17
|
+
error: 'ExpectedFailureArrayToEncodeResponseCode',
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
args: makeArgs({failure: []}),
|
|
21
|
+
description: 'A failure code is expected',
|
|
22
|
+
error: 'ExpectedErrorCodeToEncodeResponseCode',
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
args: makeArgs({}),
|
|
26
|
+
description: 'Encode response code',
|
|
27
|
+
expected: {encoded: '0001c8'},
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
args: makeArgs({failure: [400, 'Failure']}),
|
|
31
|
+
description: 'Encode failure code',
|
|
32
|
+
expected: {encoded: '0003fd019001074661696c757265'},
|
|
33
|
+
},
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
tests.forEach(({args, description, error, expected}) => {
|
|
37
|
+
return test(description, async ({end, strictSame, throws}) => {
|
|
38
|
+
if (!!error) {
|
|
39
|
+
throws(() => method(args), new Error(error), 'Got error');
|
|
40
|
+
} else {
|
|
41
|
+
const res = method(args);
|
|
42
|
+
|
|
43
|
+
strictSame(res, expected, 'Got expected result');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return end();
|
|
47
|
+
});
|
|
48
|
+
});
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
const defaultNetwork = 'bitcoin';
|
|
2
|
+
const regtestNetwork = 'regtest';
|
|
3
|
+
const regtestNetworkType = '02';
|
|
2
4
|
const testnetNetwork = 'testnet';
|
|
3
5
|
const testnetNetworkType = '01';
|
|
4
6
|
|
|
@@ -18,6 +20,10 @@ module.exports = ({value}) => {
|
|
|
18
20
|
return defaultNetwork;
|
|
19
21
|
}
|
|
20
22
|
|
|
23
|
+
if (value === regtestNetworkType) {
|
|
24
|
+
return regtestNetwork;
|
|
25
|
+
}
|
|
26
|
+
|
|
21
27
|
if (value === testnetNetworkType) {
|
|
22
28
|
return testnetNetwork;
|
|
23
29
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const defaultNetwork = 'lnbc';
|
|
2
|
+
const regtestNetwork = 'lnbcrt';
|
|
2
3
|
const testnetNetwork = 'lntb';
|
|
3
4
|
const testnetNetworkType = '01';
|
|
4
5
|
|
|
@@ -22,6 +23,10 @@ module.exports = ({request}) => {
|
|
|
22
23
|
return {};
|
|
23
24
|
}
|
|
24
25
|
|
|
26
|
+
if (request.startsWith(regtestNetwork)) {
|
|
27
|
+
return {};
|
|
28
|
+
}
|
|
29
|
+
|
|
25
30
|
if (request.startsWith(testnetNetwork)) {
|
|
26
31
|
return {value: testnetNetworkType};
|
|
27
32
|
}
|