paid-services 3.1.2 → 3.5.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 (83) hide show
  1. package/.prettierignore +2 -0
  2. package/CHANGELOG.md +18 -0
  3. package/capacity/accept_capacity_change.js +284 -0
  4. package/capacity/ask_for_change_details.js +538 -0
  5. package/capacity/ask_for_decrease.js +185 -0
  6. package/capacity/assemble_replacement_tx.js +171 -0
  7. package/capacity/capacity_change_requests.js +85 -0
  8. package/capacity/change_channel_capacity.js +189 -0
  9. package/capacity/encode_change_request.js +62 -0
  10. package/capacity/encode_sign_capacity_response.js +32 -0
  11. package/capacity/fee_for_replacement.js +108 -0
  12. package/capacity/finalize_capacity_replacement.js +67 -0
  13. package/capacity/get_capacity_change_requests.js +99 -0
  14. package/capacity/get_capacity_replacement.js +372 -0
  15. package/capacity/get_replacement_signature.js +232 -0
  16. package/capacity/index.js +4 -0
  17. package/capacity/initiate_capacity_change.js +507 -0
  18. package/capacity/interim_replacement_psbt.js +57 -0
  19. package/capacity/is_open_witness_script.js +40 -0
  20. package/capacity/parse_accept_request.js +58 -0
  21. package/capacity/parse_accept_response.js +52 -0
  22. package/capacity/parse_capacity_change_request.js +108 -0
  23. package/capacity/parse_sign_capacity_request.js +59 -0
  24. package/capacity/propose_capacity_change.js +364 -0
  25. package/capacity/sign_capacity_replacement.js +119 -0
  26. package/capacity/witness_script_from_close_txs.js +50 -0
  27. package/index.js +6 -0
  28. package/p2p/encode_peer_request.js +59 -0
  29. package/p2p/encode_peer_response.js +44 -0
  30. package/p2p/encode_response_code.js +49 -0
  31. package/p2p/index.js +4 -0
  32. package/p2p/make_peer_request.js +151 -0
  33. package/p2p/parse_request_message.js +103 -0
  34. package/p2p/parse_response_code.js +60 -0
  35. package/p2p/return_failure_response.js +43 -0
  36. package/p2p/return_success_response.js +47 -0
  37. package/p2p/service_peer_requests.js +108 -0
  38. package/package.json +8 -4
  39. package/service_types.json +16 -0
  40. package/test/capacity/test_assemble_replacement_tx.js +46 -0
  41. package/test/capacity/test_capacity_change_requests.js +55 -0
  42. package/test/capacity/test_encode_change_request.js +54 -0
  43. package/test/capacity/test_encode_sign_capacity_response.js +47 -0
  44. package/test/capacity/test_fee_for_replacement.js +40 -0
  45. package/test/capacity/test_finalize_capacity_replacement.js +45 -0
  46. package/test/capacity/test_interim_replacement_psbt.js +44 -0
  47. package/test/capacity/test_is_open_witness_script.js +40 -0
  48. package/test/capacity/test_parse_accept_request.js +42 -0
  49. package/test/capacity/test_parse_capacity_change_request.js +52 -0
  50. package/test/capacity/test_parse_sign_capacity_request.js +49 -0
  51. package/test/capacity/test_witness_script_from_close_txs.js +53 -0
  52. package/test/integration/test_accept_capacity_change.js +189 -0
  53. package/test/integration/test_change_channel_capacity.js +203 -0
  54. package/test/integration/test_decrease_channel_capacity.js +216 -0
  55. package/test/integration/test_increase_channel_capacity.js +201 -0
  56. package/test/integration/test_service_peer_requests.js +59 -0
  57. package/test/integration/test_sign_capacity_replacement.js +142 -0
  58. package/test/p2p/test_encode_peer_request.js +53 -0
  59. package/test/p2p/test_encode_peer_response.js +38 -0
  60. package/test/p2p/test_encode_response_code.js +48 -0
  61. package/test/trades/test_decode_basic_trade.js +40 -0
  62. package/test/trades/test_decode_open_trade.js +50 -0
  63. package/test/trades/test_encode_open_trade.js +35 -0
  64. package/test/trades/test_encode_trade.js +37 -0
  65. package/trades/accept_trade.js +52 -0
  66. package/trades/create_trade.js +124 -44
  67. package/trades/decode_basic_trade.js +45 -0
  68. package/trades/decode_open_trade.js +69 -0
  69. package/trades/decode_trade.js +48 -66
  70. package/trades/decode_trade_secret.js +89 -0
  71. package/trades/encode_open_trade.js +89 -0
  72. package/trades/encode_trade.js +48 -33
  73. package/trades/encode_trade_secret.js +50 -0
  74. package/trades/finalize_trade_secret.js +116 -0
  75. package/trades/find_trade.js +314 -0
  76. package/trades/manage_trade.js +46 -35
  77. package/trades/network_from_network_record.js +8 -2
  78. package/trades/network_record_from_network.js +36 -0
  79. package/trades/network_record_from_request.js +6 -0
  80. package/trades/node_as_record.js +98 -0
  81. package/trades/record_as_node.js +113 -0
  82. package/trades/request_trade_by_id.js +89 -0
  83. package/trades/service_trade_requests.js +184 -0
