paid-services 3.3.0 → 3.4.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 +5 -0
- package/capacity/accept_capacity_change.js +3 -3
- package/capacity/get_capacity_change_requests.js +1 -1
- package/capacity/get_capacity_replacement.js +1 -1
- package/capacity/initiate_capacity_change.js +5 -4
- package/capacity/propose_capacity_change.js +3 -1
- package/p2p/service_peer_requests.js +10 -2
- package/package.json +3 -2
- package/service_types.json +16 -0
- package/test/integration/test_accept_capacity_change.js +50 -13
- package/test/integration/test_change_channel_capacity.js +3 -0
- package/test/trades/test_decode_basic_trade.js +40 -0
- package/test/trades/test_decode_open_trade.js +50 -0
- package/test/trades/test_encode_open_trade.js +35 -0
- package/test/trades/test_encode_trade.js +37 -0
- package/trades/accept_trade.js +52 -0
- package/trades/create_trade.js +124 -44
- package/trades/decode_basic_trade.js +45 -0
- package/trades/decode_open_trade.js +69 -0
- package/trades/decode_trade.js +48 -66
- package/trades/decode_trade_secret.js +89 -0
- package/trades/encode_open_trade.js +89 -0
- package/trades/encode_trade.js +48 -33
- package/trades/encode_trade_secret.js +50 -0
- package/trades/finalize_trade_secret.js +116 -0
- package/trades/find_trade.js +314 -0
- package/trades/manage_trade.js +46 -35
- package/trades/network_from_network_record.js +3 -3
- package/trades/network_record_from_network.js +36 -0
- package/trades/network_record_from_request.js +2 -1
- package/trades/node_as_record.js +98 -0
- package/trades/record_as_node.js +113 -0
- package/trades/request_trade_by_id.js +89 -0
- package/trades/service_trade_requests.js +184 -0
- package/capacity/service_types.json +0 -6
package/trades/manage_trade.js
CHANGED
|
@@ -11,6 +11,7 @@ const {returnResult} = require('asyncjs-util');
|
|
|
11
11
|
const buyPreimage = require('./buy_preimage');
|
|
12
12
|
const decodeTrade = require('./decode_trade');
|
|
13
13
|
const decryptTradeSecret = require('./decrypt_trade_secret');
|
|
14
|
+
const findTrade = require('./find_trade');
|
|
14
15
|
|
|
15
16
|
const hexAsUtf8 = hex => Buffer.from(hex, 'hex').toString();
|
|
16
17
|
const {isArray} = Array;
|
|
@@ -52,13 +53,7 @@ module.exports = ({ask, lnd, logger}, cbk) => {
|
|
|
52
53
|
name: 'trade',
|
|
53
54
|
message: 'Enter encoded trade',
|
|
54
55
|
type: 'input',
|
|
55
|
-
validate: input =>
|
|
56
|
-
if (!input) {
|
|
57
|
-
return false;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return true;
|
|
61
|
-
},
|
|
56
|
+
validate: input => !!input,
|
|
62
57
|
},
|
|
63
58
|
cbk);
|
|
64
59
|
}],
|
|
@@ -71,22 +66,43 @@ module.exports = ({ask, lnd, logger}, cbk) => {
|
|
|
71
66
|
try {
|
|
72
67
|
const details = decodeTrade({trade: askForTrade.trade});
|
|
73
68
|
|
|
74
|
-
return cbk(null,
|
|
75
|
-
auth: details.auth,
|
|
76
|
-
payload: details.payload,
|
|
77
|
-
request: details.request,
|
|
78
|
-
});
|
|
69
|
+
return cbk(null, details);
|
|
79
70
|
} catch (err) {
|
|
80
71
|
return cbk([400, err.message]);
|
|
81
72
|
}
|
|
82
73
|
}],
|
|
83
74
|
|
|
84
|
-
//
|
|
85
|
-
|
|
86
|
-
|
|
75
|
+
// Get details about an open ended trade
|
|
76
|
+
findTrade: [
|
|
77
|
+
'decodeDetails',
|
|
78
|
+
'getIdentity',
|
|
79
|
+
({decodeDetails, getIdentity}, cbk) =>
|
|
80
|
+
{
|
|
81
|
+
// Exit early when there is a known trade
|
|
82
|
+
if (!!decodeDetails.secret) {
|
|
83
|
+
return cbk(null, {
|
|
84
|
+
auth: decodeDetails.secret.auth,
|
|
85
|
+
payload: decodeDetails.secret.payload,
|
|
86
|
+
request: decodeDetails.secret.request,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Get the trade details interactively
|
|
91
|
+
return findTrade({
|
|
92
|
+
ask,
|
|
93
|
+
lnd,
|
|
94
|
+
logger,
|
|
95
|
+
id: decodeDetails.connect.id,
|
|
96
|
+
identity: getIdentity.public_key,
|
|
97
|
+
nodes: decodeDetails.connect.nodes,
|
|
98
|
+
},
|
|
99
|
+
cbk);
|
|
100
|
+
}],
|
|
87
101
|
|
|
102
|
+
// Parse the trade payment request
|
|
103
|
+
requestDetails: ['findTrade', ({findTrade}, cbk) => {
|
|
88
104
|
try {
|
|
89
|
-
return cbk(null, parsePaymentRequest({request}));
|
|
105
|
+
return cbk(null, parsePaymentRequest({request: findTrade.request}));
|
|
90
106
|
} catch (err) {
|
|
91
107
|
return cbk([400, err.message]);
|
|
92
108
|
}
|
|
@@ -184,11 +200,11 @@ module.exports = ({ask, lnd, logger}, cbk) => {
|
|
|
184
200
|
|
|
185
201
|
// Select a purchase option for the trade
|
|
186
202
|
selectPurchaseAction: [
|
|
187
|
-
'
|
|
203
|
+
'findTrade',
|
|
188
204
|
'getPurchase',
|
|
189
205
|
'getRequest',
|
|
190
206
|
'requestDetails',
|
|
191
|
-
({
|
|
207
|
+
({findTrade, getPurchase, getRequest, requestDetails}, cbk) =>
|
|
192
208
|
{
|
|
193
209
|
// Exit early when the trade was already purchased
|
|
194
210
|
if (!!getPurchase.value && !!getPurchase.value.is_confirmed) {
|
|
@@ -201,7 +217,7 @@ module.exports = ({ask, lnd, logger}, cbk) => {
|
|
|
201
217
|
}
|
|
202
218
|
|
|
203
219
|
logger.info({
|
|
204
|
-
request:
|
|
220
|
+
request: findTrade.request,
|
|
205
221
|
purchase: requestDetails.description,
|
|
206
222
|
price: requestDetails.tokens,
|
|
207
223
|
to: requestDetails.destination,
|
|
@@ -257,9 +273,9 @@ module.exports = ({ask, lnd, logger}, cbk) => {
|
|
|
257
273
|
|
|
258
274
|
// Pay and get the preimage through paying for it
|
|
259
275
|
payForPreimage: [
|
|
260
|
-
'
|
|
276
|
+
'findTrade',
|
|
261
277
|
'selectPurchaseAction',
|
|
262
|
-
({
|
|
278
|
+
({findTrade, selectPurchaseAction}, cbk) =>
|
|
263
279
|
{
|
|
264
280
|
// Exit early when this is an offer
|
|
265
281
|
if (!selectPurchaseAction) {
|
|
@@ -271,32 +287,25 @@ module.exports = ({ask, lnd, logger}, cbk) => {
|
|
|
271
287
|
return cbk();
|
|
272
288
|
}
|
|
273
289
|
|
|
290
|
+
const {request} = findTrade;
|
|
291
|
+
|
|
274
292
|
return asyncRetry({
|
|
275
293
|
errorFilter: err => !!isArray(err) && err.slice().shift() >= 500,
|
|
276
294
|
},
|
|
277
|
-
cbk => {
|
|
278
|
-
return buyPreimage({
|
|
279
|
-
ask,
|
|
280
|
-
lnd,
|
|
281
|
-
logger,
|
|
282
|
-
request: decodeDetails.request,
|
|
283
|
-
},
|
|
284
|
-
cbk);
|
|
285
|
-
},
|
|
286
|
-
cbk);
|
|
295
|
+
cbk => buyPreimage({ask, lnd, logger, request}, cbk), cbk);
|
|
287
296
|
}],
|
|
288
297
|
|
|
289
298
|
// Use the preimage to decrypt the trade secret
|
|
290
299
|
decryptSecret: [
|
|
291
300
|
'askForPreimage',
|
|
292
|
-
'
|
|
301
|
+
'findTrade',
|
|
293
302
|
'getPurchase',
|
|
294
303
|
'payForPreimage',
|
|
295
304
|
'requestDetails',
|
|
296
305
|
'selectPurchaseAction',
|
|
297
306
|
({
|
|
298
307
|
askForPreimage,
|
|
299
|
-
|
|
308
|
+
findTrade,
|
|
300
309
|
getPurchase,
|
|
301
310
|
payForPreimage,
|
|
302
311
|
requestDetails,
|
|
@@ -327,11 +336,13 @@ module.exports = ({ask, lnd, logger}, cbk) => {
|
|
|
327
336
|
|
|
328
337
|
const paid = payForPreimage || askForPreimage || payment;
|
|
329
338
|
|
|
339
|
+
const {auth, payload} = findTrade;
|
|
340
|
+
|
|
330
341
|
return decryptTradeSecret({
|
|
342
|
+
auth,
|
|
331
343
|
lnd,
|
|
332
|
-
|
|
344
|
+
payload,
|
|
333
345
|
from: requestDetails.destination,
|
|
334
|
-
payload: decodeDetails.payload,
|
|
335
346
|
secret: paid.secret,
|
|
336
347
|
},
|
|
337
348
|
cbk);
|
|
@@ -17,15 +17,15 @@ const testnetNetworkType = '01';
|
|
|
17
17
|
*/
|
|
18
18
|
module.exports = ({value}) => {
|
|
19
19
|
if (!value) {
|
|
20
|
-
return defaultNetwork;
|
|
20
|
+
return {network: defaultNetwork};
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
if (value === regtestNetworkType) {
|
|
24
|
-
return regtestNetwork;
|
|
24
|
+
return {network: regtestNetwork};
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
if (value === testnetNetworkType) {
|
|
28
|
-
return testnetNetwork;
|
|
28
|
+
return {network: testnetNetwork};
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
throw new Error('UnknownNetworkType');
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
const defaultNetwork = 'btc';
|
|
2
|
+
const regtestNetwork = 'btcregtest';
|
|
3
|
+
const regtestNetworkType = '02';
|
|
4
|
+
const testnetNetwork = 'btctestnet';
|
|
5
|
+
const testnetNetworkType = '01';
|
|
6
|
+
|
|
7
|
+
/** Derive a network record name from a network name
|
|
8
|
+
|
|
9
|
+
{
|
|
10
|
+
network: <Network Name String>
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
@returns
|
|
14
|
+
{
|
|
15
|
+
[value]: <Network Record Value Hex String>
|
|
16
|
+
}
|
|
17
|
+
*/
|
|
18
|
+
module.exports = ({network}) => {
|
|
19
|
+
if (!network) {
|
|
20
|
+
throw new Error('ExpectedNetworkNameToDeriveNetworkRecord');
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
switch (network) {
|
|
24
|
+
case defaultNetwork:
|
|
25
|
+
return {};
|
|
26
|
+
|
|
27
|
+
case regtestNetwork:
|
|
28
|
+
return {value: regestNetworkType};
|
|
29
|
+
|
|
30
|
+
case testnetNetwork:
|
|
31
|
+
return {value: testnetNetworkType};
|
|
32
|
+
|
|
33
|
+
default:
|
|
34
|
+
throw new Error('UnknownNetworkNameToDeriveNetworkRecordFor');
|
|
35
|
+
}
|
|
36
|
+
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const defaultNetwork = 'lnbc';
|
|
2
2
|
const regtestNetwork = 'lnbcrt';
|
|
3
|
+
const regtestNetworkType = '02';
|
|
3
4
|
const testnetNetwork = 'lntb';
|
|
4
5
|
const testnetNetworkType = '01';
|
|
5
6
|
|
|
@@ -24,7 +25,7 @@ module.exports = ({request}) => {
|
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
if (request.startsWith(regtestNetwork)) {
|
|
27
|
-
return {};
|
|
28
|
+
return {value: regtestNetworkType};
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
if (request.startsWith(testnetNetwork)) {
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
const {decodeChanId} = require('bolt07');
|
|
2
|
+
const {encodeSocket} = require('bolt07');
|
|
3
|
+
const {encodeTlvStream} = require('bolt01');
|
|
4
|
+
const {rawChanId} = require('bolt07');
|
|
5
|
+
|
|
6
|
+
const highOrderKeyType = '1';
|
|
7
|
+
const ipV4SocketsType = '3';
|
|
8
|
+
const ipV6SocketsType = '4';
|
|
9
|
+
const torV3SocketsType = '5';
|
|
10
|
+
const {isArray} = Array;
|
|
11
|
+
const isPublicKey = n => !!n && /^0[2-3][0-9A-F]{64}$/i.test(n);
|
|
12
|
+
const join = arr => arr.join('');
|
|
13
|
+
const lowOrderKeyType = '0';
|
|
14
|
+
const nodeIdType = '2';
|
|
15
|
+
|
|
16
|
+
/** Convert node details to a node record
|
|
17
|
+
|
|
18
|
+
A node record looks like:
|
|
19
|
+
|
|
20
|
+
[0]: low order key channel id
|
|
21
|
+
[1]: high order key channel id
|
|
22
|
+
[2]: node identity public key
|
|
23
|
+
[3]: node ipv4 sockets (6 byte chunks)
|
|
24
|
+
[4]: node ipv6 sockets (18 byte chunks)
|
|
25
|
+
[5]: node torV3 addresses (37 byte chunks)
|
|
26
|
+
|
|
27
|
+
{
|
|
28
|
+
channels: [{
|
|
29
|
+
id: <Standard Format Channel Id String>
|
|
30
|
+
partner_public_key: <Node Public Key Hex String>
|
|
31
|
+
}]
|
|
32
|
+
id: <Node Public Key Id Hex String>
|
|
33
|
+
sockets: [<Peer Socket String>]
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
@returns
|
|
37
|
+
{
|
|
38
|
+
encoded: <Encoded Node Details Hex String>
|
|
39
|
+
}
|
|
40
|
+
*/
|
|
41
|
+
module.exports = ({channels, id, sockets}) => {
|
|
42
|
+
if (!isArray(channels)) {
|
|
43
|
+
throw new Error('ExpectedArrayOfChannelsToMapNodeToRecord');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (!isPublicKey(id)) {
|
|
47
|
+
throw new Error('ExpectedNodePublicKeyToMapNodeToRecord');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (!isArray(sockets)) {
|
|
51
|
+
throw new Error('ExpectedArrayOfSocketsToMapNodeToRecord');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Sort the channels by their height ascending, use the oldest as a landmark
|
|
55
|
+
const [channel] = channels.slice().sort((a, b) => {
|
|
56
|
+
const aHeight = decodeChanId({channel: a.id}).block_height;
|
|
57
|
+
const bHeight = decodeChanId({channel: b.id}).block_height;
|
|
58
|
+
|
|
59
|
+
return aHeight - bHeight;
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// Exit early when there is a channel to reference
|
|
63
|
+
if (!!channel) {
|
|
64
|
+
const value = rawChanId({channel: channel.id}).id;
|
|
65
|
+
|
|
66
|
+
// Sort the keys by lexicographical order
|
|
67
|
+
const [key1, key2] = [channel.partner_public_key, id].sort();
|
|
68
|
+
|
|
69
|
+
// When the id is the first key in order, it is a low record
|
|
70
|
+
const type = key1 === id ? lowOrderKeyType : highOrderKeyType;
|
|
71
|
+
|
|
72
|
+
return encodeTlvStream({records: [{type, value}]});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// When there is no channel to reference, use the node identity key instead
|
|
76
|
+
const records = [{type: nodeIdType, value: id}];
|
|
77
|
+
|
|
78
|
+
const encodedSockets = sockets.map(socket => encodeSocket({socket}));
|
|
79
|
+
|
|
80
|
+
const ipV4 = join(encodedSockets.filter(n => !!n.ip4).map(n => n.ip4));
|
|
81
|
+
const ipV6 = join(encodedSockets.filter(n => !!n.ip6).map(n => n.ip6));
|
|
82
|
+
const torV3 = join(encodedSockets.filter(n => !!n.tor3).map(n => n.tor3));
|
|
83
|
+
|
|
84
|
+
if (!!ipV4) {
|
|
85
|
+
records.push({type: ipV4SocketsType, value: ipV4});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (!!ipV6) {
|
|
89
|
+
records.push({type: ipV6SocketsType, value: ipV6});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (!!torV3) {
|
|
93
|
+
records.push({type: torV3SocketsType, value: ipV6});
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Return the node identity key and network sockets
|
|
97
|
+
return encodeTlvStream({records});
|
|
98
|
+
};
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
const {chanFormat} = require('bolt07');
|
|
2
|
+
const {decodeSocket} = require('bolt07');
|
|
3
|
+
const {decodeTlvStream} = require('bolt01');
|
|
4
|
+
|
|
5
|
+
const channelHexLength = 16;
|
|
6
|
+
const chunkIpV4 = data => !!data ? data.value.match(/.{1,12}/g) : [];
|
|
7
|
+
const chunkIpV6 = data => !!data ? data.value.match(/.{1,36}/g) : [];
|
|
8
|
+
const chunkTorV3 = data => !!data ? data.value.match(/.{1,74}/g) : [];
|
|
9
|
+
|
|
10
|
+
const findHighKeyChannelRecord = records => records.find(n => n.type === '1');
|
|
11
|
+
const findIdRecord = records => records.find(n => n.type === '2');
|
|
12
|
+
const findIpV4Record = records => records.find(n => n.type === '3');
|
|
13
|
+
const findIpV6Record = records => records.find(n => n.type === '4');
|
|
14
|
+
const findLowKeyChannelRecord = records => records.find(n => n.type === '0');
|
|
15
|
+
const findTorV3Record = records => records.find(n => n.type === '5');
|
|
16
|
+
const ipV4HexLength = 12;
|
|
17
|
+
const ipV6HexLength = 36;
|
|
18
|
+
const isPublicKey = n => !!n && /^0[2-3][0-9A-F]{64}$/i.test(n);
|
|
19
|
+
const torV3HexLength = 74;
|
|
20
|
+
|
|
21
|
+
/** Decode a node record
|
|
22
|
+
|
|
23
|
+
{
|
|
24
|
+
encoded: <Encoded Node Record>
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
@throws
|
|
28
|
+
<Error>
|
|
29
|
+
|
|
30
|
+
@returns
|
|
31
|
+
{
|
|
32
|
+
[high_channel]: <High Key Channel Id String>
|
|
33
|
+
[low_channel]: <Low Key Channel Id String>
|
|
34
|
+
[node]: {
|
|
35
|
+
id: <Node Public Key Id Hex String>
|
|
36
|
+
sockets: [<Peer Socket String>]
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
*/
|
|
40
|
+
module.exports = ({encoded}) => {
|
|
41
|
+
if (!encoded) {
|
|
42
|
+
throw new Error('ExpectedEncodedNodeRecordToGetNodePointer');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const {records} = decodeTlvStream({encoded});
|
|
46
|
+
|
|
47
|
+
const highKeyRecord = findHighKeyChannelRecord(records);
|
|
48
|
+
|
|
49
|
+
if (!!highKeyRecord && highKeyRecord.value.length !== channelHexLength) {
|
|
50
|
+
throw new Error('ExpectedChannelIdInHighKeyRecord');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (!!highKeyRecord) {
|
|
54
|
+
return {high_channel: chanFormat({id: highKeyRecord.value}).channel};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const lowKeyRecord = findLowKeyChannelRecord(records);
|
|
58
|
+
|
|
59
|
+
if (!!lowKeyRecord && lowKeyRecord.value.length !== channelHexLength) {
|
|
60
|
+
throw new Error('ExpectedChannelIdInLowKeyRecord');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (!!lowKeyRecord) {
|
|
64
|
+
return {low_channel: chanFormat({id: lowKeyRecord.value}).channel};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const idRecord = findIdRecord(records);
|
|
68
|
+
|
|
69
|
+
if (!idRecord) {
|
|
70
|
+
throw new Error('ExpectedNodeIdRecordToMapNodeRecordToNodePointer');
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (!isPublicKey(idRecord.value)) {
|
|
74
|
+
throw new Error('ExpectedNodeIdPublicKeyToMapNodeRecordToNodePointer');
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const ipV4SocketsRecord = findIpV4Record(records);
|
|
78
|
+
|
|
79
|
+
if (!!ipV4SocketsRecord && !!(ipV4SocketsRecord % ipV4HexLength)) {
|
|
80
|
+
throw new Error('ExpectedListOfIpV4SocketsToMapRecordToNode');
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const ipV4Sockets = chunkIpV4(ipV4SocketsRecord).map(ip4 => {
|
|
84
|
+
return decodeSocket({ip4}).socket;
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
const ipV6SocketsRecord = findIpV6Record(records);
|
|
88
|
+
|
|
89
|
+
if (!!ipV6SocketsRecord && !!(ipV6SocketsRecord % ipV6HexLength)) {
|
|
90
|
+
throw new Error('ExpectedListOfIpV6SocketsToMapRecordToNode');
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const ipV6Sockets = chunkIpV6(ipV6SocketsRecord).map(ip6 => {
|
|
94
|
+
return decodeSocket({ip6}).socket;
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
const torV3SocketsRecord = findTorV3Record(records);
|
|
98
|
+
|
|
99
|
+
if (!!torV3SocketsRecord && !!(torV3SocketsRecord % torV3HexLength)) {
|
|
100
|
+
throw new Error('ExpectedListOfTorV3SocketsToMapRecordToNode');
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const torV3Sockets = chunkTorV3(torV3SocketsRecord).map(tor3 => {
|
|
104
|
+
return decodeSocket({tor3}).socket;
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
return {
|
|
108
|
+
node: {
|
|
109
|
+
id: idRecord.value,
|
|
110
|
+
sockets: [].concat(ipV4Sockets).concat(ipV6Sockets).concat(torV3Sockets),
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
};
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
const asyncAuto = require('async/auto');
|
|
2
|
+
const {returnResult} = require('asyncjs-util');
|
|
3
|
+
|
|
4
|
+
const decodeTrade = require('./decode_trade');
|
|
5
|
+
const {makePeerRequest} = require('./../p2p');
|
|
6
|
+
|
|
7
|
+
const findTradeRecord = records => records.find(n => n.type === '1');
|
|
8
|
+
const requestTradeTimeoutMs = 1000 * 30;
|
|
9
|
+
const {serviceTypeRequestTrades} = require('./../service_types');
|
|
10
|
+
const tradeIdRecordType = '0';
|
|
11
|
+
|
|
12
|
+
/** Request a specific trade by its id
|
|
13
|
+
|
|
14
|
+
{
|
|
15
|
+
id: <Trade Identifier Hex String>
|
|
16
|
+
lnd: <Authenticated LND API Object>
|
|
17
|
+
to: <Make Request To Public Key Hex Encoded String>
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
@returns via cbk or Promise
|
|
21
|
+
{
|
|
22
|
+
auth: <Encrypted Payload Auth Hex String>
|
|
23
|
+
payload: <Preimage Encrypted Payload Hex String>
|
|
24
|
+
request: <BOLT 11 Payment Request String>
|
|
25
|
+
}
|
|
26
|
+
*/
|
|
27
|
+
module.exports = ({id, lnd, to}, cbk) => {
|
|
28
|
+
return new Promise((resolve, reject) => {
|
|
29
|
+
return asyncAuto({
|
|
30
|
+
// Check arguments
|
|
31
|
+
validate: cbk => {
|
|
32
|
+
if (!id) {
|
|
33
|
+
return cbk([400, 'ExpectedTradeIdentifierToRequestTradeById']);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (!lnd) {
|
|
37
|
+
return cbk([400, 'ExpectedAuthenticatedLndToRequestTradeById']);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (!to) {
|
|
41
|
+
return cbk([400, 'ExpectedRemotePublicKeyToRequestTradeById']);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return cbk();
|
|
45
|
+
},
|
|
46
|
+
|
|
47
|
+
// Get trade
|
|
48
|
+
getTrade: ['validate', ({}, cbk) => {
|
|
49
|
+
return makePeerRequest({
|
|
50
|
+
lnd,
|
|
51
|
+
to,
|
|
52
|
+
records: [{type: tradeIdRecordType, value: id}],
|
|
53
|
+
timeout: requestTradeTimeoutMs,
|
|
54
|
+
type: serviceTypeRequestTrades,
|
|
55
|
+
},
|
|
56
|
+
(err, res) => {
|
|
57
|
+
if (!!err) {
|
|
58
|
+
return cbk(err);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const tradeRecord = findTradeRecord(res.records);
|
|
62
|
+
|
|
63
|
+
if (!tradeRecord) {
|
|
64
|
+
return cbk([503, 'ExpectedTradeRecordFromPeer']);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
try {
|
|
68
|
+
decodeTrade({trade: tradeRecord.value});
|
|
69
|
+
} catch (err) {
|
|
70
|
+
return cbk([503, err.message]);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const {secret} = decodeTrade({trade: tradeRecord.value});
|
|
74
|
+
|
|
75
|
+
if (!secret) {
|
|
76
|
+
return cbk([503, 'ExpectedTradeSecretInResponseForTradeById']);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
try {
|
|
80
|
+
return cbk(null, secret);
|
|
81
|
+
} catch (err) {
|
|
82
|
+
return cbk([503, 'ExpectedValidTradeRecordFromPeer', {err}]);
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
}],
|
|
86
|
+
},
|
|
87
|
+
returnResult({reject, resolve, of: 'getTrade'}, cbk));
|
|
88
|
+
});
|
|
89
|
+
};
|