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.
@@ -1,56 +1,50 @@
1
- const {randomBytes} = require('crypto');
2
-
3
1
  const asyncAuto = require('async/auto');
4
- const asyncReflect = require('async/reflect');
5
- const {getChainFeeRate} = require('ln-service');
2
+ const {getChainBalance} = require('ln-service');
6
3
  const {getChannels} = require('ln-service');
7
4
  const {getNetwork} = require('ln-sync');
8
5
  const {getWalletInfo} = require('ln-service');
9
- const {signMessage} = require('ln-service');
10
6
  const {returnResult} = require('asyncjs-util');
11
7
 
8
+ const convertFiat = require('./convert_fiat');
12
9
  const createAnchoredTrade = require('./create_anchored_trade');
13
10
  const serviceOpenTrade = require('./service_open_trade');
14
11
 
15
12
  const asNumber = n => parseFloat(n, 10);
16
13
  const daysAsMs = days => Number(days) * 1000 * 60 * 60 * 24;
14
+ const defaultChannelSize = 5000000;
17
15
  const defaultExpirationDays = 1;
16
+ const {floor} = Math;
18
17
  const futureDate = ms => new Date(Date.now() + ms).toISOString();
19
18
  const isNumber = n => !isNaN(n);
19
+ const {min} = Math;
20
+ const minChannelSize = 20000;
21
+ const ppmCost = (amount, rate) => Math.ceil(amount * rate / 1000000);
22
+ const priceFiat = 'price-in-fiat';
23
+ const pricePpm = 'price-in-ppm';
24
+ const priceTokens = 'price-in-tokens';
20
25
  const query = 'How much would you like to sell?';
21
- const saleCost = (amount, rate) => (amount * rate / 1000000).toFixed(0);
22
- const saleSecret = randomBytes(48).toString('hex');
23
- const tradeDescription = (alias, tokens) => `channelsale:${alias}-${tokens}`;
26
+ const usdAsPrice = usd => `${usd}*USD`;
24
27
 
25
28
  /** Create a new channel sale
26
29
 
27
30
  {
28
- action: <Channel Sale Action String>
29
31
  ask: <Ask Function>
30
- balance: <Total Available Chain Confirmed Balance Tokens Number>
31
32
  lnd: <Authenticated LND API Object>
32
33
  logger: <Winston Logger Object>
34
+ request: <Request Function>
33
35
  }
34
36
 
35
37
  @returns via cbk or Promise
36
38
  */
