paid-services 3.3.0 → 3.6.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.
Files changed (54) hide show
  1. package/.prettierignore +2 -0
  2. package/CHANGELOG.md +17 -0
  3. package/capacity/accept_capacity_change.js +3 -3
  4. package/capacity/ask_for_change_details.js +34 -1
  5. package/capacity/capacity_change_requests.js +9 -0
  6. package/capacity/change_channel_capacity.js +7 -1
  7. package/capacity/encode_change_request.js +8 -1
  8. package/capacity/fee_for_replacement.js +1 -1
  9. package/capacity/get_capacity_change_requests.js +2 -1
  10. package/capacity/get_capacity_replacement.js +1 -1
  11. package/capacity/initiate_capacity_change.js +5 -5
  12. package/capacity/parse_capacity_change_request.js +8 -1
  13. package/capacity/propose_capacity_change.js +4 -1
  14. package/p2p/service_peer_requests.js +10 -2
  15. package/package.json +10 -9
  16. package/service_types.json +16 -0
  17. package/services/response_for_relay.js +0 -1
  18. package/test/capacity/test_capacity_change_requests.js +1 -0
  19. package/test/capacity/test_encode_change_request.js +5 -0
  20. package/test/capacity/test_parse_capacity_change_request.js +1 -0
  21. package/test/integration/test_accept_capacity_change.js +50 -14
  22. package/test/integration/test_change_channel_capacity.js +7 -1
  23. package/test/integration/test_decrease_channel_capacity.js +16 -7
  24. package/test/integration/test_increase_channel_capacity.js +4 -1
  25. package/test/trades/test_decode_basic_trade.js +40 -0
  26. package/test/trades/test_decode_open_trade.js +50 -0
  27. package/test/trades/test_encode_open_trade.js +35 -0
  28. package/test/trades/test_encode_trade.js +37 -0
  29. package/trades/accept_trade.js +61 -0
  30. package/trades/create_trade.js +149 -37
  31. package/trades/decode_anchored_trade.js +56 -0
  32. package/trades/decode_basic_trade.js +45 -0
  33. package/trades/decode_open_trade.js +69 -0
  34. package/trades/decode_trade.js +48 -66
  35. package/trades/decode_trade_secret.js +89 -0
  36. package/trades/encode_anchored_trade.js +35 -0
  37. package/trades/encode_open_trade.js +89 -0
  38. package/trades/encode_trade.js +48 -33
  39. package/trades/encode_trade_secret.js +50 -0
  40. package/trades/finalize_trade_secret.js +123 -0
  41. package/trades/find_trade.js +339 -0
  42. package/trades/manage_trade.js +61 -39
  43. package/trades/manage_trades.js +209 -2
  44. package/trades/network_from_network_record.js +3 -3
  45. package/trades/network_record_from_network.js +36 -0
  46. package/trades/network_record_from_request.js +2 -1
  47. package/trades/node_as_record.js +98 -0
  48. package/trades/record_as_node.js +113 -0
  49. package/trades/request_trade_by_id.js +95 -0
  50. package/trades/service_anchored_trades.js +181 -0
  51. package/trades/service_open_trade.js +172 -0
  52. package/trades/service_trade_requests.js +255 -0
  53. package/trades/trade_from_invoice.js +51 -0
  54. package/capacity/service_types.json +0 -6
