paid-services 3.13.2 → 3.14.2
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 +8 -0
- package/p2p/encode_peer_response.js +1 -2
- package/package.json +2 -1
- package/test/trades/test_encode_open_trade.js +48 -0
- package/test/trades/test_encode_trade.js +24 -1
- package/trades/accept_trade.js +83 -33
- package/trades/buy_channel.js +251 -0
- package/trades/buy_preimage.js +3 -2
- package/trades/connect_to_seller.js +183 -0
- package/trades/convert_fiat.js +112 -0
- package/trades/create_anchored_trade.js +22 -13
- package/trades/create_channel_sale.js +181 -77
- package/trades/create_trade.js +115 -20
- package/trades/decode_anchored_trade.js +39 -11
- package/trades/decode_open_trade.js +6 -0
- package/trades/decode_trade.js +16 -4
- package/trades/decode_trade_payment.js +45 -0
- package/trades/encode_anchored_trade.js +25 -5
- package/trades/encode_trade.js +1 -1
- package/trades/encode_trade_payment.js +38 -0
- package/trades/encode_trade_secret.js +1 -1
- package/trades/finalize_trade.js +244 -0
- package/trades/find_trade.js +14 -175
- package/trades/get_anchored_trade.js +10 -6
- package/trades/manage_trade.js +2 -8
- package/trades/manage_trades.js +44 -37
- package/trades/request_trade_by_id.js +3 -18
- package/trades/service_anchored_trades.js +5 -1
- package/trades/service_open_trade.js +24 -17
- package/trades/service_trade_requests.js +51 -31
- package/trades/trade_from_invoice.js +11 -7
- package/trades/finalize_trade_secret.js +0 -158
- package/trades/open_channel.js +0 -60
package/trades/find_trade.js
CHANGED
|
@@ -1,34 +1,23 @@
|
|
|
1
1
|
const {randomBytes} = require('crypto');
|
|
2
2
|
|
|
3
|
-
const {addPeer} = require('ln-service');
|
|
4
3
|
const asyncAuto = require('async/auto');
|
|
5
|
-
const asyncDetect = require('async/detect');
|
|
6
|
-
const asyncDetectSeries = require('async/detectSeries');
|
|
7
|
-
const asyncMap = require('async/map');
|
|
8
4
|
const asyncReflect = require('async/reflect');
|
|
9
|
-
const {getChannel} = require('ln-service');
|
|
10
|
-
const {getNode} = require('ln-service');
|
|
11
|
-
const {getPeers} = require('ln-service');
|
|
12
5
|
const {returnResult} = require('asyncjs-util');
|
|
13
6
|
|
|
7
|
+
const connectToSeller = require('./connect_to_seller');
|
|
14
8
|
const decodeBasicTrade = require('./decode_basic_trade');
|
|
15
9
|
const {makePeerRequest} = require('./../p2p');
|
|
16
10
|
const requestTradeById = require('./request_trade_by_id');
|
|
17
11
|
const {servicePeerRequests} = require('./../p2p');
|
|
18
|
-
const {serviceTypeReceiveChannelSale} = require('./../service_types');
|
|
19
|
-
const {serviceTypeRequestChannelSale} = require('./../service_types');
|
|
20
12
|
const {serviceTypeReceiveTrades} = require('./../service_types');
|
|
21
13
|
const {serviceTypeRequestTrades} = require('./../service_types');
|
|
22
14
|
|
|
23
|
-
const buyChannelAction = 'buy';
|
|
24
15
|
const findBasicRecord = records => records.find(n => n.type === '1');
|
|
25
16
|
const findIdRecord = records => records.find(n => n.type === '0');
|
|
26
17
|
const {isArray} = Array;
|
|
27
18
|
const makeRequestId = () => randomBytes(32).toString('hex');
|
|
28
|
-
const requestTradeType = '805005';
|
|
29
19
|
const requestTradesTimeoutMs = 1000 * 30;
|
|
30
20
|
const tradesRequestIdType = '1';
|
|
31
|
-
const uniq = arr => Array.from(new Set(arr));
|
|
32
21
|
const uniqBy = (a,b) => a.filter((e,i) => a.findIndex(n => n[b] == e[b]) == i);
|
|
33
22
|
const waitForTradesMs = 1000 * 5;
|
|
34
23
|
|
|
@@ -37,7 +26,6 @@ const waitForTradesMs = 1000 * 5;
|
|
|
37
26
|
{
|
|
38
27
|
ask: <Inquirer Ask Function>
|
|
39
28
|
[id]: <Trade Id Encoded Hex String>
|
|
40
|
-
identity: <Own Node Identity Public Key Hex String>
|
|
41
29
|
lnd: <Authenticated LND API Object>
|
|
42
30
|
logger: <Winston Logger Object>
|
|
43
31
|
nodes: [{
|
|
@@ -52,29 +40,21 @@ const waitForTradesMs = 1000 * 5;
|
|
|
52
40
|
|
|
53
41
|
@returns via cbk or Promise
|
|
54
42
|
{
|
|
55
|
-
auth: <Encrypted Payload Auth Hex String>
|
|
56
|
-
payload: <Preimage Encrypted Payload Hex String>
|
|
43
|
+
[auth]: <Encrypted Payload Auth Hex String>
|
|
44
|
+
[payload]: <Preimage Encrypted Payload Hex String>
|
|
57
45
|
request: <BOLT 11 Payment Request String>
|
|
58
46
|
trade: <Encoded Trade String>
|
|
59
47
|
}
|
|
60
48
|
*/
|
|
61
|
-
module.exports = ({
|
|
49
|
+
module.exports = ({ask, id, lnd, logger, nodes}, cbk) => {
|
|
62
50
|
return new Promise((resolve, reject) => {
|
|
63
51
|
return asyncAuto({
|
|
64
52
|
// Check arguments
|
|
65
53
|
validate: cbk => {
|
|
66
|
-
if (!action) {
|
|
67
|
-
return cbk([400, 'ExpectedActionTypeToFindTrade']);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
54
|
if (!ask) {
|
|
71
55
|
return cbk([400, 'ExpectedAskMethodToFindTrade']);
|
|
72
56
|
}
|
|
73
57
|
|
|
74
|
-
if (!identity) {
|
|
75
|
-
return cbk([400, 'ExpectedIdentityToFindTrade']);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
58
|
if (!lnd) {
|
|
79
59
|
return cbk([400, 'ExpectedLndApiToFindTrade']);
|
|
80
60
|
}
|
|
@@ -90,148 +70,13 @@ module.exports = ({action, ask, id, identity, lnd, logger, nodes}, cbk) => {
|
|
|
90
70
|
return cbk();
|
|
91
71
|
},
|
|
92
72
|
|
|
93
|
-
//
|
|
94
|
-
|
|
95
|
-
return
|
|
96
|
-
// Exit early when the node is self
|
|
97
|
-
if (!!connect.node && connect.node.id === identity) {
|
|
98
|
-
return cbk();
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// Exit early when the node id and sockets is specified directly
|
|
102
|
-
if (!!connect.node) {
|
|
103
|
-
return getNode({
|
|
104
|
-
lnd,
|
|
105
|
-
is_omitting_channels: true,
|
|
106
|
-
public_key: connect.node.id,
|
|
107
|
-
},
|
|
108
|
-
(err, res) => {
|
|
109
|
-
if (!!err) {
|
|
110
|
-
return cbk(null, connect.node);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
const sockets = res.sockets.map(n => n.socket);
|
|
114
|
-
|
|
115
|
-
return cbk(null, {
|
|
116
|
-
id: connect.node.id,
|
|
117
|
-
sockets: uniq([].concat(sockets).concat(connect.node.sockets)),
|
|
118
|
-
});
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
// Exit early when there is no landmark channel
|
|
123
|
-
if (!connect.high_channel && !connect.low_channel) {
|
|
124
|
-
return cbk();
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
const channelId = connect.high_channel || connect.low_channel;
|
|
128
|
-
|
|
129
|
-
// Get the public keys of the landmark channel
|
|
130
|
-
return getChannel({lnd, id: channelId}, (err, res) => {
|
|
131
|
-
// Exit early when the channel cannot be fetched
|
|
132
|
-
if (!!err) {
|
|
133
|
-
return cbk();
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
const [low, high] = res.policies.map(n => n.public_key);
|
|
137
|
-
|
|
138
|
-
// The node key is either the lower or the higher public key
|
|
139
|
-
const nodeId = !!connect.low_channel ? low : high;
|
|
140
|
-
|
|
141
|
-
// Exit early when the node is self
|
|
142
|
-
if (nodeId === identity) {
|
|
143
|
-
return cbk();
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
// Find the sockets for the node
|
|
147
|
-
return getNode({
|
|
148
|
-
lnd,
|
|
149
|
-
is_omitting_channels: true,
|
|
150
|
-
public_key: nodeId,
|
|
151
|
-
},
|
|
152
|
-
(err, res) => {
|
|
153
|
-
if (!!err) {
|
|
154
|
-
return cbk();
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
return cbk(null, {
|
|
158
|
-
id: nodeId,
|
|
159
|
-
sockets: res.sockets.map(n => n.socket),
|
|
160
|
-
});
|
|
161
|
-
});
|
|
162
|
-
});
|
|
163
|
-
},
|
|
164
|
-
cbk);
|
|
73
|
+
// Connect to the seller
|
|
74
|
+
connect: ['validate', ({}, cbk) => {
|
|
75
|
+
return connectToSeller({lnd, logger, nodes}, cbk);
|
|
165
76
|
}],
|
|
166
77
|
|
|
167
|
-
//
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
// Determine the receive type to listen for
|
|
171
|
-
receiveType: ['validate', ({}, cbk) => {
|
|
172
|
-
// Exit early when the action is to buy a channel
|
|
173
|
-
if (action === buyChannelAction) {
|
|
174
|
-
return cbk(null, serviceTypeReceiveChannelSale);
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
return cbk(null, serviceTypeReceiveTrades);
|
|
178
|
-
}],
|
|
179
|
-
|
|
180
|
-
// Determine the request type to send
|
|
181
|
-
requestType: ['validate', ({}, cbk) => {
|
|
182
|
-
// Exit early when the action is to buy a channel
|
|
183
|
-
if (action === buyChannelAction) {
|
|
184
|
-
return cbk(null, serviceTypeRequestChannelSale);
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
return cbk(null, serviceTypeRequestTrades);
|
|
188
|
-
}],
|
|
189
|
-
|
|
190
|
-
// Try and connect to a node in order to do p2p messaging
|
|
191
|
-
connect: ['getNodes', 'getPeers', ({getNodes, getPeers}, cbk) => {
|
|
192
|
-
const connected = getPeers.peers.map(n => n.public_key);
|
|
193
|
-
|
|
194
|
-
// Look for a node that is already a connected peer
|
|
195
|
-
const [alreadyConnected] = getNodes.filter(node => {
|
|
196
|
-
return !!node && connected.includes(node.id);
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
// Exit early when already connected to a node
|
|
200
|
-
if (!!alreadyConnected) {
|
|
201
|
-
return cbk(null, alreadyConnected);
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// Try and connect to a referenced node
|
|
205
|
-
return asyncDetect(getNodes.filter(n => !!n), (node, cbk) => {
|
|
206
|
-
logger.info({connecting_to: node.id});
|
|
207
|
-
|
|
208
|
-
// Attempt referenced sockets to establish p2p connection
|
|
209
|
-
return asyncDetectSeries(node.sockets, (socket, cbk) => {
|
|
210
|
-
return addPeer({lnd, socket, public_key: node.id}, err => {
|
|
211
|
-
// Stop trying sockets when there is no error
|
|
212
|
-
return cbk(null, !err);
|
|
213
|
-
});
|
|
214
|
-
},
|
|
215
|
-
(err, socket) => {
|
|
216
|
-
if (!!err) {
|
|
217
|
-
return cbk(err);
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
// The node is connected if one of the sockets worked
|
|
221
|
-
return cbk(null, !!socket);
|
|
222
|
-
});
|
|
223
|
-
},
|
|
224
|
-
cbk);
|
|
225
|
-
}],
|
|
226
|
-
|
|
227
|
-
// Node to request trades from
|
|
228
|
-
to: ['connect', ({connect}, cbk) => {
|
|
229
|
-
if (!connect) {
|
|
230
|
-
return cbk([503, 'FailedToConnectToNode']);
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
return cbk(null, connect.id);
|
|
234
|
-
}],
|
|
78
|
+
// Send request to node with public key identity
|
|
79
|
+
to: ['connect', ({connect}, cbk) => cbk(null, connect.id)],
|
|
235
80
|
|
|
236
81
|
// Request a specific trade
|
|
237
82
|
requestTrade: ['to', asyncReflect(({to}, cbk) => {
|
|
@@ -240,17 +85,11 @@ module.exports = ({action, ask, id, identity, lnd, logger, nodes}, cbk) => {
|
|
|
240
85
|
return cbk();
|
|
241
86
|
}
|
|
242
87
|
|
|
243
|
-
return requestTradeById({
|
|
88
|
+
return requestTradeById({id, lnd, to}, cbk);
|
|
244
89
|
})],
|
|
245
90
|
|
|
246
91
|
// Request an inventory of trades
|
|
247
|
-
requestTrades: [
|
|
248
|
-
'receiveType',
|
|
249
|
-
'requestTrade',
|
|
250
|
-
'requestType',
|
|
251
|
-
'to',
|
|
252
|
-
({receiveType, requestTrade, requestType, to}, cbk) =>
|
|
253
|
-
{
|
|
92
|
+
requestTrades: ['requestTrade', 'to', ({requestTrade, to}, cbk) => {
|
|
254
93
|
// Exit early when there was a successful request for a specific id
|
|
255
94
|
if (!!requestTrade.value) {
|
|
256
95
|
return cbk();
|
|
@@ -267,7 +106,7 @@ module.exports = ({action, ask, id, identity, lnd, logger, nodes}, cbk) => {
|
|
|
267
106
|
return !!err ? cbk(err) : cbk(null, {trades});
|
|
268
107
|
};
|
|
269
108
|
|
|
270
|
-
service.request({type:
|
|
109
|
+
service.request({type: serviceTypeReceiveTrades}, (req, res) => {
|
|
271
110
|
const requestIdRecord = findIdRecord(req.records);
|
|
272
111
|
|
|
273
112
|
// Exit early when this is a request for something else
|
|
@@ -300,7 +139,7 @@ module.exports = ({action, ask, id, identity, lnd, logger, nodes}, cbk) => {
|
|
|
300
139
|
to,
|
|
301
140
|
records: [{type: tradesRequestIdType, value: requestId}],
|
|
302
141
|
timeout: requestTradesTimeoutMs,
|
|
303
|
-
type:
|
|
142
|
+
type: serviceTypeRequestTrades,
|
|
304
143
|
},
|
|
305
144
|
(err, res) => {
|
|
306
145
|
if (!!err) {
|
|
@@ -355,7 +194,7 @@ module.exports = ({action, ask, id, identity, lnd, logger, nodes}, cbk) => {
|
|
|
355
194
|
return cbk();
|
|
356
195
|
}
|
|
357
196
|
|
|
358
|
-
return requestTradeById({
|
|
197
|
+
return requestTradeById({lnd, to, id: selectTrade.id}, cbk);
|
|
359
198
|
}],
|
|
360
199
|
|
|
361
200
|
// Final trade details
|
|
@@ -15,10 +15,12 @@ const decodeAnchoredTrade = require('./decode_anchored_trade');
|
|
|
15
15
|
@returns via cbk or Promise
|
|
16
16
|
{
|
|
17
17
|
[trade]: {
|
|
18
|
-
|
|
18
|
+
[channel]: <Channel Sale Capacity Tokens Number>
|
|
19
|
+
[description]: <Description of Trade String>
|
|
19
20
|
expires_at: <Trade Expires at ISO 8601 Date String>
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
[price]: <Trade Price String>
|
|
22
|
+
[secret]: <Trade Secret String>
|
|
23
|
+
[tokens]: <Trade Price Tokens Number>
|
|
22
24
|
}
|
|
23
25
|
}
|
|
24
26
|
*/
|
|
@@ -59,10 +61,12 @@ module.exports = ({id, lnd}, cbk) => {
|
|
|
59
61
|
|
|
60
62
|
return cbk(null, {
|
|
61
63
|
trade: {
|
|
62
|
-
|
|
64
|
+
channel: trade.channel || undefined,
|
|
65
|
+
description: trade.description || undefined,
|
|
63
66
|
expires_at: getInvoice.value.expires_at,
|
|
64
|
-
|
|
65
|
-
|
|
67
|
+
price: trade.price || undefined,
|
|
68
|
+
secret: trade.secret || undefined,
|
|
69
|
+
tokens: getInvoice.value.tokens || undefined,
|
|
66
70
|
},
|
|
67
71
|
});
|
|
68
72
|
}],
|
package/trades/manage_trade.js
CHANGED
|
@@ -21,7 +21,6 @@ const tokensAsBigUnit = tokens => (tokens / 1e8).toFixed(8);
|
|
|
21
21
|
/** Manage an individual trade
|
|
22
22
|
|
|
23
23
|
{
|
|
24
|
-
action: <Action Type String>
|
|
25
24
|
ask: <Ask Function>
|
|
26
25
|
lnd: <Authenticated LND API Object>
|
|
27
26
|
logger: <Winston Logger Object>
|
|
@@ -29,15 +28,11 @@ const tokensAsBigUnit = tokens => (tokens / 1e8).toFixed(8);
|
|
|
29
28
|
|
|
30
29
|
@returns via cbk or Promise
|
|
31
30
|
*/
|
|
32
|
-
module.exports = ({
|
|
31
|
+
module.exports = ({ask, lnd, logger}, cbk) => {
|
|
33
32
|
return new Promise((resolve, reject) => {
|
|
34
33
|
return asyncAuto({
|
|
35
34
|
// Check arguments
|
|
36
35
|
validate: cbk => {
|
|
37
|
-
if (!action) {
|
|
38
|
-
return cbk([400, 'ExpectedActionTypeToManageTrade']);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
36
|
if (!ask) {
|
|
42
37
|
return cbk([400, 'ExpectedAskFunctionToManageTrade']);
|
|
43
38
|
}
|
|
@@ -95,7 +90,6 @@ module.exports = ({action, ask, lnd, logger}, cbk) => {
|
|
|
95
90
|
|
|
96
91
|
// Get the trade details interactively
|
|
97
92
|
return findTrade({
|
|
98
|
-
action,
|
|
99
93
|
ask,
|
|
100
94
|
lnd,
|
|
101
95
|
logger,
|
|
@@ -376,7 +370,7 @@ module.exports = ({action, ask, lnd, logger}, cbk) => {
|
|
|
376
370
|
return cbk();
|
|
377
371
|
}
|
|
378
372
|
|
|
379
|
-
logger.info({
|
|
373
|
+
logger.info({secret_purchased: hexAsUtf8(decryptSecret.plain)});
|
|
380
374
|
|
|
381
375
|
return cbk();
|
|
382
376
|
}],
|
package/trades/manage_trades.js
CHANGED
|
@@ -2,13 +2,13 @@ const asyncAuto = require('async/auto');
|
|
|
2
2
|
const asyncUntil = require('async/until');
|
|
3
3
|
const {cancelHodlInvoice} = require('ln-service');
|
|
4
4
|
const {diffieHellmanComputeSecret} = require('ln-service');
|
|
5
|
-
const {getChainBalance} = require('ln-service');
|
|
6
5
|
const {getIdentity} = require('ln-service');
|
|
7
6
|
const {getInvoices} = require('ln-service');
|
|
8
7
|
const {getNetwork} = require('ln-sync');
|
|
9
8
|
const {getNodeAlias} = require('ln-sync');
|
|
10
9
|
const {returnResult} = require('asyncjs-util');
|
|
11
10
|
|
|
11
|
+
const buyChannel = require('./buy_channel');
|
|
12
12
|
const createChannelSale = require('./create_channel_sale');
|
|
13
13
|
const createTrade = require('./create_trade');
|
|
14
14
|
const encodeTrade = require('./encode_trade');
|
|
@@ -33,15 +33,15 @@ const viewAction = 'view';
|
|
|
33
33
|
|
|
34
34
|
{
|
|
35
35
|
ask: <Ask Function>
|
|
36
|
-
experimental: <Experiment Mode Bool>
|
|
37
36
|
lnd: <Authenticated LND API Object>
|
|
38
37
|
logger: <Winston Logger Object>
|
|
38
|
+
request: <Request Function>
|
|
39
39
|
separator: <Create Separator Function>
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
@returns via cbk or Promise
|
|
43
43
|
*/
|
|
44
|
-
module.exports = ({ask,
|
|
44
|
+
module.exports = ({ask, lnd, logger, request, separator}, cbk) => {
|
|
45
45
|
return new Promise((resolve, reject) => {
|
|
46
46
|
return asyncAuto({
|
|
47
47
|
// Check arguments
|
|
@@ -58,6 +58,10 @@ module.exports = ({ask, experimental, lnd, logger, separator}, cbk) => {
|
|
|
58
58
|
return cbk([400, 'ExpectedLoggerToManageTrades']);
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
if (!request) {
|
|
62
|
+
return cbk([400, 'ExpectedRequestFunctionToManageTrades']);
|
|
63
|
+
}
|
|
64
|
+
|
|
61
65
|
return cbk();
|
|
62
66
|
},
|
|
63
67
|
|
|
@@ -71,23 +75,20 @@ module.exports = ({ask, experimental, lnd, logger, separator}, cbk) => {
|
|
|
71
75
|
select: ['validate', ({}, cbk) => {
|
|
72
76
|
return ask({
|
|
73
77
|
choices: [
|
|
74
|
-
|
|
75
|
-
{name: 'Create Trade', value: createAction},
|
|
76
|
-
{name: 'Decode Trade', value: decodeAction},
|
|
77
|
-
separator(),
|
|
78
|
+
{name: 'Buy Secret', value: decodeAction},
|
|
78
79
|
{
|
|
79
80
|
name: 'Buy Channel (experimental)',
|
|
80
81
|
value: buyAction,
|
|
81
|
-
disabled: !experimental,
|
|
82
82
|
},
|
|
83
|
+
separator(),
|
|
84
|
+
{name: 'Sell Secret', value: createAction},
|
|
83
85
|
{
|
|
84
86
|
name: 'Sell Channel (experimental)',
|
|
85
87
|
value: sellAction,
|
|
86
|
-
disabled: !experimental,
|
|
87
88
|
},
|
|
88
89
|
separator(),
|
|
89
|
-
{name: 'Open Trades', value: listAction},
|
|
90
|
-
{name: 'Serve Trades', value: serveAction},
|
|
90
|
+
{name: 'List Open Trades', value: listAction},
|
|
91
|
+
{name: 'Serve Open Trades', value: serveAction},
|
|
91
92
|
],
|
|
92
93
|
loop: false,
|
|
93
94
|
message: 'Trade?',
|
|
@@ -97,7 +98,7 @@ module.exports = ({ask, experimental, lnd, logger, separator}, cbk) => {
|
|
|
97
98
|
cbk);
|
|
98
99
|
}],
|
|
99
100
|
|
|
100
|
-
// Confirm that signer RPC is enabled
|
|
101
|
+
// Confirm that signer RPC is enabled, this is required for trade secret
|
|
101
102
|
checkSigner: ['getIdentity', ({getIdentity}, cbk) => {
|
|
102
103
|
return diffieHellmanComputeSecret({
|
|
103
104
|
lnd,
|
|
@@ -113,7 +114,7 @@ module.exports = ({ask, experimental, lnd, logger, separator}, cbk) => {
|
|
|
113
114
|
return cbk();
|
|
114
115
|
}
|
|
115
116
|
|
|
116
|
-
return createTrade({ask, lnd, logger}, cbk);
|
|
117
|
+
return createTrade({ask, lnd, logger, request}, cbk);
|
|
117
118
|
}],
|
|
118
119
|
|
|
119
120
|
// Trade was created
|
|
@@ -131,14 +132,24 @@ module.exports = ({ask, experimental, lnd, logger, separator}, cbk) => {
|
|
|
131
132
|
// View an existing trade
|
|
132
133
|
view: ['checkSigner', 'select', ({checkSigner, select}, cbk) => {
|
|
133
134
|
// Exit early when not decoding a trade
|
|
134
|
-
if (select.action !== decodeAction
|
|
135
|
+
if (select.action !== decodeAction) {
|
|
136
|
+
return cbk();
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return manageTrade({ask, lnd, logger}, cbk)
|
|
140
|
+
}],
|
|
141
|
+
|
|
142
|
+
// Buy a channel
|
|
143
|
+
buyChannel: ['select', ({select}, cbk) => {
|
|
144
|
+
// Exit early when not buying a channel
|
|
145
|
+
if (select.action !== buyAction) {
|
|
135
146
|
return cbk();
|
|
136
147
|
}
|
|
137
148
|
|
|
138
|
-
return
|
|
149
|
+
return buyChannel({ask, lnd, logger}, cbk);
|
|
139
150
|
}],
|
|
140
151
|
|
|
141
|
-
// Get open trades
|
|
152
|
+
// Get open trades that are being offered
|
|
142
153
|
getTrades: ['validate', ({}, cbk) => {
|
|
143
154
|
const paging = {trades: []};
|
|
144
155
|
|
|
@@ -189,11 +200,14 @@ module.exports = ({ask, experimental, lnd, logger, separator}, cbk) => {
|
|
|
189
200
|
return cbk([404, 'NoTradesCurrentlyOpen']);
|
|
190
201
|
}
|
|
191
202
|
|
|
203
|
+
const trades = getTrades.filter(n => !!n.secret && !!n.description);
|
|
204
|
+
|
|
192
205
|
return ask({
|
|
193
|
-
choices:
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
206
|
+
choices: trades.map(({description, id, price, tokens}) => {
|
|
207
|
+
const charging = !!tokens ? tokensAsBigUnit(tokens) : price;
|
|
208
|
+
|
|
209
|
+
return {name: `${charging} ${description}`, value: id};
|
|
210
|
+
}),
|
|
197
211
|
message: 'Trade?',
|
|
198
212
|
name: 'manage',
|
|
199
213
|
type: 'list',
|
|
@@ -241,11 +255,13 @@ module.exports = ({ask, experimental, lnd, logger, separator}, cbk) => {
|
|
|
241
255
|
return serviceOpenTrade({
|
|
242
256
|
lnd,
|
|
243
257
|
logger,
|
|
258
|
+
request,
|
|
244
259
|
channels: [],
|
|
245
260
|
description: trade.description,
|
|
246
261
|
expires_at: trade.expires_at,
|
|
247
262
|
id: trade.id,
|
|
248
263
|
network: getNetwork.network,
|
|
264
|
+
price: trade.price,
|
|
249
265
|
public_key: getIdentity.public_key,
|
|
250
266
|
secret: trade.secret,
|
|
251
267
|
tokens: trade.tokens,
|
|
@@ -280,7 +296,7 @@ module.exports = ({ask, experimental, lnd, logger, separator}, cbk) => {
|
|
|
280
296
|
return cbk();
|
|
281
297
|
}
|
|
282
298
|
|
|
283
|
-
const sub = serviceAnchoredTrades({lnd});
|
|
299
|
+
const sub = serviceAnchoredTrades({lnd, request});
|
|
284
300
|
|
|
285
301
|
const {trade} = encodeTrade({
|
|
286
302
|
connect: {
|
|
@@ -294,11 +310,15 @@ module.exports = ({ask, experimental, lnd, logger, separator}, cbk) => {
|
|
|
294
310
|
sub.on('settled', async ({description, to, tokens}) => {
|
|
295
311
|
const {alias, id} = await getNodeAlias({lnd, id: to});
|
|
296
312
|
|
|
297
|
-
|
|
313
|
+
const item = `${description} to ${alias} ${to}`;
|
|
314
|
+
|
|
315
|
+
return logger.info(`sold: ${tokensAsBigUnit(tokens)} ${item}`);
|
|
298
316
|
});
|
|
299
317
|
|
|
300
318
|
sub.on('start', ({description, tokens}) => {
|
|
301
|
-
|
|
319
|
+
const trade = `${tokensAsBigUnit(tokens)} ${description}`;
|
|
320
|
+
|
|
321
|
+
return logger.info(`open: ${trade}`);
|
|
302
322
|
});
|
|
303
323
|
|
|
304
324
|
sub.on('error', err => {
|
|
@@ -315,20 +335,7 @@ module.exports = ({ask, experimental, lnd, logger, separator}, cbk) => {
|
|
|
315
335
|
return cbk();
|
|
316
336
|
}
|
|
317
337
|
|
|
318
|
-
return
|
|
319
|
-
if (!!err) {
|
|
320
|
-
return cbk(err);
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
return createChannelSale({
|
|
324
|
-
ask,
|
|
325
|
-
lnd,
|
|
326
|
-
logger,
|
|
327
|
-
action: select.action,
|
|
328
|
-
balance: res.chain_balance,
|
|
329
|
-
},
|
|
330
|
-
cbk);
|
|
331
|
-
});
|
|
338
|
+
return createChannelSale({ask, lnd, logger, request}, cbk);
|
|
332
339
|
}],
|
|
333
340
|
},
|
|
334
341
|
returnResult({reject, resolve}, cbk));
|
|
@@ -4,7 +4,6 @@ const {returnResult} = require('asyncjs-util');
|
|
|
4
4
|
const decodeTrade = require('./decode_trade');
|
|
5
5
|
const {makePeerRequest} = require('./../p2p');
|
|
6
6
|
|
|
7
|
-
const buyChannelAction = 'buy';
|
|
8
7
|
const findTradeRecord = records => records.find(n => n.type === '1');
|
|
9
8
|
const requestTradeTimeoutMs = 1000 * 30;
|
|
10
9
|
const {serviceTypeRequestChannelSale} = require('./../service_types');
|
|
@@ -14,7 +13,6 @@ const tradeIdRecordType = '0';
|
|
|
14
13
|
/** Request a specific trade by its id
|
|
15
14
|
|
|
16
15
|
{
|
|
17
|
-
action: <Purchase Action String>
|
|
18
16
|
id: <Trade Identifier Hex String>
|
|
19
17
|
lnd: <Authenticated LND API Object>
|
|
20
18
|
to: <Make Request To Public Key Hex Encoded String>
|
|
@@ -28,15 +26,11 @@ const tradeIdRecordType = '0';
|
|
|
28
26
|
trade: <Encoded Trade Record String>
|
|
29
27
|
}
|
|
30
28
|
*/
|
|
31
|
-
module.exports = ({
|
|
29
|
+
module.exports = ({id, lnd, to}, cbk) => {
|
|
32
30
|
return new Promise((resolve, reject) => {
|
|
33
31
|
return asyncAuto({
|
|
34
32
|
// Check arguments
|
|
35
33
|
validate: cbk => {
|
|
36
|
-
if (!action) {
|
|
37
|
-
return cbk([400, 'ExpectedActionTypeToRequestTradeById']);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
34
|
if (!id) {
|
|
41
35
|
return cbk([400, 'ExpectedTradeIdentifierToRequestTradeById']);
|
|
42
36
|
}
|
|
@@ -52,23 +46,14 @@ module.exports = ({action, id, lnd, to}, cbk) => {
|
|
|
52
46
|
return cbk();
|
|
53
47
|
},
|
|
54
48
|
|
|
55
|
-
// Derive request type
|
|
56
|
-
requestType: ['validate', ({}, cbk) => {
|
|
57
|
-
if (action === buyChannelAction) {
|
|
58
|
-
return cbk(null, serviceTypeRequestChannelSale);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
return cbk(null, serviceTypeRequestTrades);
|
|
62
|
-
}],
|
|
63
|
-
|
|
64
49
|
// Get trade
|
|
65
|
-
getTrade: ['
|
|
50
|
+
getTrade: ['validate', ({}, cbk) => {
|
|
66
51
|
return makePeerRequest({
|
|
67
52
|
lnd,
|
|
68
53
|
to,
|
|
69
54
|
records: [{type: tradeIdRecordType, value: id}],
|
|
70
55
|
timeout: requestTradeTimeoutMs,
|
|
71
|
-
type:
|
|
56
|
+
type: serviceTypeRequestTrades,
|
|
72
57
|
},
|
|
73
58
|
(err, res) => {
|
|
74
59
|
if (!!err) {
|
|
@@ -19,6 +19,7 @@ const sumOf = arr => arr.reduce((sum, n) => sum + n, 0);
|
|
|
19
19
|
|
|
20
20
|
{
|
|
21
21
|
lnd: <Authenticated LND API Object>
|
|
22
|
+
request: <Request Function>
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
// Returned details
|
|
@@ -65,7 +66,7 @@ const sumOf = arr => arr.reduce((sum, n) => sum + n, 0);
|
|
|
65
66
|
@returns
|
|
66
67
|
<EventEmitter Object>
|
|
67
68
|
*/
|
|
68
|
-
module.exports = ({lnd}) => {
|
|
69
|
+
module.exports = ({lnd, request}) => {
|
|
69
70
|
const emitter = new EventEmitter();
|
|
70
71
|
const listening = {};
|
|
71
72
|
const paging = {};
|
|
@@ -79,9 +80,11 @@ module.exports = ({lnd}) => {
|
|
|
79
80
|
|
|
80
81
|
const sub = serviceTradeRequests({
|
|
81
82
|
lnd,
|
|
83
|
+
request,
|
|
82
84
|
description: trade.description,
|
|
83
85
|
expires_at: trade.expires_at,
|
|
84
86
|
id: trade.id,
|
|
87
|
+
price: trade.price,
|
|
85
88
|
secret: trade.secret,
|
|
86
89
|
tokens: trade.tokens,
|
|
87
90
|
});
|
|
@@ -195,6 +198,7 @@ module.exports = ({lnd}) => {
|
|
|
195
198
|
.map(tradeFromInvoice)
|
|
196
199
|
.map(n => n.trade)
|
|
197
200
|
.filter(n => !!n)
|
|
201
|
+
.filter(n => !!n.description && !!n.secret)
|
|
198
202
|
.forEach(serviceTrade);
|
|
199
203
|
|
|
200
204
|
return cbk();
|