37
- module.exports = ({action, ask, balance, lnd, logger}, cbk) => {
39
+ module.exports = ({ask, lnd, logger, request}, cbk) => {
38
40
  return new Promise((resolve, reject) => {
39
41
  return asyncAuto({
40
42
  // Check arguments
41
43
  validate: cbk => {
42
- if (!action) {
43
- return cbk([400, 'ExpectedActionTypeToCreateChannelSale']);
44
- }
45
-
46
44
  if (!ask) {
47
45
  return cbk([400, 'ExpectedAskFunctionToCreateChannelSale']);
48
46
  }
49
47
 
50
- if (balance === undefined) {
51
- return cbk([400, 'ExpectedOnChainBalanceToCreateChannelSale']);
52
- }
53
-
54
48
  if (!lnd) {
55
49
  return cbk([400, 'ExpectedLndToCreateChannelSale']);
56
50
  }
@@ -59,9 +53,16 @@ module.exports = ({action, ask, balance, lnd, logger}, cbk) => {
59
53
  return cbk([400, 'ExpectedLoggerToCreateChannelSale']);
60
54
  }
61
55
 
56
+ if (!request) {
57
+ return cbk([400, 'ExpectedRequestFunctionToCreateChannelSale']);
58
+ }
59
+
62
60
  return cbk();
63
61
  },
64
62
 
63
+ // Get the current chain balance to set the limit for a channel sale
64
+ getBalance: ['validate', ({}, cbk) => getChainBalance({lnd}, cbk)],
65
+
65
66
  // Get the public channels to use for an open trade
66
67
  getChannels: ['validate', ({}, cbk) => {
67
68
  return getChannels({lnd, is_public: true}, cbk);
@@ -73,10 +74,15 @@ module.exports = ({action, ask, balance, lnd, logger}, cbk) => {
73
74
  // Get the network name to use for an open trade
74
75
  getNetwork: ['validate', ({}, cbk) => getNetwork({lnd}, cbk)],
75
76
 
76
- // Ask for sale amount
77
- askForAmount: ['validate', ({}, cbk) => {
77
+ // Ask for channel capacity to sell
78
+ askForAmount: ['getBalance', ({getBalance}, cbk) => {
79
+ if (getBalance.chain_balance < minChannelSize) {
80
+ return cbk([400, 'InsufficientOnChainFundsToSellChannel']);
81
+ }
82
+
78
83
  return ask({
79
- message: `${query} (Available balance: ${balance})`,
84
+ default: min(defaultChannelSize, getBalance.chain_balance),
85
+ message: `${query} (Available balance: ${getBalance.chain_balance})`,
80
86
  name: 'amount',
81
87
  type: 'input',
82
88
  validate: input => {
@@ -86,31 +92,56 @@ module.exports = ({action, ask, balance, lnd, logger}, cbk) => {
86
92
 
87
93
  // The token amount should be numeric
88
94
  if (!isNumber(input)) {
89
- return 'Expected numeric amount for sale';
95
+ return 'Expected numeric amount for channel capacity';
90
96
  }
91
97
 
92
- if (input > balance) {
93
- return 'Sale amount cannot be more than available balance';
98
+ // Avoid listing more coins than are present on-chain
99
+ if (Number(input) > getBalance.chain_balance) {
100
+ return 'Capacity cannot be more than available balance';
101
+ }
102
+
103
+ if (Number(input) < minChannelSize) {
104
+ return `Channel capacity must be larger than ${minChannelSize}`;
105
+ }
106
+
107
+ // Disallow fractional values
108
+ if (!!isNumber(input) && floor(input) !== asNumber(input)) {
109
+ return 'Decimal capacities are not supported';
94
110
  }
95
111
 
96
112
  return true;
97
113
  },
98
114
  },
99
- (err, result) => {
100
- if (!!err) {
101
- return cbk([503, 'UnexpectedErrorAskingForSaleAmount', {err}]);
102
- }
115
+ cbk);
116
+ }],
103
117
 
104
- return cbk(null, result);
105
- });
118
+ // Select method of pricing
119
+ selectPricing: ['askForAmount', ({}, cbk) => {
120
+ return ask({
121
+ choices: [
122
+ {name: 'Set absolute price', value: priceTokens},
123
+ {name: 'Set price by PPM (parts per million)', value: pricePpm},
124
+ {name: 'Set price in fiat (USD)', value: priceFiat},
125
+ ],
126
+ default: pricePpm,
127
+ message: '?',
128
+ name: 'action',
129
+ type: 'list',
130
+ },
131
+ cbk);
106
132
  }],
107
133
 
108
- // Ask for the rate
109
- askForRate: ['askForAmount', ({}, cbk) => {
134
+ // Ask for fiat based cost
135
+ askForFiat: ['selectPricing', ({selectPricing}, cbk) => {
136
+ // Exit early when the pricing is not in fiat
137
+ if (selectPricing.action !== priceFiat) {
138
+ return cbk();
139
+ }
140
+
110
141
  return ask({
111
- default: '1',
112
- message: 'Price of channel (in ppm)?',
113
- name: 'rate',
142
+ default: '0.01',
143
+ message: 'Dollars USD to charge?',
144
+ name: 'usd',
114
145
  type: 'input',
115
146
  validate: input => {
116
147
  if (!input) {
@@ -119,23 +150,83 @@ module.exports = ({action, ask, balance, lnd, logger}, cbk) => {
119
150
 
120
151
  // Price of sale should be numeric
121
152
  if (!isNumber(input)) {
122
- return 'Expected numeric fee rate for sale';
153
+ return 'Not a number of dollars, try a number?';
123
154
  }
124
155
 
125
156
  return true;
126
157
  },
127
158
  },
128
- (err, result) => {
129
- if (!!err) {
130
- return cbk([503, 'UnexpectedErrorAskingForRate', err]);
131
- }
159
+ cbk);
160
+ }],
161
+
162
+ // Ask for absolute cost
163
+ askForPrice: ['selectPricing', ({selectPricing}, cbk) => {
164
+ // Exit early when the pricing is not absolute
165
+ if (selectPricing.action !== priceTokens) {
166
+ return cbk();
167
+ }
168
+
169
+ return ask({
170
+ default: '1337',
171
+ message: 'Amount to charge?',
172
+ name: 'tokens',
173
+ type: 'input',
174
+ validate: input => {
175
+ if (!input) {
176
+ return false;
177
+ }
178
+
179
+ // Price of sale should be numeric
180
+ if (!isNumber(input)) {
181
+ return 'Not a number, try a number?';
182
+ }
183
+
184
+ // Disallow fractional values
185
+ if (!!isNumber(input) && floor(input) !== asNumber(input)) {
186
+ return 'Specified precision not supported';
187
+ }
132
188
 
133
- return cbk(null, result);
134
- });
189
+ return true;
190
+ },
191
+ },
192
+ cbk);
193
+ }],
194
+
195
+ // Ask for rate-based cost
196
+ askForRate: ['askForAmount', 'selectPricing', ({selectPricing}, cbk) => {
197
+ // Exit early when the pricing is not in ppm
198
+ if (selectPricing.action !== pricePpm) {
199
+ return cbk();
200
+ }
201
+
202
+ return ask({
203
+ default: '350',
204
+ message: 'Price in PPM?',
205
+ name: 'rate',
206
+ type: 'input',
207
+ validate: input => {
208
+ if (!input) {
209
+ return false;
210
+ }
211
+
212
+ // Price of sale should be in numeric ppm
213
+ if (!isNumber(input)) {
214
+ return 'Unable to parse rate, try a numeric ppm rate?';
215
+ }
216
+
217
+ // Disallow fractional values
218
+ if (!!isNumber(input) && floor(input) !== asNumber(input)) {
219
+ return 'Specified precision not supported';
220
+ }
221
+
222
+ return true;
223
+ },
224
+ },
225
+ cbk);
135
226
  }],
136
227
 
137
228
  // Ask for the expiration of the channel sale
138
- askForExpiration: ['askForRate', ({}, cbk) => {
229
+ askForDays: ['askForFiat', 'askForPrice', 'askForRate', ({}, cbk) => {
139
230
  return ask({
140
231
  default: defaultExpirationDays,
141
232
  name: 'days',
@@ -151,40 +242,54 @@ module.exports = ({action, ask, balance, lnd, logger}, cbk) => {
151
242
  cbk);
152
243
  }],
153
244
 
154
- // Calculate sale cost
155
- saleCost: [
156
- 'askForAmount',
157
- 'askForRate',
158
- ({askForRate, askForAmount}, cbk) =>
159
- {
160
- return cbk(null, saleCost(askForAmount.amount, askForRate.rate));
245
+ // Check ability to get fiat prices
246
+ checkCostLookup: ['askForFiat', ({askForFiat}, cbk) => {
247
+ // Exit early when no fiat is referenced
248
+ if (!askForFiat) {
249
+ return cbk();
250
+ }
251
+
252
+ return convertFiat({request, price: usdAsPrice(askForFiat.usd)}, cbk);
161
253
  }],
162
254
 
163
- // Description of sale
164
- description: [
255
+ // Determine the tokens value of the trade
256
+ cost: [
165
257
  'askForAmount',
166
- 'getIdentity',
167
- ({askForAmount, getIdentity}, cbk) =>
258
+ 'askForFiat',
259
+ 'askForPrice',
260
+ 'askForRate',
261
+ ({askForAmount, askForFiat, askForPrice, askForRate}, cbk) =>
168
262
  {
169
- const alias = getIdentity.alias || getIdentity.public_key;
263
+ // Exit early when price is in fiat, not tokens
264
+ if (!!askForFiat) {
265
+ return cbk(null, {price: usdAsPrice(askForFiat.usd)});
266
+ }
170
267
 
171
- return cbk(null, tradeDescription(alias, askForAmount.amount));
268
+ // Exit early when the price is specified directly
269
+ if (!!askForPrice) {
270
+ return cbk(null, {tokens: askForPrice.tokens});
271
+ }
272
+
273
+ // Calculate the rate that was specified in PPM
274
+ const tokens = ppmCost(Number(askForAmount.amount), askForRate.rate);
275
+
276
+ return cbk(null, {tokens});
172
277
  }],
173
278
 
174
279
  // Create an anchor invoice for the channel sale
175
280
  createAnchor: [
176
- 'askForExpiration',
177
- 'askForRate',
178
- 'description',
179
- 'saleCost',
180
- ({askForExpiration, description, saleCost}, cbk) =>
281
+ 'askForAmount',
282
+ 'askForDays',
283
+ 'checkCostLookup',
284
+ 'cost',
285
+ ({askForAmount, askForDays, askForRate, cost}, cbk) =>
181
286
  {
182
287
  return createAnchoredTrade({
183
- description,
184
288
  lnd,
185
- expires_at: futureDate(daysAsMs(askForExpiration.days)),
186
- secret: saleSecret,
187
- tokens: asNumber(saleCost),
289
+ channel: Number(askForAmount.amount),
290
+ expires_at: futureDate(daysAsMs(askForDays.days)),
291
+ price: cost.price,
292
+ tokens: cost.tokens,
188
293
  },
189
294
  cbk);
190
295
  }],
@@ -192,37 +297,36 @@ module.exports = ({action, ask, balance, lnd, logger}, cbk) => {
192
297
  // Wait for a peer to connect and ask for the channel sale details
193
298
  serviceSaleRequests: [
194
299
  'askForAmount',
195
- 'askForExpiration',
300
+ 'askForDays',
301
+ 'cost',
196
302
  'createAnchor',
197
- 'description',
198
303
  'getChannels',
199
304
  'getNetwork',
200
305
  'getIdentity',
201
306
  ({
202
307
  askForAmount,
203
- askForExpiration,
308
+ askForDays,
309
+ askForRate,
310
+ cost,
204
311
  createAnchor,
205
- description,
206
312
  getChannels,
207
313
  getNetwork,
208
314
  getIdentity,
209
- saleCost,
210
315
  },
211
316
  cbk) =>
212
317
  {
213
318
  return serviceOpenTrade({
214
- action,
215
- description,
216
319
  lnd,
217
320
  logger,
218
- capacity: askForAmount.amount,
321
+ request,
322
+ channel: Number(askForAmount.amount),
219
323
  channels: getChannels.channels,
220
- expires_at: futureDate(daysAsMs(askForExpiration.days)),
324
+ expires_at: futureDate(daysAsMs(askForDays.days)),
221
325
  id: createAnchor.id,
222
326
  network: getNetwork.network,
327
+ price: cost.price,
223
328
  public_key: getIdentity.public_key,
224
- secret: saleSecret,
225
- tokens: asNumber(saleCost),
329
+ tokens: cost.tokens,
226
330
  uris: (getIdentity.uris || []),
227
331
  },
228
332
  cbk);
@@ -4,20 +4,25 @@ const {getNetwork} = require('ln-sync');
4
4
  const {getWalletInfo} = require('ln-service');
5
5
  const {returnResult} = require('asyncjs-util');
6
6
 
7
+ const convertFiat = require('./convert_fiat');
7
8
  const createAnchoredTrade = require('./create_anchored_trade');
8
- const finalizeTradeSecret = require('./finalize_trade_secret');
9
+ const finalizeTrade = require('./finalize_trade');
9
10
  const serviceOpenTrade = require('./service_open_trade');
10
11
 
11
12
  const asNumber = n => parseFloat(n, 10);
12
13
  const daysAsMs = days => Number(days) * 1000 * 60 * 60 * 24;
13
- const defaultExpirationDays = 14;
14
+ const defaultExpirationDays = 1;
15
+ const defaultFiatInvoiceExpiryMs = 1000 * 60 * 30;
14
16
  const {floor} = Math;
15
17
  const futureDate = ms => new Date(Date.now() + ms).toISOString();
16
18
  const isNumber = n => !isNaN(n);
17
19
  const isPublicKey = n => !!n && /^0[2-3][0-9A-F]{64}$/i.test(n);
18
20
  const maxDescriptionLength = 100;
19
21
  const maxSecretLength = 100;
22
+ const priceFiat = 'set-price-fiat';
23
+ const priceTokens = 'set-price-tokens';
20
24
  const uriAsSocket = n => n.substring(67);
25
+ const usdAsPrice = ({usd}) => `${usd}*USD`;
21
26
  const utf8AsHex = utf8 => Buffer.from(utf8).toString('hex');
22
27
 
23
28
  /** Create a new trade
@@ -26,6 +31,7 @@ const utf8AsHex = utf8 => Buffer.from(utf8).toString('hex');
26
31
  ask: <Ask Function>
27
32
  lnd: <Authenticated LND API Object>
28
33
  logger: <Winston Logger Object>
34
+ request: <Request Function>
29
35
  }
30
36
 
31
37
  @returns via cbk or Promise
@@ -33,7 +39,7 @@ const utf8AsHex = utf8 => Buffer.from(utf8).toString('hex');
33
39
  trade: <Hex Encoded Trade String>
34
40
  }
35
41
  */
36
- module.exports = ({ask, lnd, logger}, cbk) => {
42
+ module.exports = ({ask, lnd, logger, request}, cbk) => {
37
43
  return new Promise((resolve, reject) => {
38
44
  return asyncAuto({
39
45
  // Check arguments
@@ -50,6 +56,10 @@ module.exports = ({ask, lnd, logger}, cbk) => {
50
56
  return cbk([400, 'ExpectedWinstonLoggerToCreateTrade']);
51
57
  }
52
58
 
59
+ if (!request) {
60
+ return cbk([400, 'ExpectedRequestFunctionToCreateTrade']);
61
+ }
62
+
53
63
  return cbk();
54
64
  },
55
65
 
@@ -126,7 +136,7 @@ module.exports = ({ask, lnd, logger}, cbk) => {
126
136
  askForSecret: ['askForDescription', ({askForDescription}, cbk) => {
127
137
  return ask({
128
138
  name: 'secret',
129
- message: 'Enter the secret you want to sell',
139
+ message: 'What is the secret you want to sell?',
130
140
  type: 'input',
131
141
  validate: input => {
132
142
  if (!input) {
@@ -143,19 +153,81 @@ module.exports = ({ask, lnd, logger}, cbk) => {
143
153
  cbk);
144
154
  }],
145
155
 
156
+ // Select pricing type
157
+ selectPriceType: [
158
+ 'askForNodeId',
159
+ 'askForSecret',
160
+ ({askForNodeId}, cbk) =>
161
+ {
162
+ // Exit early and force absolute price when this is a direct trade
163
+ if (!!askForNodeId.id) {
164
+ return cbk(null, {type: priceTokens});
165
+ }
166
+
167
+ return ask({
168
+ choices: [
169
+ {name: 'Set absolute price', value: priceTokens},
170
+ {name: 'Set dynamic price in fiat terms (USD)', value: priceFiat},
171
+ ],
172
+ message: '?',
173
+ name: 'type',
174
+ type: 'list',
175
+ },
176
+ cbk);
177
+ }],
178
+
179
+ // Ask for the fiat price of the secret
180
+ askForFiatPrice: ['selectPriceType', ({selectPriceType}, cbk) => {
181
+ // Exit early when not setting a fiat price
182
+ if (selectPriceType.type !== priceFiat) {
183
+ return cbk();
184
+ }
185
+
186
+ return ask({
187
+ default: '0.01',
188
+ message: 'Dollars USD to charge?',
189
+ name: 'usd',
190
+ type: 'input',
191
+ validate: input => {
192
+ if (!input) {
193
+ return false;
194
+ }
195
+
196
+ // Price of sale should be numeric
197
+ if (!isNumber(input)) {
198
+ return 'Not a number of dollars, try a number?';
199
+ }
200
+
201
+ return true;
202
+ },
203
+ },
204
+ cbk);
205
+ }],
206
+
146
207
  // Ask for the price of the secret
147
- askForPrice: ['askForSecret', ({}, cbk) => {
208
+ askForTokensPrice: ['selectPriceType', ({selectPriceType}, cbk) => {
209
+ // Exit early when not asking for an absolute price
210
+ if (selectPriceType.type !== priceTokens) {
211
+ return cbk();
212
+ }
213
+
148
214
  return ask({
215
+ default: '1',
216
+ message: 'Amount to charge?',
149
217
  name: 'tokens',
150
- message: 'How much do you want to charge?',
218
+ type: 'input',
151
219
  validate: input => {
152
- // Only allow numeric input
153
- if (!isNumber(input)) {
220
+ if (!input) {
154
221
  return false;
155
222
  }
156
223
 
224
+ // Price of sale should be numeric
225
+ if (!isNumber(input)) {
226
+ return 'Not a number, try a number?';
227
+ }
228
+
157
229
  // Disallow fractional values
158
- if (floor(input) !== asNumber(input)) {
230
+ if (!!isNumber(input) && floor(input) !== asNumber(input)) {
159
231
  return 'Specified precision not supported';
160
232
  }
161
233
 
@@ -166,12 +238,13 @@ module.exports = ({ask, lnd, logger}, cbk) => {
166
238
  }],
167
239
 
168
240
  // Ask for the expiration of the trade
169
- askForExpiration: ['askForPrice', ({}, cbk) => {
241
+ askForExpiration: ['askForFiatPrice', 'askForTokensPrice', ({}, cbk) => {
170
242
  return ask({
171
243
  default: defaultExpirationDays,
172
244
  name: 'days',
173
245
  message: 'Days to offer this for?',
174
246
  validate: input => {
247
+ // Days must be a number
175
248
  if (!isNumber(input) || !Number(input)) {
176
249
  return false;
177
250
  }
@@ -182,19 +255,33 @@ module.exports = ({ask, lnd, logger}, cbk) => {
182
255
  cbk);
183
256
  }],
184
257
 
258
+ // Get the conversion to tokens for fiat
259
+ getTokens: ['askForFiatPrice', ({askForFiatPrice}, cbk) => {
260
+ // Exit early if not using fiat
261
+ if (!askForFiatPrice) {
262
+ return cbk();
263
+ }
264
+
265
+ // Check that the fiat price can be converted
266
+ return convertFiat({request, price: usdAsPrice(askForFiatPrice)}, cbk);
267
+ }],
268
+
185
269
  // Create an anchor invoice for the trade
186
270
  createAnchor: [
187
271
  'askForDescription',
188
272
  'askForExpiration',
273
+ 'askForFiatPrice',
189
274
  'askForNodeId',
190
- 'askForPrice',
191
275
  'askForSecret',
276
+ 'askForTokensPrice',
277
+ 'getTokens',
192
278
  ({
193
279
  askForDescription,
194
280
  askForExpiration,
281
+ askForFiatPrice,
195
282
  askForNodeId,
196
- askForPrice,
197
283
  askForSecret,
284
+ askForTokensPrice,
198
285
  },
199
286
  cbk) =>
200
287
  {
@@ -203,12 +290,16 @@ module.exports = ({ask, lnd, logger}, cbk) => {
203
290
  return cbk();
204
291
  }
205
292
 
293
+ // Tokens may be undefined when fiat price is set
294
+ const {tokens} = !!askForTokensPrice ? askForTokensPrice : {};
295
+
206
296
  return createAnchoredTrade({
207
297
  lnd,
298
+ tokens,
208
299
  description: askForDescription.description,
209
300
  expires_at: futureDate(daysAsMs(askForExpiration.days)),
301
+ price: !!askForFiatPrice ? usdAsPrice(askForFiatPrice) : undefined,
210
302
  secret: askForSecret.secret,
211
- tokens: asNumber(askForPrice.tokens),
212
303
  },
213
304
  cbk);
214
305
  }],
@@ -217,9 +308,10 @@ module.exports = ({ask, lnd, logger}, cbk) => {
217
308
  serviceTradeRequests: [
218
309
  'askForDescription',
219
310
  'askForExpiration',
311
+ 'askForFiatPrice',
220
312
  'askForNodeId',
221
- 'askForPrice',
222
313
  'askForSecret',
314
+ 'askForTokensPrice',
223
315
  'createAnchor',
224
316
  'getChannels',
225
317
  'getIdentity',
@@ -227,9 +319,10 @@ module.exports = ({ask, lnd, logger}, cbk) => {
227
319
  ({
228
320
  askForDescription,
229
321
  askForExpiration,
322
+ askForFiatPrice,
230
323
  askForNodeId,
231
- askForPrice,
232
324
  askForSecret,
325
+ askForTokensPrice,
233
326
  createAnchor,
234
327
  getChannels,
235
328
  getIdentity,
@@ -245,14 +338,16 @@ module.exports = ({ask, lnd, logger}, cbk) => {
245
338
  return serviceOpenTrade({
246
339
  lnd,
247
340
  logger,
341
+ request,
248
342
  channels: getChannels.channels,
249
343
  description: askForDescription.description,
250
344
  expires_at: futureDate(daysAsMs(askForExpiration.days)),
251
345
  id: createAnchor.id,
252
346
  network: getNetwork.network,
347
+ price: !!askForFiatPrice ? usdAsPrice(askForFiatPrice) : undefined,
253
348
  public_key: getIdentity.public_key,
254
349
  secret: askForSecret.secret,
255
- tokens: asNumber(askForPrice.tokens),
350
+ tokens: (!!askForTokensPrice ? askForTokensPrice : {}).tokens,
256
351
  uris: (getIdentity.uris || []),
257
352
  },
258
353
  cbk);
@@ -263,14 +358,14 @@ module.exports = ({ask, lnd, logger}, cbk) => {
263
358
  'askForDescription',
264
359
  'askForExpiration',
265
360
  'askForNodeId',
266
- 'askForPrice',
267
361
  'askForSecret',
362
+ 'askForTokensPrice',
268
363
  ({
269
364
  askForDescription,
270
365
  askForExpiration,
271
366
  askForNodeId,
272
- askForPrice,
273
367
  askForSecret,
368
+ askForTokensPrice,
274
369
  },
275
370
  cbk) =>
276
371
  {
@@ -279,13 +374,13 @@ module.exports = ({ask, lnd, logger}, cbk) => {
279
374
  return cbk();
280
375
  }
281
376
 
282
- return finalizeTradeSecret({
377
+ return finalizeTrade({
283
378
  lnd,
284
379
  description: askForDescription.description,
285
380
  expires_at: futureDate(daysAsMs(askForExpiration.days)),
286
381
  secret: askForSecret.secret,
287
382
  to: askForNodeId.id,
288
- tokens: asNumber(askForPrice.tokens),
383
+ tokens: asNumber(askForTokensPrice.tokens),
289
384
  },
290
385
  cbk);
291
386
  }],