@@ -0,0 +1,123 @@
1
+ const {createHash} = require('crypto');
2
+
3
+ const asyncAuto = require('async/auto');
4
+ const {createHodlInvoice} = require('ln-service');
5
+ const {createInvoice} = require('ln-service');
6
+ const {returnResult} = require('asyncjs-util');
7
+
8
+ const encodeTradeSecret = require('./encode_trade_secret');
9
+ const encryptTradeSecret = require('./encrypt_trade_secret');
10
+
11
+ const bufferAsHex = buffer => buffer.toString('hex');
12
+ const hexAsBuffer = hex => Buffer.from(hex, 'hex');
13
+ const sha256 = preimage => createHash('sha256').update(preimage).digest();
14
+ const utf8AsHex = utf8 => Buffer.from(utf8, 'utf8').toString('hex');
15
+
16
+ /** Create a trade secret for a node
17
+
18
+ {
19
+ description: <Trade Description String>
20
+ expires_at: <Trade Expires At ISO 8601 Date String>
21
+ is_hold: <Create Hold Invoice Bool>
22
+ lnd: <Authenticated LND API Object>
23
+ secret: <Clear Secret String>
24
+ to: <To Public Key Hex Encoded String>
25
+ tokens: <Price Tokens Number>
26
+ }
27
+
28
+ @returns via cbk or Promise
29
+ {
30
+ id: <Payment Hash Hex String>
31
+ secret: <Hex Encoded Payment Secret String>
32
+ trade: <Hex Encoded Trade String>
33
+ }
34
+ */
35
+ module.exports = (args, cbk) => {
36
+ return new Promise((resolve, reject) => {
37
+ return asyncAuto({
38
+ // Check arguments
39
+ validate: cbk => {
40
+ if (!args.description) {
41
+ return cbk([400, 'ExpectedDescriptionToFinalizeTradeSecret']);
42
+ }
43
+
44
+ if (!args.expires_at) {
45
+ return cbk([400, 'ExpectedExpiresAtDateToFinalizeTradeSecret']);
46
+ }
47
+
48
+ if (!args.lnd) {
49
+ return cbk([400, 'ExpectedAuthenticatedLndToFinalizeTradeSecret']);
50
+ }
51
+
52
+ if (!args.secret) {
53
+ return cbk([400, 'ExpectedSecretValueToFinalizeTradeSecret']);
54
+ }
55
+
56
+ if (!args.to) {
57
+ return cbk([400, 'ExpectedToPublicKeyToFinalizeTradeSecret']);
58
+ }
59
+
60
+ if (!args.tokens) {
61
+ return cbk([400, 'ExpectedTokensPriceToFinalizeTradeSecret']);
62
+ }
63
+
64
+ return cbk();
65
+ },
66
+
67
+ // Encrypt the secret data
68
+ encrypt: ['validate', ({}, cbk) => {
69
+ return encryptTradeSecret({
70
+ lnd: args.lnd,
71
+ secret: utf8AsHex(args.secret),
72
+ to: args.to,
73
+ },
74
+ cbk);
75
+ }],
76
+
77
+ // Create the invoice to purchase the unlocking secret
78
+ createInvoice: ['encrypt', ({encrypt}, cbk) => {
79
+ // Exit early when this is a hold invoice
80
+ if (!!args.is_hold) {
81
+ return createHodlInvoice({
82
+ description: args.description,
83
+ expires_at: args.expires_at,
84
+ id: bufferAsHex(sha256(hexAsBuffer(encrypt.payment_secret))),
85
+ lnd: args.lnd,
86
+ secret: encrypt.payment_secret,
87
+ tokens: args.tokens,
88
+ },
89
+ cbk);
90
+ }
91
+
92
+ return createInvoice({
93
+ description: args.description,
94
+ expires_at: args.expires_at,
95
+ lnd: args.lnd,
96
+ secret: encrypt.payment_secret,
97
+ tokens: args.tokens,
98
+ },
99
+ cbk);
100
+ }],
101
+
102
+ // Encode all the trade data into wire format
103
+ encode: ['createInvoice', 'encrypt', ({createInvoice, encrypt}, cbk) => {
104
+ try {
105
+ const {trade} = encodeTradeSecret({
106
+ auth: encrypt.trade_auth_tag,
107
+ payload: encrypt.trade_cipher,
108
+ request: createInvoice.request,
109
+ });
110
+
111
+ return cbk(null, {
112
+ trade,
113
+ id: createInvoice.id,
114
+ secret: encrypt.payment_secret,
115
+ });
116
+ } catch (err) {
117
+ return cbk([500, err.message]);
118
+ }
119
+ }],
120
+ },
121
+ returnResult({reject, resolve, of: 'encode'}, cbk));
122
+ });
123
+ };
@@ -0,0 +1,339 @@
1
+ const {randomBytes} = require('crypto');
2
+
3
+ const {addPeer} = require('ln-service');
4
+ const asyncAuto = require('async/auto');
5
+ const asyncDetect = require('async/detect');
6
+ const asyncDetectSeries = require('async/detectSeries');
7
+ const asyncMap = require('async/map');
8
+ const {getChannel} = require('ln-service');
9
+ const {getNode} = require('ln-service');
10
+ const {getPeers} = require('ln-service');
11
+ const {returnResult} = require('asyncjs-util');
12
+
13
+ const decodeBasicTrade = require('./decode_basic_trade');
14
+ const {makePeerRequest} = require('./../p2p');
15
+ const requestTradeById = require('./request_trade_by_id');
16
+ const {servicePeerRequests} = require('./../p2p');
17
+ const {serviceTypeReceiveTrades} = require('./../service_types');
18
+ const {serviceTypeRequestTrades} = require('./../service_types');
19
+
20
+ const findBasicRecord = records => records.find(n => n.type === '1');
21
+ const findIdRecord = records => records.find(n => n.type === '0');
22
+ const {isArray} = Array;
23
+ const makeRequestId = () => randomBytes(32).toString('hex');
24
+ const requestTradeType = '805005';
25
+ const requestTradesTimeoutMs = 1000 * 30;
26
+ const tradesRequestIdType = '1';
27
+ const uniq = arr => Array.from(new Set(arr));
28
+ const uniqBy = (a,b) => a.filter((e,i) => a.findIndex(n => n[b] == e[b]) == i);
29
+ const waitForTradesMs = 1000 * 5;
30
+
31
+ /** Find a trade to purchase
32
+
33
+ {
34
+ ask: <Inquirer Ask Function>
35
+ [id]: <Trade Id Encoded Hex String>
36
+ identity: <Own Node Identity Public Key Hex String>
37
+ lnd: <Authenticated LND API Object>
38
+ logger: <Winston Logger Object>
39
+ nodes: [{
40
+ [high_channel]: <High Key Channel Id String>
41
+ [low_channel]: <Low Key Channel Id String>
42
+ [node]: {
43
+ id: <Node Public Key Id Hex String>
44
+ sockets: [<Peer Socket String>]
45
+ }
46
+ }]
47
+ }
48
+
49
+ @returns via cbk or Promise
50
+ {
51
+ auth: <Encrypted Payload Auth Hex String>
52
+ payload: <Preimage Encrypted Payload Hex String>
53
+ request: <BOLT 11 Payment Request String>
54
+ trade: <Encoded Trade String>
55
+ }
56
+ */
57
+ module.exports = ({ask, id, identity, lnd, logger, nodes}, cbk) => {
58
+ return new Promise((resolve, reject) => {
59
+ return asyncAuto({
60
+ // Check arguments
61
+ validate: cbk => {
62
+ if (!ask) {
63
+ return cbk([400, 'ExpectedAskMethodToFindTrade']);
64
+ }
65
+
66
+ if (!identity) {
67
+ return cbk([400, 'ExpectedIdentityToFindTrade']);
68
+ }
69
+
70
+ if (!lnd) {
71
+ return cbk([400, 'ExpectedLndApiToFindTrade']);
72
+ }
73
+
74
+ if (!logger) {
75
+ return cbk([400, 'ExpectedLoggerObjectToFindTrade']);
76
+ }
77
+
78
+ if (!isArray(nodes)) {
79
+ return cbk([400, 'ExpectedNodesArrayToFindTrade']);
80
+ }
81
+
82
+ return cbk();
83
+ },
84
+
85
+ // Find node connect info to connect to
86
+ getNodes: ['validate', ({}, cbk) => {
87
+ return asyncMap(nodes, (connect, cbk) => {
88
+ // Exit early when the node is self
89
+ if (!!connect.node && connect.node.id === identity) {
90
+ return cbk();
91
+ }
92
+
93
+ // Exit early when the node id and sockets is specified directly
94
+ if (!!connect.node) {
95
+ return getNode({
96
+ lnd,
97
+ is_omitting_channels: true,
98
+ public_key: connect.node.id,
99
+ },
100
+ (err, res) => {
101
+ if (!!err) {
102
+ return cbk(null, connect.node);
103
+ }
104
+
105
+ const sockets = connect.node.sockets.map(n => n.socket);
106
+
107
+ return cbk(null, {
108
+ id: connect.node.id,
109
+ sockets: uniq([].concat(sockets).concat(connect.node.sockets)),
110
+ });
111
+ });
112
+ }
113
+
114
+ // Exit early when there is no landmark channel
115
+ if (!connect.high_channel && !connect.low_channel) {
116
+ return cbk();
117
+ }
118
+
119
+ const channelId = connect.high_channel || connect.low_channel;
120
+
121
+ // Get the public keys of the landmark channel
122
+ return getChannel({lnd, id: channelId}, (err, res) => {
123
+ // Exit early when the channel cannot be fetched
124
+ if (!!err) {
125
+ return cbk();
126
+ }
127
+
128
+ const [low, high] = res.policies.map(n => n.public_key);
129
+
130
+ // The node key is either the lower or the higher public key
131
+ const nodeId = !!connect.low_channel ? low : high;
132
+
133
+ // Exit early when the node is self
134
+ if (nodeId === identity) {
135
+ return cbk();
136
+ }
137
+
138
+ // Find the sockets for the node
139
+ return getNode({
140
+ lnd,
141
+ is_omitting_channels: true,
142
+ public_key: nodeId,
143
+ },
144
+ (err, res) => {
145
+ if (!!err) {
146
+ return cbk();
147
+ }
148
+
149
+ return cbk(null, {
150
+ id: nodeId,
151
+ sockets: res.sockets.map(n => n.socket),
152
+ });
153
+ });
154
+ });
155
+ },
156
+ cbk);
157
+ }],
158
+
159
+ // Get the list of connected peers
160
+ getPeers: ['validate', ({}, cbk) => getPeers({lnd}, cbk)],
161
+
162
+ // Try and connect to a node in order to do p2p messaging
163
+ connect: ['getNodes', 'getPeers', ({getNodes, getPeers}, cbk) => {
164
+ const connected = getPeers.peers.map(n => n.public_key);
165
+
166
+ // Look for a node that is already a connected peer
167
+ const [alreadyConnected] = getNodes.filter(node => {
168
+ return !!node && connected.includes(node.id);
169
+ });
170
+
171
+ // Exit early when already connected to a node
172
+ if (!!alreadyConnected) {
173
+ return cbk(null, alreadyConnected);
174
+ }
175
+
176
+ // Try and connect to a referenced node
177
+ return asyncDetect(getNodes.filter(n => !!n), (node, cbk) => {
178
+ logger.info({connecting_to: node.id});
179
+
180
+ // Attempt referenced sockets to establish p2p connection
181
+ return asyncDetectSeries(node.sockets, (socket, cbk) => {
182
+ return addPeer({lnd, socket, public_key: node.id}, err => {
183
+ // Stop trying sockets when there is no error
184
+ return cbk(null, !err);
185
+ });
186
+ },
187
+ (err, socket) => {
188
+ if (!!err) {
189
+ return cbk(err);
190
+ }
191
+
192
+ // The node is connected if one of the sockets worked
193
+ return cbk(null, !!socket);
194
+ });
195
+ },
196
+ cbk);
197
+ }],
198
+
199
+ // Node to request trades from
200
+ to: ['connect', ({connect}, cbk) => {
201
+ if (!connect) {
202
+ return cbk([503, 'FailedToConnectToNode']);
203
+ }
204
+
205
+ return cbk(null, connect.id);
206
+ }],
207
+
208
+ // Request a specific trade
209
+ requestTrade: ['to', ({to}, cbk) => {
210
+ // Exit early when this is an open ended trade request with no id
211
+ if (!id) {
212
+ return cbk();
213
+ }
214
+
215
+ return requestTradeById({id, lnd, to}, cbk);
216
+ }],
217
+
218
+ // Request an inventory of trades
219
+ requestTrades: ['to', ({to}, cbk) => {
220
+ // Exit early when this is a trade request for a specific id
221
+ if (!!id) {
222
+ return cbk();
223
+ }
224
+
225
+ const requestId = makeRequestId();
226
+ const service = servicePeerRequests({lnd});
227
+ const trades = [];
228
+
229
+ // When the requesting period is over, return the received trades
230
+ const finished = err => {
231
+ service.stop({});
232
+
233
+ return !!err ? cbk(err) : cbk(null, {trades});
234
+ };
235
+
236
+ // Listen for trades
237
+ service.request({type: serviceTypeReceiveTrades}, (req, res) => {
238
+ const requestIdRecord = findIdRecord(req.records);
239
+
240
+ // Exit early when this is a request for something else
241
+ if (!requestIdRecord || requestIdRecord.value !== requestId) {
242
+ return;
243
+ }
244
+
245
+ // Make sure there is a basic trade record in the records
246
+ if (!findBasicRecord(req.records)) {
247
+ return res.failure([400, 'ExpectedBasicTradeRecord']);
248
+ }
249
+
250
+ // Make sure the basic trade record is valid
251
+ try {
252
+ decodeBasicTrade({records: req.records});
253
+ } catch (err) {
254
+ return res.failure([400, 'ExpectedValidBasicTradeRecord']);
255
+ }
256
+
257
+ trades.push(decodeBasicTrade({records: req.records}));
258
+
259
+ return res.success({});
260
+ });
261
+
262
+ logger.info({requesting_trade_details: true});
263
+
264
+ // Once connected, ask for the trade details
265
+ return makePeerRequest({
266
+ lnd,
267
+ to,
268
+ records: [{type: tradesRequestIdType, value: requestId}],
269
+ timeout: requestTradesTimeoutMs,
270
+ type: serviceTypeRequestTrades,
271
+ },
272
+ (err, res) => {
273
+ if (!!err) {
274
+ return finished(err);
275
+ }
276
+
277
+ return setTimeout(finished, waitForTradesMs);
278
+ });
279
+ }],
280
+
281
+ // Select the desired basic trade
282
+ selectTrade: [
283
+ 'requestTrade',
284
+ 'requestTrades',
285
+ ({requestTrade, requestTrades}, cbk) =>
286
+ {
287
+ // Exit early when the trade was already selected
288
+ if (!!requestTrade) {
289
+ return cbk();
290
+ }
291
+
292
+ if (!requestTrades.trades.length) {
293
+ return cbk([404, 'NoTradesFound']);
294
+ }
295
+
296
+ const uniqueTrades = uniqBy(requestTrades.trades, 'description');
297
+
298
+ const [trade, other] = uniqueTrades;
299
+
300
+ // Exit early when there is only a single trade
301
+ if (!other) {
302
+ return cbk(null, trade);
303
+ }
304
+
305
+ // Present the possible choices
306
+ return ask({
307
+ choices: uniqueTrades.map(trade => ({
308
+ name: trade.description,
309
+ value: trade.id,
310
+ })),
311
+ message: 'What would you like to buy?',
312
+ name: 'id',
313
+ type: 'list',
314
+ },
315
+ cbk);
316
+ }],
317
+
318
+ // Fetch the full trade-secret that was selected
319
+ fetchSelectedTrade: ['selectTrade', 'to', ({selectTrade, to}, cbk) => {
320
+ // Exit early when trade is already known
321
+ if (!selectTrade) {
322
+ return cbk();
323
+ }
324
+
325
+ return requestTradeById({lnd, to, id: selectTrade.id}, cbk);
326
+ }],
327
+
328
+ // Final trade details
329
+ trade: [
330
+ 'fetchSelectedTrade',
331
+ 'requestTrade',
332
+ ({fetchSelectedTrade, requestTrade}, cbk) =>
333
+ {
334
+ return cbk(null, fetchSelectedTrade || requestTrade);
335
+ }],
336
+ },
337
+ returnResult({reject, resolve, of: 'trade'}, cbk));
338
+ });
339
+ };
@@ -11,10 +11,12 @@ 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;
17
18
  const isHexPreimage = n => !!n && /^[0-9A-F]{64}$/i.test(n);