@@ -0,0 +1,232 @@
1
+ const asyncAuto = require('async/auto');
2
+ const asyncRetry = require('async/retry');
3
+ const {closeChannel} = require('ln-service');
4
+ const {decodeChanId} = require('bolt07');
5
+ const {getChainTransactions} = require('ln-service');
6
+ const {getPendingChannels} = require('ln-service');
7
+ const {returnResult} = require('asyncjs-util');
8
+ const {Transaction} = require('bitcoinjs-lib');
9
+
10
+ const signCapacityReplacement = require('./sign_capacity_replacement');
11
+ const witnessScriptFromCloseTxs = require('./witness_script_from_close_txs');
12
+
13
+ const blocksBuffer = 1e3;
14
+ const {fromHex} = Transaction;
15
+ const interval = 200;
16
+ const notFoundIndex = -1;
17
+ const times = 72000;
18
+ const txIdAsHash = id => Buffer.from(id, 'hex').reverse();
19
+
20
+ /** Close channel and then sign the unsigned replacement transaction
21
+
22
+ {
23
+ channel: <Replace Channel Standard Format Id String>
24
+ id: <Channel Funding Transaction Id Hex String>
25
+ lnd: <Authenticated LND API Object>
26
+ output: <Original Funding Output Script Hex String>
27
+ unsigned: <Unsigned Replacement Transaction Hex String>
28
+ vout: <Channel Funding Output Index Number>
29
+ }
30
+
31
+ @returns via cbk or Promise
32
+ {
33
+ signature: <Funding Spend Signature Hex String>
34
+ transaction_id: <Replacement Transaction Id Hex String>
35
+ transaction_vout: <Replacement Transaction Output Index Number>
36
+ }
37
+ */
38
+ module.exports = ({channel, id, lnd, output, unsigned, vout}, cbk) => {
39
+ return new Promise((resolve, reject) => {
40
+ return asyncAuto({
41
+ // Check arguments
42
+ validate: cbk => {
43
+ if (!channel) {
44
+ return cbk([400, 'ExpectedChannelIdToSignReplacementTransaction']);
45
+ }
46
+
47
+ if (!id) {
48
+ return cbk([400, 'ExpectedFundingTxIdToSignReplacementTransaction']);
49
+ }
50
+
51
+ if (!lnd) {
52
+ return cbk([400, 'ExpectedLndToSignReplacementTransaction']);
53
+ }
54
+
55
+ if (!output) {
56
+ return cbk([400, 'ExpectedOutputScriptToGetReplacementSignature']);
57
+ }
58
+
59
+ if (!unsigned) {
60
+ return cbk([400, 'ExpectedUnsignedTxToGetReplacementSignature']);
61
+ }
62
+
63
+ if (vout === undefined) {
64
+ return cbk([400, 'ExpectedFundingOutputIndexToGetReplacementSig']);
65
+ }
66
+
67
+ return cbk();
68
+ },
69
+
70
+ // Find input index that is respending the original funding outpoint
71
+ vin: ['validate', ({}, cbk) => {
72
+ const inputIndex = fromHex(unsigned).ins.findIndex(input => {
73
+ return input.index === vout && input.hash.equals(txIdAsHash(id));
74
+ });
75
+
76
+ if (inputIndex === notFoundIndex) {
77
+ return cbk([503, 'ExpectedReplacementTransactionSpendingFunding']);
78
+ }
79
+
80
+ return cbk(null, inputIndex);
81
+ }],
82
+
83
+ // Force close the channel to allow for looking up the public key
84
+ closeChannel: ['vin', ({}, cbk) => {
85
+ return closeChannel({
86
+ lnd,
87
+ is_force_close: true,
88
+ transaction_id: id,
89
+ transaction_vout: vout,
90
+ },
91
+ cbk);
92
+ }],
93
+
94
+ // Get the pending close channels to see the final channel balance
95
+ getPending: ['closeChannel', ({}, cbk) => {
96
+ return getPendingChannels({lnd}, cbk);
97
+ }],
98
+
99
+ // Get the post close channel transactions to find the open/close txs
100
+ getTx: ['closeChannel', ({}, cbk) => {
101
+ const after = decodeChanId({channel}).block_height - blocksBuffer;
102
+
103
+ return getChainTransactions({after, lnd}, cbk);
104
+ }],
105
+
106
+ // Find the funding witness script in the close transaction
107
+ script: ['closeChannel', 'getTx', ({closeChannel, getTx}, cbk) => {
108
+ try {
109
+ const {script} = witnessScriptFromCloseTxs({
110
+ closing_tx_id: closeChannel.transaction_id,
111
+ transactions: getTx.transactions,
112
+ transaction_id: id,
113
+ transaction_vout: vout,
114
+ });
115
+
116
+ return cbk(null, script);
117
+ } catch (err) {
118
+ return cbk([503, err.message]);
119
+ }
120
+ }],
121
+
122
+ // Find the pending channel close that was just force closed
123
+ pending: [
124
+ 'closeChannel',
125
+ 'getPending',
126
+ ({closeChannel, getPending}, cbk) =>
127
+ {
128
+ // The pending close tx has the closing transaction id
129
+ const pending = getPending.pending_channels.find(chan => {
130
+ return chan.transaction_id === id && chan.transaction_vout === vout;
131
+ });
132
+
133
+ if (!pending) {
134
+ return cbk([503, 'ExpectedPendingChannelToGetReplacementSignature']);
135
+ }
136
+
137
+ // There should be no pending payments on the channel
138
+ if (!!pending.pending_payments && !!pending.pending_payments.length) {
139
+ return cbk([503, 'ExpectedNoActiveHtlcsOnCapacityChangeChannel']);
140
+ }
141
+
142
+ // Return the local balance expected to be returned in replacement
143
+ return cbk(null, {
144
+ capacity: pending.capacity,
145
+ local_balance: pending.local_balance,
146
+ partner_public_key: pending.partner_public_key,
147
+ });
148
+ }],
149
+
150
+ // Given the unsigned transaction, look for the matching open proposal
151
+ waitForProposal: ['pending', ({pending}, cbk) => {
152
+ const id = fromHex(unsigned).getId();
153
+
154
+ return asyncRetry({interval, times}, cbk => {
155
+ return getPendingChannels({lnd}, (err, res) => {
156
+ if (!!err) {
157
+ return cbk(err);
158
+ }
159
+
160
+ // Find an incoming channel that indicates it's safe to sign reopen
161
+ const incomingChannel = res.pending_channels.find(channel => {
162
+ // This will be an opening channel
163
+ if (!channel.is_opening) {
164
+ return false;
165
+ }
166
+
167
+ // The new channel must be from the same peer
168
+ if (channel.partner_public_key !== pending.partner_public_key) {
169
+ return false;
170
+ }
171
+
172
+ // The new channel must be spending the old transaction
173
+ if (channel.transaction_id !== id) {
174
+ return false;
175
+ }
176
+
177
+ // The new channel must have at least the balance of the old one
178
+ if (channel.local_balance < pending.local_balance) {
179
+ return false;
180
+ }
181
+
182
+ return true;
183
+ });
184
+
185
+ if (!incomingChannel) {
186
+ return cbk([503, 'FailedToFindPendingReplacementChannel']);
187
+ }
188
+
189
+ return cbk(null, {
190
+ transaction_id: incomingChannel.transaction_id,
191
+ transaction_vout: incomingChannel.transaction_vout,
192
+ });
193
+ });
194
+ },
195
+ cbk);
196
+ }],
197
+
198
+ // Sign the channel funding to prepare to authorize the new channel
199
+ signFunding: [
200
+ 'pending',
201
+ 'script',
202
+ 'vin',
203
+ 'waitForProposal',
204
+ ({pending, script, vin, waitForProposal}, cbk) =>
205
+ {
206
+ return signCapacityReplacement({
207
+ lnd,
208
+ output,
209
+ script,
210
+ vin,
211
+ capacity: pending.capacity,
212
+ transaction: unsigned,
213
+ },
214
+ cbk);
215
+ }],
216
+
217
+ // Final signature
218
+ signature: [
219
+ 'signFunding',
220
+ 'waitForProposal',
221
+ ({signFunding, waitForProposal}, cbk) =>
222
+ {
223
+ return cbk(null, {
224
+ signature: signFunding.signature,
225
+ transaction_id: waitForProposal.transaction_id,
226
+ transaction_vout: waitForProposal.transaction_vout,
227
+ });
228
+ }],
229
+ },
230
+ returnResult({reject, resolve, of: 'signature'}, cbk));
231
+ });
232
+ };
@@ -0,0 +1,4 @@
1
+ const changeChannelCapacity = require('./change_channel_capacity');
2
+ const getCapacityChangeRequests = require('./get_capacity_change_requests');
3
+
4
+ module.exports = {changeChannelCapacity, getCapacityChangeRequests};