19
+ const tokensAsBigUnit = tokens => (tokens / 1e8).toFixed(8);
18
20
 
19
21
  /** Manage an individual trade
20
22
 
@@ -52,13 +54,7 @@ module.exports = ({ask, lnd, logger}, cbk) => {
52
54
  name: 'trade',
53
55
  message: 'Enter encoded trade',
54
56
  type: 'input',
55
- validate: input => {
56
- if (!input) {
57
- return false;
58
- }
59
-
60
- return true;
61
- },
57
+ validate: input => !!input,
62
58
  },
63
59
  cbk);
64
60
  }],
@@ -71,22 +67,43 @@ module.exports = ({ask, lnd, logger}, cbk) => {
71
67
  try {
72
68
  const details = decodeTrade({trade: askForTrade.trade});
73
69
 
74
- return cbk(null, {
75
- auth: details.auth,
76
- payload: details.payload,
77
- request: details.request,
78
- });
70
+ return cbk(null, details);
79
71
  } catch (err) {
80
72
  return cbk([400, err.message]);
81
73
  }
82
74
  }],
83
75
 
84
- // Parse the trade payment request
85
- requestDetails: ['decodeDetails', ({decodeDetails}, cbk) => {
86
- const {request} = decodeDetails;
76
+ // Get details about an open ended trade
77
+ findTrade: [
78
+ 'decodeDetails',
79
+ 'getIdentity',
80
+ ({decodeDetails, getIdentity}, cbk) =>
81
+ {
82
+ // Exit early when there is a known trade
83
+ if (!!decodeDetails.secret) {
84
+ return cbk(null, {
85
+ auth: decodeDetails.secret.auth,
86
+ payload: decodeDetails.secret.payload,
87
+ request: decodeDetails.secret.request,
88
+ });
89
+ }
87
90
 
91
+ // Get the trade details interactively
92
+ return findTrade({
93
+ ask,
94
+ lnd,
95
+ logger,
96
+ id: decodeDetails.connect.id,
97
+ identity: getIdentity.public_key,
98
+ nodes: decodeDetails.connect.nodes,
99
+ },
100
+ cbk);
101
+ }],
102
+
103
+ // Parse the trade payment request
104
+ requestDetails: ['findTrade', ({findTrade}, cbk) => {
88
105
  try {
89
- return cbk(null, parsePaymentRequest({request}));
106
+ return cbk(null, parsePaymentRequest({request: findTrade.request}));
90
107
  } catch (err) {
91
108
  return cbk([400, err.message]);
92
109
  }
@@ -125,7 +142,7 @@ module.exports = ({ask, lnd, logger}, cbk) => {
125
142
  logger.info({
126
143
  id: requestDetails.id,
127
144
  offering: requestDetails.description,
128
- price: requestDetails.tokens,
145
+ price: tokensAsBigUnit(requestDetails.tokens),
129
146
  is_canceled: invoice.is_canceled || undefined,
130
147
  is_purchased: invoice.is_confirmed || undefined,
131
148
  });
@@ -153,7 +170,7 @@ module.exports = ({ask, lnd, logger}, cbk) => {
153
170
  logger.info({
154
171
  id: requestDetails.id,
155
172
  offering: requestDetails.description,
156
- price: requestDetails.tokens,
173
+ price: tokensAsBigUnit(requestDetails.tokens),
157
174
  });
158
175
 
159
176
  return ask({
@@ -179,16 +196,24 @@ module.exports = ({ask, lnd, logger}, cbk) => {
179
196
  return cbk();
180
197
  }
181
198
 
182
- return cancelHodlInvoice({lnd, id: requestDetails.id}, cbk);
199
+ return cancelHodlInvoice({lnd, id: requestDetails.id}, err => {
200
+ if (!!err) {
201
+ return cbk(err);
202
+ }
203
+
204
+ logger.info({trade_canceled: true});
205
+
206
+ return cbk();
207
+ });
183
208
  }],
184
209
 
185
210
  // Select a purchase option for the trade
186
211
  selectPurchaseAction: [
187
- 'decodeDetails',
212
+ 'findTrade',
188
213
  'getPurchase',
189
214
  'getRequest',
190
215
  'requestDetails',
191
- ({decodeDetails, getPurchase, getRequest, requestDetails}, cbk) =>
216
+ ({findTrade, getPurchase, getRequest, requestDetails}, cbk) =>
192
217
  {
193
218
  // Exit early when the trade was already purchased
194
219
  if (!!getPurchase.value && !!getPurchase.value.is_confirmed) {
@@ -200,10 +225,12 @@ module.exports = ({ask, lnd, logger}, cbk) => {
200
225
  return cbk();
201
226
  }
202
227
 
228
+ logger.info({trade: findTrade.trade});
229
+
203
230
  logger.info({
204
- request: decodeDetails.request,
231
+ request: findTrade.request,
205
232
  purchase: requestDetails.description,
206
- price: requestDetails.tokens,
233
+ price: tokensAsBigUnit(requestDetails.tokens),
207
234
  to: requestDetails.destination,
208
235
  });
209
236
 
@@ -257,9 +284,9 @@ module.exports = ({ask, lnd, logger}, cbk) => {
257
284
 
258
285
  // Pay and get the preimage through paying for it
259
286
  payForPreimage: [
260
- 'decodeDetails',
287
+ 'findTrade',
261
288
  'selectPurchaseAction',
262
- ({decodeDetails, selectPurchaseAction}, cbk) =>
289
+ ({findTrade, selectPurchaseAction}, cbk) =>
263
290
  {
264
291
  // Exit early when this is an offer
265
292
  if (!selectPurchaseAction) {
@@ -271,32 +298,25 @@ module.exports = ({ask, lnd, logger}, cbk) => {
271
298
  return cbk();
272
299
  }
273
300
 
301
+ const {request} = findTrade;
302
+
274
303
  return asyncRetry({
275
304
  errorFilter: err => !!isArray(err) && err.slice().shift() >= 500,
276
305
  },
277
- cbk => {
278
- return buyPreimage({
279
- ask,
280
- lnd,
281
- logger,
282
- request: decodeDetails.request,
283
- },
284
- cbk);
285
- },
286
- cbk);
306
+ cbk => buyPreimage({ask, lnd, logger, request}, cbk), cbk);
287
307
  }],
288
308
 
289
309
  // Use the preimage to decrypt the trade secret
290
310
  decryptSecret: [
291
311
  'askForPreimage',
292
- 'decodeDetails',
312
+ 'findTrade',
293
313
  'getPurchase',
294
314
  'payForPreimage',
295
315
  'requestDetails',
296
316
  'selectPurchaseAction',
297
317
  ({
298
318
  askForPreimage,
299
- decodeDetails,
319
+ findTrade,
300
320
  getPurchase,
301
321
  payForPreimage,
302
322
  requestDetails,
@@ -327,11 +347,13 @@ module.exports = ({ask, lnd, logger}, cbk) => {
327
347
 
328
348
  const paid = payForPreimage || askForPreimage || payment;
329
349
 
350
+ const {auth, payload} = findTrade;
351
+
330
352
  return decryptTradeSecret({
353
+ auth,
331
354
  lnd,
332
- auth: decodeDetails.auth,
355
+ payload,
333
356
  from: requestDetails.destination,
334
- payload: decodeDetails.payload,
335
357
  secret: paid.secret,
336
358
  },
337
359
  cbk);