ln-service 53.1.1 → 53.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 +16 -0
- package/README.md +93 -44
- package/index.js +2 -0
- package/package.json +10 -9
- package/test/integration/test_delete_pending_channel.js +144 -0
- package/test/integration/test_get_invoices.js +13 -1
- package/test/integration/test_get_pending_coop.js +1 -0
- package/test/integration/test_get_pending_force.js +3 -0
- package/test/integration/test_open_channels.js +34 -14
- package/test/integration/test_propose_channel.js +1 -0
- package/test/integration/test_subscribe_to_open_requests.js +10 -8
- package/test/integration/test_subscribe_to_peers.js +9 -2
- package/test/macros/btcsuite_type_daemon.js +11 -4
- package/test/macros/chain_send_transaction.js +9 -4
- package/test/macros/change_password.js +7 -4
- package/test/macros/create_cluster.js +8 -0
- package/test/macros/generate_blocks.js +6 -4
- package/test/macros/spawn_lnd.js +7 -4
- package/test/routerrpc-integration/test_multipath_payment.js +1 -1
- package/test/walletrpc-integration/test_broadcast_chain_transaction.js +2 -0
- package/test/walletrpc-integration/test_request_chain_fee_increase.js +2 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# Versions
|
|
2
2
|
|
|
3
|
+
## 53.4.0
|
|
4
|
+
|
|
5
|
+
- `deletePendingChannel`: Add method to remove a stuck pending channel open
|
|
6
|
+
|
|
7
|
+
## 53.3.0
|
|
8
|
+
|
|
9
|
+
- `getInvoices`: Add `is_unconfirmed` to filter out canceled/settled invoices
|
|
10
|
+
|
|
11
|
+
## 53.2.0
|
|
12
|
+
|
|
13
|
+
- `getPendingChannels`: Add support for channel `capacity`
|
|
14
|
+
|
|
15
|
+
## 53.1.2
|
|
16
|
+
|
|
17
|
+
- `openChannels`: Fix `cooperative_close_address` not being set on channels
|
|
18
|
+
|
|
3
19
|
## 53.1.0
|
|
4
20
|
|
|
5
21
|
- Add support for LND 0.14.1
|
package/README.md
CHANGED
|
@@ -74,8 +74,8 @@ the LND directory. (~/.lnd or ~/Library/Application Support/Lnd)
|
|
|
74
74
|
|
|
75
75
|
Be careful to avoid copying any newline characters in creds. To exclude them:
|
|
76
76
|
|
|
77
|
-
base64 ~/.lnd/tls.cert
|
|
78
|
-
base64 ~/.lnd/data/chain/bitcoin/mainnet/admin.macaroon
|
|
77
|
+
base64 -w0 ~/.lnd/tls.cert
|
|
78
|
+
base64 -w0 ~/.lnd/data/chain/bitcoin/mainnet/admin.macaroon
|
|
79
79
|
|
|
80
80
|
You can then use these to interact with your LND node directly:
|
|
81
81
|
|
|
@@ -102,7 +102,7 @@ for `unlocker` methods.
|
|
|
102
102
|
|
|
103
103
|
## All Methods
|
|
104
104
|
|
|
105
|
-
- [addPeer](#
|
|
105
|
+
- [addPeer](#addpeer) - Connect to a peer
|
|
106
106
|
- [authenticatedLndGrpc](#authenticatedlndgrpc) - LND API Object
|
|
107
107
|
- [broadcastChainTransaction](#broadcastchaintransaction) - Push a chain tx
|
|
108
108
|
- [cancelHodlInvoice](#cancelhodlinvoice) - Cancel a held or any open invoice
|
|
@@ -118,17 +118,22 @@ for `unlocker` methods.
|
|
|
118
118
|
- [createUnsignedRequest](#createunsignedrequest) - create an unsigned invoice
|
|
119
119
|
- [createWallet](#createwallet) - Make a new wallet
|
|
120
120
|
- [decodePaymentRequest](#decodepaymentrequest) - Decode a Lightning invoice
|
|
121
|
-
- [deleteFailedPayAttempts](#deletefailedpayattempts) - Remove records of
|
|
122
|
-
|
|
121
|
+
- [deleteFailedPayAttempts](#deletefailedpayattempts) - Remove records of
|
|
122
|
+
failed pay attempts
|
|
123
|
+
- [deleteFailedPayments](#deletefailedpayments) - Remove records of payments
|
|
124
|
+
that failed
|
|
123
125
|
- [deleteForwardingReputations](#deleteforwardingreputations) - Wipe node reps
|
|
124
126
|
- [deletePayment](#deletepayment) - Delete the record of a single past payment
|
|
125
127
|
- [deletePayments](#deletepayments) - Delete entire history of past payments
|
|
128
|
+
- [deletePendingChannel](#deletependingchannel) - Delete a pending channel that
|
|
129
|
+
will never confirm due to a conflicting confirmed transaction
|
|
126
130
|
- [diffieHellmanComputeSecret](#diffiehellmancomputesecret) - Get DH shared key
|
|
127
131
|
- [disableChannel](#disablechannel) - Disable a channel for outgoing payments
|
|
128
132
|
- [disconnectWatchtower](#disconnectwatchtower) - Disconnect a watchtower
|
|
129
133
|
- [enableChannel](#enablechannel) - Enable a channel for outgoing payments
|
|
130
134
|
- [fundPendingChannels](#fundpendingchannels) - Fund pending open channels
|
|
131
|
-
- [fundPsbt](#fundpsbt) - Create an unsigned PSBT with funding inputs and
|
|
135
|
+
- [fundPsbt](#fundpsbt) - Create an unsigned PSBT with funding inputs and
|
|
136
|
+
spending outputs
|
|
132
137
|
- [getAccessIds](#getaccessids) - Get granted macaroon root access ids
|
|
133
138
|
- [getAutopilot](#getautopilot) - Get autopilot status or node scores
|
|
134
139
|
- [getBackup](#getbackup) - Get a backup of a channel
|
|
@@ -157,48 +162,53 @@ for `unlocker` methods.
|
|
|
157
162
|
- [getNetworkGraph](#getnetworkgraph) - Get the channels and nodes of the graph
|
|
158
163
|
- [getNetworkInfo](#getnetworkinfo) - Get high-level graph info
|
|
159
164
|
- [getNode](#getnode) - Get graph info about a single node and its channels
|
|
160
|
-
- [getPathfindingSettings](#getpathfindingsettings) - Get pathfinding system
|
|
165
|
+
- [getPathfindingSettings](#getpathfindingsettings) - Get pathfinding system
|
|
166
|
+
settings
|
|
161
167
|
- [getPayment](#getpayment) - Get a past payment
|
|
162
168
|
- [getPayments](#getpayments) - Get all past payments
|
|
163
169
|
- [getPeers](#getpeers) - Get all connected peers
|
|
164
170
|
- [getPendingChainBalance](#getpendingchainbalance) - Get pending chain balance
|
|
165
171
|
- [getPendingChannels](#getpendingchannels) - Get channels in pending states
|
|
166
172
|
- [getPublicKey](#getpublickey) - Get a public key out of the seed
|
|
167
|
-
- [getRouteConfidence](#
|
|
168
|
-
- [getRouteThroughHops](#
|
|
169
|
-
- [getRouteToDestination](#
|
|
170
|
-
- [getSweepTransactions](#
|
|
171
|
-
|
|
172
|
-
- [
|
|
173
|
-
- [
|
|
173
|
+
- [getRouteConfidence](#getrouteconfidence) - Get confidence in a route
|
|
174
|
+
- [getRouteThroughHops](#getroutethroughhops) - Get a route through nodes
|
|
175
|
+
- [getRouteToDestination](#getroutetodestination) - Get a route to a destination
|
|
176
|
+
- [getSweepTransactions](#getsweeptransactions) - Get transactions sweeping to
|
|
177
|
+
self
|
|
178
|
+
- [getTowerServerInfo](#gettowerserverinfo) - Get information about tower server
|
|
179
|
+
- [getUtxos](#getutxos) - Get on-chain unspent outputs
|
|
180
|
+
- [getWalletInfo](#getwalletinfo) - Get general wallet info
|
|
174
181
|
- [getWalletStatus](#getwalletstatus) - Get the status of the wallet
|
|
175
|
-
- [getWalletVersion](#
|
|
176
|
-
- [grantAccess](#
|
|
177
|
-
- [grpcProxyServer](#
|
|
178
|
-
- [isDestinationPayable](#
|
|
179
|
-
- [lockUtxo](#
|
|
180
|
-
- [openChannel](#
|
|
181
|
-
- [openChannels](#
|
|
182
|
-
- [parsePaymentRequest](#
|
|
182
|
+
- [getWalletVersion](#getwalletversion) - Get the build and version of the LND
|
|
183
|
+
- [grantAccess](#grantaccess) - Grant an access credential macaroon
|
|
184
|
+
- [grpcProxyServer](#grpcproxyserver) - REST proxy server for calling to gRPC
|
|
185
|
+
- [isDestinationPayable](#isdestinationpayable) - Check can pay to destination
|
|
186
|
+
- [lockUtxo](#lockutxo) - Lock a UTXO temporarily to prevent it being used
|
|
187
|
+
- [openChannel](#openchannel) - Open a new channel
|
|
188
|
+
- [openChannels](#openchannels) - Open channels with external funding
|
|
189
|
+
- [parsePaymentRequest](#parsepaymentrequest) - Parse a BOLT11 Payment Request
|
|
183
190
|
- [pay](#pay) - Send a payment
|
|
184
|
-
- [payViaPaymentDetails](#
|
|
185
|
-
- [payViaPaymentRequest](#
|
|
186
|
-
- [payViaRoutes](#
|
|
187
|
-
- [prepareForChannelProposal](#
|
|
191
|
+
- [payViaPaymentDetails](#payviapaymentdetails) - Pay using decomposed details
|
|
192
|
+
- [payViaPaymentRequest](#payviapaymentrequest) - Pay using a payment request
|
|
193
|
+
- [payViaRoutes](#payviaroutes) - Make a payment over specified routes
|
|
194
|
+
- [prepareForChannelProposal](#prepareforchannelproposal) - setup for a channel
|
|
195
|
+
proposal
|
|
188
196
|
- [probe](#probe) - Find a payable route by attempting a fake payment
|
|
189
|
-
- [probeForRoute](#
|
|
197
|
+
- [probeForRoute](#probeforroute) - Actively probe to find a payable route
|
|
190
198
|
- [proposeChannel](#proposechannel) - Offer a channel proposal to a peer
|
|
191
|
-
- [recoverFundsFromChannel](#
|
|
192
|
-
- [recoverFundsFromChannels](#
|
|
193
|
-
- [removePeer](#
|
|
194
|
-
- [requestChainFeeIncrease](#requestchainfeeincrease) - Request a CPFP spend on
|
|
199
|
+
- [recoverFundsFromChannel](#recoverfundsfromchannel) - Restore a channel
|
|
200
|
+
- [recoverFundsFromChannels](#recoverfundsfromchannels) - Restore all channels
|
|
201
|
+
- [removePeer](#removepeer) - Disconnect from a connected peer
|
|
202
|
+
- [requestChainFeeIncrease](#requestchainfeeincrease) - Request a CPFP spend on
|
|
203
|
+
a UTXO
|
|
195
204
|
- [restrictMacaroon](#restrictmacaroon) - Add limitations to a macaroon
|
|
196
205
|
- [revokeAccess](#revokeaccess) - Revoke all access macaroons given to an id
|
|
197
206
|
- [routeFromChannels](#routefromchannels) - Convert channel series to a route
|
|
198
207
|
- [sendMessageToPeer](#sendmessagetopeer) - Send a custom message to a peer
|
|
199
208
|
- [sendToChainAddress](#sendtochainaddress) - Send on-chain to an address
|
|
200
209
|
- [sendToChainAddresses](#sendtochainaddresses) - Send on-chain to addresses
|
|
201
|
-
- [sendToChainOutputScripts](#sendtochainoutputscripts) - Send to on-chain
|
|
210
|
+
- [sendToChainOutputScripts](#sendtochainoutputscripts) - Send to on-chain
|
|
211
|
+
script outputs
|
|
202
212
|
- [setAutopilot](#setautopilot) - Turn autopilot on and set autopilot scores
|
|
203
213
|
- [settleHodlInvoice](#settlehodlinvoice) - Accept a HODL HTLC invoice
|
|
204
214
|
- [signBytes](#signbytes) - Sign over arbitrary bytes with node keys
|
|
@@ -211,18 +221,21 @@ for `unlocker` methods.
|
|
|
211
221
|
- [subscribeToChainAddress](#subscribetochainaddress) - Subscribe to receives
|
|
212
222
|
- [subscribeToChainSpend](#subscribetochainspend) - Subscribe to chain spends
|
|
213
223
|
- [subscribeToChannels](#subscribetochannels) - Subscribe to channel statuses
|
|
214
|
-
- [subscribeToForwardRequests](#subscribetoforwardrequests) - Interactively
|
|
224
|
+
- [subscribeToForwardRequests](#subscribetoforwardrequests) - Interactively
|
|
225
|
+
route
|
|
215
226
|
- [subscribeToForwards](#subscribetoforwards) - Subscribe to HTLC events
|
|
216
227
|
- [subscribeToGraph](#subscribetograph) - Subscribe to network graph updates
|
|
217
228
|
- [subscribeToInvoice](#subscribetoinvoice) - Subscribe to invoice updates
|
|
218
229
|
- [subscribeToInvoices](#subscribetoinvoices) - Subscribe to all invoices
|
|
219
230
|
- [subscribeToOpenRequests](#subscribetoopenrequests) - Approve open requests
|
|
220
231
|
- [subscribeToPastPayment](#subscribetopastpayment) - Subscribe to a payment
|
|
221
|
-
- [subscribeToPastPayments](#subscribetopastpayments) - Subscribe to all sent
|
|
232
|
+
- [subscribeToPastPayments](#subscribetopastpayments) - Subscribe to all sent
|
|
233
|
+
payments
|
|
222
234
|
- [subscribeToPayViaDetails](#subscribetopayviadetails) - Pay using details
|
|
223
235
|
- [subscribeToPayViaRequest](#subscribetopayviarequest) - Pay using a request
|
|
224
236
|
- [subscribeToPayViaRoutes](#subscribetopayviaroutes) - Pay using routes
|
|
225
|
-
- [subscribeToPeerMessages](#subscribetopeermessages) - Listen to incoming
|
|
237
|
+
- [subscribeToPeerMessages](#subscribetopeermessages) - Listen to incoming
|
|
238
|
+
custom messages
|
|
226
239
|
- [subscribeToPeers](#subscribetopeers) - Subscribe to peers connectivity
|
|
227
240
|
- [subscribeToProbe](#subscribetoprobe) - Subscribe to a probe for a route
|
|
228
241
|
- [subscribeToProbeForRoute](#subscribetoprobeforroute) - Probe for a route
|
|
@@ -230,11 +243,14 @@ for `unlocker` methods.
|
|
|
230
243
|
- [subscribeToTransactions](#subscribetotransactions) - Subscribe to chain tx
|
|
231
244
|
- [subscribeToWalletStatus](#subscribetowalletstatus) - Subscribe to node state
|
|
232
245
|
- [unauthenticatedLndGrpc](#unauthenticatedLndGrpc) - LND for locked lnd APIs
|
|
233
|
-
- [unlockUtxo](#
|
|
234
|
-
|
|
235
|
-
- [
|
|
246
|
+
- [unlockUtxo](#unlockutxo) - Release a locked UTXO so that it can be used
|
|
247
|
+
again
|
|
248
|
+
- [unlockWallet](#unlockwallet) - Unlock a locked lnd
|
|
249
|
+
- [updateChainTransaction](#updatechaintransaction) - Update a chain
|
|
250
|
+
transaction
|
|
236
251
|
- [updateConnectedWatchtower](#updateconnectedwatchtower) - Update watchtower
|
|
237
|
-
- [updatePathfindingSettings](#updatepathfindingsettings) - Update pathfinding
|
|
252
|
+
- [updatePathfindingSettings](#updatepathfindingsettings) - Update pathfinding
|
|
253
|
+
configuration
|
|
238
254
|
- [updateRoutingFees](#updateroutingfees) - Change routing fees
|
|
239
255
|
- [verifyAccess](#verifyaccess) - Verify a macaroon has access
|
|
240
256
|
- [verifyBackup](#verifybackup) - Verify a channel backup
|
|
@@ -256,6 +272,7 @@ for `unlocker` methods.
|
|
|
256
272
|
- run regtest integration tests
|
|
257
273
|
- [ln-pathfinding](https://npmjs.com/package/ln-accounting) - pathfinding
|
|
258
274
|
utilities
|
|
275
|
+
- [ln-sync](https://www.npmjs.com/package/ln-sync) - metadata helper methods
|
|
259
276
|
- [probing](https://npmjs.com/package/probing) - payment probing utilities
|
|
260
277
|
- [psbt](https://www.npmjs.com/package/psbt) - BIP 174 PSBT utilities
|
|
261
278
|
|
|
@@ -918,6 +935,36 @@ const {deletePayments} = require('ln-service');
|
|
|
918
935
|
await deletePayments({lnd});
|
|
919
936
|
```
|
|
920
937
|
|
|
938
|
+
### deletePendingChannel
|
|
939
|
+
|
|
940
|
+
Delete a pending channel
|
|
941
|
+
|
|
942
|
+
Pass the confirmed conflicting transaction that spends the same input to
|
|
943
|
+
make sure that no funds are being deleted.
|
|
944
|
+
|
|
945
|
+
This method is not supported on LND 0.13.3 and below
|
|
946
|
+
|
|
947
|
+
{
|
|
948
|
+
confirmed_transaction: <Hex Encoded Conflicting Transaction String>
|
|
949
|
+
lnd: <Authenticated LND API Object>
|
|
950
|
+
pending_transaction: <Hex Encoded Pending Transaction String>
|
|
951
|
+
pending_transaction_vout: <Pending Channel Output Index Number>
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
@returns via cbk or Promise
|
|
955
|
+
|
|
956
|
+
```node
|
|
957
|
+
const {deletePendingChannel} = require('ln-service');
|
|
958
|
+
|
|
959
|
+
// Delete a stuck pending channel
|
|
960
|
+
await deletePendingChannel({
|
|
961
|
+
lnd,
|
|
962
|
+
confirmed_transaction: confirmedTransactionHex,
|
|
963
|
+
pending_transaction: stuckPendingChannelOpenTxHex,
|
|
964
|
+
pending_transaction_vout: pendingChannelOutputIndexNumber,
|
|
965
|
+
});
|
|
966
|
+
```
|
|
967
|
+
|
|
921
968
|
### diffieHellmanComputeSecret
|
|
922
969
|
|
|
923
970
|
Derive a shared secret
|
|
@@ -1952,6 +1999,7 @@ Requires `invoices:read` permission
|
|
|
1952
1999
|
Invoice `payment` is not supported on LND 0.11.1 and below
|
|
1953
2000
|
|
|
1954
2001
|
{
|
|
2002
|
+
[is_unconfirmed]: <Omit Canceled and Settled Invoices Bool>
|
|
1955
2003
|
[limit]: <Page Result Limit Number>
|
|
1956
2004
|
lnd: <Authenticated LND API Object>
|
|
1957
2005
|
[token]: <Opaque Paging Token String>
|
|
@@ -2535,6 +2583,7 @@ Requires `offchain:read` permission
|
|
|
2535
2583
|
@returns via cbk or Promise
|
|
2536
2584
|
{
|
|
2537
2585
|
pending_channels: [{
|
|
2586
|
+
capacity: <Channel Capacity Tokens Number>
|
|
2538
2587
|
[close_transaction_id]: <Channel Closing Transaction Id String>
|
|
2539
2588
|
is_active: <Channel Is Active Bool>
|
|
2540
2589
|
is_closing: <Channel Is Closing Bool>
|
|
@@ -3205,11 +3254,11 @@ Requires `offchain:write`, `onchain:write`, `peers:write` permissions
|
|
|
3205
3254
|
[give_tokens]: <Tokens to Gift To Partner Number> // Defaults to zero
|
|
3206
3255
|
[is_private]: <Channel is Private Bool> // Defaults to false
|
|
3207
3256
|
lnd: <Authenticated LND API Object>
|
|
3208
|
-
local_tokens: <
|
|
3257
|
+
local_tokens: <Total Channel Capacity Tokens Number>
|
|
3209
3258
|
[min_confirmations]: <Spend UTXOs With Minimum Confirmations Number>
|
|
3210
3259
|
[min_htlc_mtokens]: <Minimum HTLC Millitokens String>
|
|
3211
|
-
partner_public_key: <Public Key Hex String>
|
|
3212
3260
|
[partner_csv_delay]: <Peer Output CSV Delay Number>
|
|
3261
|
+
partner_public_key: <Public Key Hex String>
|
|
3213
3262
|
[partner_socket]: <Peer Connection Host:Port String>
|
|
3214
3263
|
}
|
|
3215
3264
|
|
|
@@ -3250,11 +3299,11 @@ after the funding step.
|
|
|
3250
3299
|
[give_tokens]: <Tokens to Gift To Partner Number> // Defaults to zero
|
|
3251
3300
|
[is_private]: <Channel is Private Bool> // Defaults to false
|
|
3252
3301
|
[min_htlc_mtokens]: <Minimum HTLC Millitokens String>
|
|
3253
|
-
partner_public_key: <Public Key Hex String>
|
|
3254
3302
|
[partner_csv_delay]: <Peer Output CSV Delay Number>
|
|
3303
|
+
partner_public_key: <Public Key Hex String>
|
|
3255
3304
|
[partner_socket]: <Peer Connection Host:Port String>
|
|
3256
3305
|
}]
|
|
3257
|
-
is_avoiding_broadcast: <Avoid Broadcast of All Channels Bool>
|
|
3306
|
+
[is_avoiding_broadcast]: <Avoid Broadcast of All Channels Bool>
|
|
3258
3307
|
lnd: <Authenticated LND API Object>
|
|
3259
3308
|
}
|
|
3260
3309
|
|
|
@@ -6060,8 +6109,8 @@ This method is not supported in LND 0.13.4 and below
|
|
|
6060
6109
|
local_tokens: <Local Tokens Number>
|
|
6061
6110
|
[min_confirmations]: <Spend UTXOs With Minimum Confirmations Number>
|
|
6062
6111
|
[min_htlc_mtokens]: <Minimum HTLC Millitokens String>
|
|
6063
|
-
partner_public_key: <Public Key Hex String>
|
|
6064
6112
|
[partner_csv_delay]: <Peer Output CSV Delay Number>
|
|
6113
|
+
partner_public_key: <Public Key Hex String>
|
|
6065
6114
|
}
|
|
6066
6115
|
uri: <RPC URI String>
|
|
6067
6116
|
}
|
package/index.js
CHANGED
|
@@ -19,6 +19,7 @@ const {deleteFailedPayAttempts} = require('lightning');
|
|
|
19
19
|
const {deleteFailedPayments} = require('lightning');
|
|
20
20
|
const {deletePayment} = require('lightning');
|
|
21
21
|
const {deletePayments} = require('lightning');
|
|
22
|
+
const {deletePendingChannel} = require('lightning');
|
|
22
23
|
const {diffieHellmanComputeSecret} = require('lightning');
|
|
23
24
|
const {disableChannel} = require('lightning');
|
|
24
25
|
const {disconnectWatchtower} = require('lightning');
|
|
@@ -157,6 +158,7 @@ module.exports = {
|
|
|
157
158
|
deleteForwardingReputations,
|
|
158
159
|
deletePayment,
|
|
159
160
|
deletePayments,
|
|
161
|
+
deletePendingChannel,
|
|
160
162
|
diffieHellmanComputeSecret,
|
|
161
163
|
disableChannel,
|
|
162
164
|
disconnectWatchtower,
|
package/package.json
CHANGED
|
@@ -7,35 +7,36 @@
|
|
|
7
7
|
"url": "https://github.com/alexbosworth/ln-service/issues"
|
|
8
8
|
},
|
|
9
9
|
"dependencies": {
|
|
10
|
-
"bolt07": "1.
|
|
10
|
+
"bolt07": "1.8.0",
|
|
11
11
|
"cors": "2.8.5",
|
|
12
|
-
"express": "4.17.
|
|
12
|
+
"express": "4.17.2",
|
|
13
13
|
"invoices": "2.0.2",
|
|
14
|
-
"lightning": "5.1
|
|
14
|
+
"lightning": "5.3.1",
|
|
15
15
|
"macaroon": "3.0.4",
|
|
16
16
|
"morgan": "1.10.0",
|
|
17
|
-
"ws": "8.
|
|
17
|
+
"ws": "8.4.0"
|
|
18
18
|
},
|
|
19
19
|
"description": "Interaction helper for your Lightning Network daemon",
|
|
20
20
|
"devDependencies": {
|
|
21
21
|
"@alexbosworth/tap": "15.0.10",
|
|
22
22
|
"@alexbosworth/node-fetch": "2.6.2",
|
|
23
|
-
"async": "3.2.
|
|
23
|
+
"async": "3.2.3",
|
|
24
24
|
"asyncjs-util": "1.2.7",
|
|
25
25
|
"bip66": "1.1.5",
|
|
26
26
|
"bitcoinjs-lib": "6.0.1",
|
|
27
27
|
"bn.js": "5.2.0",
|
|
28
|
-
"ecpair": "
|
|
28
|
+
"ecpair": "2.0.1",
|
|
29
29
|
"ln-docker-daemons": "2.1.0",
|
|
30
30
|
"portfinder": "1.0.28",
|
|
31
31
|
"psbt": "1.1.10",
|
|
32
32
|
"rimraf": "3.0.2",
|
|
33
|
-
"secp256k1": "4.0.
|
|
33
|
+
"secp256k1": "4.0.3",
|
|
34
|
+
"tiny-secp256k1": "2.1.2",
|
|
34
35
|
"uuid": "8.3.2",
|
|
35
36
|
"varuint-bitcoin": "1.1.2"
|
|
36
37
|
},
|
|
37
38
|
"engines": {
|
|
38
|
-
"node": ">=12"
|
|
39
|
+
"node": ">=12.20"
|
|
39
40
|
},
|
|
40
41
|
"keywords": [
|
|
41
42
|
"bitcoin",
|
|
@@ -54,5 +55,5 @@
|
|
|
54
55
|
"scripts": {
|
|
55
56
|
"test": "echo $DOCKER_LND_VERSION && tap -j 2 --branches=1 --functions=1 --lines=1 --statements=1 -t 200 test/autopilotrpc-integration/*.js test/chainrpc-integration/*.js test/integration/*.js test/invoicesrpc-integration/*.js test/routerrpc-integration/*.js test/signerrpc-integration/*.js test/tower_clientrpc-integration/*.js test/tower_serverrpc-integration/*.js test/walletrpc-integration/*.js"
|
|
56
57
|
},
|
|
57
|
-
"version": "53.
|
|
58
|
+
"version": "53.4.0"
|
|
58
59
|
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
const {once} = require('events');
|
|
2
|
+
|
|
3
|
+
const asyncEach = require('async/each');
|
|
4
|
+
const asyncRetry = require('async/retry');
|
|
5
|
+
const {extractTransaction} = require('psbt');
|
|
6
|
+
const {spawnLightningCluster} = require('ln-docker-daemons');
|
|
7
|
+
const {test} = require('@alexbosworth/tap');
|
|
8
|
+
|
|
9
|
+
const {addPeer} = require('./../../');
|
|
10
|
+
const {broadcastChainTransaction} = require('./../../');
|
|
11
|
+
const {createCluster} = require('./../macros');
|
|
12
|
+
const {delay} = require('./../macros');
|
|
13
|
+
const {deletePendingChannel} = require('./../../');
|
|
14
|
+
const {fundPendingChannels} = require('./../../');
|
|
15
|
+
const {fundPsbt} = require('./../../');
|
|
16
|
+
const {getChainBalance} = require('./../../');
|
|
17
|
+
const {getChannels} = require('./../../');
|
|
18
|
+
const {getLockedUtxos} = require('./../../');
|
|
19
|
+
const {getPendingChannels} = require('./../../');
|
|
20
|
+
const {openChannels} = require('./../../');
|
|
21
|
+
const {signPsbt} = require('./../../');
|
|
22
|
+
const {unlockUtxo} = require('./../../');
|
|
23
|
+
|
|
24
|
+
const capacity = 1e6;
|
|
25
|
+
const count = 100;
|
|
26
|
+
const interval = 100;
|
|
27
|
+
const race = promises => Promise.race(promises);
|
|
28
|
+
const size = 3;
|
|
29
|
+
const timeout = 1000 * 5;
|
|
30
|
+
const times = 200;
|
|
31
|
+
|
|
32
|
+
// Forfeiting a pending channel should remove the pending channel
|
|
33
|
+
test(`Forfeit pending channel`, async ({end, equal}) => {
|
|
34
|
+
const {kill, nodes} = await spawnLightningCluster({size});
|
|
35
|
+
|
|
36
|
+
const [control, target, remote] = nodes;
|
|
37
|
+
|
|
38
|
+
const {generate, lnd} = control;
|
|
39
|
+
|
|
40
|
+
try {
|
|
41
|
+
await control.generate({count});
|
|
42
|
+
|
|
43
|
+
await asyncEach([target, remote], async node => {
|
|
44
|
+
return await addPeer({lnd, public_key: node.id, socket: node.socket});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const channels = [{capacity, partner_public_key: target.id}];
|
|
48
|
+
|
|
49
|
+
// Propose a channel to target
|
|
50
|
+
const proposeToTarget = await asyncRetry({interval, times}, async () => {
|
|
51
|
+
return await race([
|
|
52
|
+
delay(timeout),
|
|
53
|
+
openChannels({channels, lnd, is_avoiding_broadcast: true}),
|
|
54
|
+
]);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// Setup funding for the target
|
|
58
|
+
const fundTarget = await fundPsbt({lnd, outputs: proposeToTarget.pending});
|
|
59
|
+
|
|
60
|
+
// Sign the funding to the target
|
|
61
|
+
const signTarget = await signPsbt({lnd, psbt: fundTarget.psbt});
|
|
62
|
+
|
|
63
|
+
// Fund the target channel
|
|
64
|
+
await fundPendingChannels({
|
|
65
|
+
lnd,
|
|
66
|
+
channels: proposeToTarget.pending.map(n => n.id),
|
|
67
|
+
funding: signTarget.psbt,
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
await asyncEach((await getLockedUtxos({lnd})).utxos, async utxo => {
|
|
71
|
+
return await unlockUtxo({
|
|
72
|
+
lnd,
|
|
73
|
+
id: utxo.lock_id,
|
|
74
|
+
transaction_id: utxo.transaction_id,
|
|
75
|
+
transaction_vout: utxo.transaction_vout,
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// Propose a channel to remote
|
|
80
|
+
const proposeToRemote = await asyncRetry({interval, times}, async () => {
|
|
81
|
+
return await race([
|
|
82
|
+
delay(timeout),
|
|
83
|
+
openChannels({lnd,
|
|
84
|
+
channels: [{capacity, partner_public_key: remote.id}],
|
|
85
|
+
is_avoiding_broadcast: true,
|
|
86
|
+
}),
|
|
87
|
+
]);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// Setup funding for the remote, using the same inputs
|
|
91
|
+
const fundRemote = await fundPsbt({
|
|
92
|
+
lnd,
|
|
93
|
+
inputs: fundTarget.inputs,
|
|
94
|
+
outputs: proposeToRemote.pending
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
// Sign the funding to the target
|
|
98
|
+
const signRemote = await signPsbt({lnd, psbt: fundRemote.psbt});
|
|
99
|
+
|
|
100
|
+
// Fund the remote channel
|
|
101
|
+
await fundPendingChannels({
|
|
102
|
+
lnd,
|
|
103
|
+
channels: proposeToRemote.pending.map(n => n.id),
|
|
104
|
+
funding: signRemote.psbt,
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
const {transaction} = extractTransaction({psbt: signRemote.psbt});
|
|
108
|
+
|
|
109
|
+
await broadcastChainTransaction({lnd, transaction});
|
|
110
|
+
|
|
111
|
+
const channel = await asyncRetry({interval, times}, async () => {
|
|
112
|
+
const [channel] = (await getChannels({lnd})).channels;
|
|
113
|
+
|
|
114
|
+
if (!!channel) {
|
|
115
|
+
return channel;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
await generate({});
|
|
119
|
+
|
|
120
|
+
throw new Error('ExpectedNewChannelCreated');
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
const [pending] = (await getPendingChannels({lnd})).pending_channels;
|
|
124
|
+
|
|
125
|
+
const stuckTx = extractTransaction({psbt: signTarget.psbt});
|
|
126
|
+
|
|
127
|
+
await deletePendingChannel({
|
|
128
|
+
lnd,
|
|
129
|
+
confirmed_transaction: transaction,
|
|
130
|
+
pending_transaction: stuckTx.transaction,
|
|
131
|
+
pending_transaction_vout: pending.transaction_vout,
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
const [stillPending] = (await getPendingChannels({lnd})).pending_channels;
|
|
135
|
+
|
|
136
|
+
equal(stillPending, undefined, 'Conflicting pending channel deleted');
|
|
137
|
+
} catch (err) {
|
|
138
|
+
equal(err, null, 'No error is expected');
|
|
139
|
+
} finally {
|
|
140
|
+
await kill({});
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return end();
|
|
144
|
+
});
|
|
@@ -1,13 +1,15 @@
|
|
|
1
|
+
const asyncEach = require('async/each');
|
|
1
2
|
const {spawnLightningCluster} = require('ln-docker-daemons');
|
|
2
3
|
const {test} = require('@alexbosworth/tap');
|
|
3
4
|
|
|
5
|
+
const {cancelHodlInvoice} = require('./../../');
|
|
4
6
|
const {createInvoice} = require('./../../');
|
|
5
7
|
const {getInvoices} = require('./../../');
|
|
6
8
|
|
|
7
9
|
const limit = 1;
|
|
8
10
|
|
|
9
11
|
// createInvoice should result in a created invoice
|
|
10
|
-
test(`Create an invoice`, async ({end, equal}) => {
|
|
12
|
+
test(`Create an invoice`, async ({end, equal, strictSame}) => {
|
|
11
13
|
const {kill, nodes} = await spawnLightningCluster({});
|
|
12
14
|
|
|
13
15
|
try {
|
|
@@ -48,6 +50,16 @@ test(`Create an invoice`, async ({end, equal}) => {
|
|
|
48
50
|
equal(invoice.secret, expected.secret, 'Payment secret');
|
|
49
51
|
equal(invoice.tokens, expected.tokens, 'Tokens');
|
|
50
52
|
});
|
|
53
|
+
|
|
54
|
+
const reversed = invoices.slice().reverse();
|
|
55
|
+
|
|
56
|
+
await asyncEach(reversed.filter((n, i) => !!i), async (invoice) => {
|
|
57
|
+
return await cancelHodlInvoice({lnd, id: invoice.id});
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
const unconfirmed = await getInvoices({limit, lnd, is_unconfirmed: true});
|
|
61
|
+
|
|
62
|
+
strictSame(unconfirmed, thirdPage, 'Pending invoices are ignored');
|
|
51
63
|
} catch (err) {
|
|
52
64
|
equal(err, null, 'No error is expected');
|
|
53
65
|
}
|
|
@@ -51,6 +51,7 @@ test(`Get pending channels`, async ({end, equal}) => {
|
|
|
51
51
|
equal(channel.pending_balance, 980950, 'Waiting on balance');
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
equal(channel.capacity, 1000000, 'Got channel capacity');
|
|
54
55
|
equal(channel.close_transaction_id, undefined, 'No close tx id');
|
|
55
56
|
equal(channel.is_active, false, 'Ended');
|
|
56
57
|
equal(channel.is_closing, true, 'Closing');
|
|
@@ -68,6 +68,7 @@ test(`Get pending channels`, async ({end, equal}) => {
|
|
|
68
68
|
equal(pendingOpen.transaction_weight, 724, 'Channel tx weight');
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
+
equal(pendingOpen.capacity, 1000000, 'Got channel opening capacity');
|
|
71
72
|
equal(pendingOpen.close_transaction_id, undefined, 'Not closing');
|
|
72
73
|
equal(pendingOpen.is_active, false, 'Not active yet');
|
|
73
74
|
equal(pendingOpen.is_closing, false, 'Not closing yet');
|
|
@@ -111,6 +112,7 @@ test(`Get pending channels`, async ({end, equal}) => {
|
|
|
111
112
|
equal(waitClose.pending_balance, 980950, 'Waiting on balance');
|
|
112
113
|
}
|
|
113
114
|
|
|
115
|
+
equal(waitClose.capacity, 1000000, 'Got channel closing capacity');
|
|
114
116
|
equal(waitClose.close_transaction_id, undefined, 'Waiting for close tx');
|
|
115
117
|
equal(waitClose.is_active, false, 'Not active yet');
|
|
116
118
|
equal(waitClose.is_closing, true, 'Channel is closing');
|
|
@@ -166,6 +168,7 @@ test(`Get pending channels`, async ({end, equal}) => {
|
|
|
166
168
|
equal(forceClose.pending_balance, 980950, 'Waiting on balance');
|
|
167
169
|
}
|
|
168
170
|
|
|
171
|
+
equal(forceClose.capacity, 1000000, 'Got channel close capacity');
|
|
169
172
|
equal(forceClose.close_transaction_id, channelClose.transaction_id, 'Txid');
|
|
170
173
|
equal(forceClose.is_active, false, 'Not active anymore');
|
|
171
174
|
equal(forceClose.is_closing, true, 'Channel is force closing');
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const asyncMap = require('async/map');
|
|
1
2
|
const asyncRetry = require('async/retry');
|
|
2
3
|
const {extractTransaction} = require('psbt');
|
|
3
4
|
const {finalizePsbt} = require('psbt');
|
|
@@ -6,22 +7,25 @@ const {test} = require('@alexbosworth/tap');
|
|
|
6
7
|
const {transactionAsPsbt} = require('psbt');
|
|
7
8
|
|
|
8
9
|
const {addPeer} = require('./../../');
|
|
10
|
+
const {createChainAddress} = require('./../../');
|
|
9
11
|
const {delay} = require('./../macros');
|
|
10
12
|
const {fundPendingChannels} = require('./../../');
|
|
11
13
|
const {getChainBalance} = require('./../../');
|
|
12
14
|
const {getChainTransactions} = require('./../../');
|
|
13
15
|
const {getChannels} = require('./../../');
|
|
16
|
+
const {getHeight} = require('./../../');
|
|
14
17
|
const {getPeers} = require('./../../');
|
|
15
18
|
const {openChannels} = require('./../../');
|
|
16
19
|
const {sendToChainAddresses} = require('./../../');
|
|
17
20
|
|
|
18
21
|
const capacity = 1e6;
|
|
19
22
|
const count = 10;
|
|
20
|
-
const interval =
|
|
23
|
+
const interval = 10;
|
|
24
|
+
const maturity = 100;
|
|
21
25
|
const race = promises => Promise.race(promises);
|
|
22
26
|
const size = 3;
|
|
23
27
|
const timeout = 250 * 10;
|
|
24
|
-
const times =
|
|
28
|
+
const times = 2000;
|
|
25
29
|
|
|
26
30
|
// Opening channels should open up channels
|
|
27
31
|
test(`Open channels`, async ({end, equal}) => {
|
|
@@ -29,11 +33,19 @@ test(`Open channels`, async ({end, equal}) => {
|
|
|
29
33
|
|
|
30
34
|
const [{generate, lnd}, target, remote] = nodes;
|
|
31
35
|
|
|
32
|
-
await
|
|
33
|
-
|
|
34
|
-
|
|
36
|
+
await generate({count: maturity});
|
|
37
|
+
|
|
38
|
+
await asyncRetry({interval, times}, async () => {
|
|
39
|
+
const lnds = [lnd, target.lnd, remote.lnd];
|
|
40
|
+
|
|
41
|
+
const heights = await asyncMap(lnds, async lnd => {
|
|
42
|
+
return (await getHeight({lnd})).current_block_height;
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
const [controlHeight, targetHeight, remoteHeight] = heights;
|
|
35
46
|
|
|
36
|
-
|
|
47
|
+
if (controlHeight !== targetHeight || controlHeight !== remoteHeight) {
|
|
48
|
+
throw new Error('ExpectedSyncHeights');
|
|
37
49
|
}
|
|
38
50
|
});
|
|
39
51
|
|
|
@@ -42,11 +54,12 @@ test(`Open channels`, async ({end, equal}) => {
|
|
|
42
54
|
|
|
43
55
|
const spending = chainTx.map(({transaction}) => transaction);
|
|
44
56
|
|
|
45
|
-
await
|
|
57
|
+
const {address} = await createChainAddress({lnd});
|
|
46
58
|
|
|
47
|
-
const channels = [target, remote].map(
|
|
59
|
+
const channels = [target, remote].map(({id}) => ({
|
|
48
60
|
capacity,
|
|
49
|
-
|
|
61
|
+
cooperative_close_address: address,
|
|
62
|
+
partner_public_key: id,
|
|
50
63
|
}));
|
|
51
64
|
|
|
52
65
|
let pending;
|
|
@@ -54,6 +67,7 @@ test(`Open channels`, async ({end, equal}) => {
|
|
|
54
67
|
// Wait for peers to be connected
|
|
55
68
|
await asyncRetry({interval, times}, async () => {
|
|
56
69
|
await addPeer({lnd, public_key: remote.id, socket: remote.socket});
|
|
70
|
+
await addPeer({lnd, public_key: target.id, socket: target.socket});
|
|
57
71
|
|
|
58
72
|
if ((await getPeers({lnd})).peers.length !== channels.length) {
|
|
59
73
|
throw new Error('ExpectedConnectedPeersToOpenChannels');
|
|
@@ -67,13 +81,13 @@ test(`Open channels`, async ({end, equal}) => {
|
|
|
67
81
|
});
|
|
68
82
|
|
|
69
83
|
// Normally funding would involve an un-broadcast transaction
|
|
70
|
-
await sendToChainAddresses({lnd, send_to: pending});
|
|
84
|
+
const {id} = await sendToChainAddresses({lnd, send_to: pending});
|
|
71
85
|
|
|
72
|
-
await asyncRetry({interval, times}, async() => {
|
|
86
|
+
await asyncRetry({interval, times}, async () => {
|
|
73
87
|
const {transactions} = await getChainTransactions({lnd});
|
|
74
88
|
|
|
75
|
-
if (transactions.
|
|
76
|
-
throw new Error('
|
|
89
|
+
if (!transactions.find(n => n.id === id)) {
|
|
90
|
+
throw new Error('ExpectedChainTransaction');
|
|
77
91
|
}
|
|
78
92
|
|
|
79
93
|
return;
|
|
@@ -96,7 +110,7 @@ test(`Open channels`, async ({end, equal}) => {
|
|
|
96
110
|
});
|
|
97
111
|
|
|
98
112
|
await asyncRetry({interval, times}, async () => {
|
|
99
|
-
await generate({
|
|
113
|
+
await generate({});
|
|
100
114
|
|
|
101
115
|
const {channels} = await getChannels({lnd});
|
|
102
116
|
|
|
@@ -104,8 +118,14 @@ test(`Open channels`, async ({end, equal}) => {
|
|
|
104
118
|
throw new Error('ExpectedNewChannelsCreatedAndActive');
|
|
105
119
|
}
|
|
106
120
|
|
|
121
|
+
const [channel] = channels;
|
|
122
|
+
|
|
123
|
+
equal(channel.cooperative_close_address, address, 'Channel close addr');
|
|
124
|
+
|
|
107
125
|
return;
|
|
108
126
|
});
|
|
127
|
+
} catch (err) {
|
|
128
|
+
equal(err, null, 'No error is reported');
|
|
109
129
|
} finally {
|
|
110
130
|
return await kill({});
|
|
111
131
|
}
|
|
@@ -359,6 +359,7 @@ test(`Propose a channel with a coop delay`, async ({end, equal, ok}) => {
|
|
|
359
359
|
equal(incoming.transaction_weight, 724, 'Funding tx weight');
|
|
360
360
|
}
|
|
361
361
|
|
|
362
|
+
equal(incoming.capacity, 1000000, 'Incoming capacity is defined');
|
|
362
363
|
equal(incoming.close_transaction_id, undefined, 'Not a closing tx');
|
|
363
364
|
equal(incoming.is_active, false, 'Not active yet');
|
|
364
365
|
equal(incoming.is_closing, false, 'Channel is not closing');
|
|
@@ -105,14 +105,16 @@ test(`Subscribe to open requests`, async ({end, equal, fail, ok}) => {
|
|
|
105
105
|
});
|
|
106
106
|
|
|
107
107
|
try {
|
|
108
|
-
await
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
108
|
+
await asyncRetry({interval, times}, async () => {
|
|
109
|
+
return await openChannel({
|
|
110
|
+
lnd: target.lnd,
|
|
111
|
+
chain_fee_tokens_per_vbyte: defaultFee,
|
|
112
|
+
give_tokens: giftTokens,
|
|
113
|
+
is_private: true,
|
|
114
|
+
local_tokens: channelCapacityTokens,
|
|
115
|
+
partner_public_key: control.id,
|
|
116
|
+
socket: control.socket,
|
|
117
|
+
});
|
|
116
118
|
});
|
|
117
119
|
} catch (err) {
|
|
118
120
|
equal(err, null, 'Expected no error when a channel is accepted');
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const {once} = require('events');
|
|
2
2
|
|
|
3
|
+
const asyncRetry = require('async/retry');
|
|
3
4
|
const {spawnLightningCluster} = require('ln-docker-daemons');
|
|
4
5
|
const {test} = require('@alexbosworth/tap');
|
|
5
6
|
|
|
@@ -9,7 +10,9 @@ const {removePeer} = require('./../../');
|
|
|
9
10
|
const {subscribeToPeers} = require('./../../');
|
|
10
11
|
|
|
11
12
|
const all = promise => Promise.all(promise);
|
|
13
|
+
const interval = 10;
|
|
12
14
|
const size = 2;
|
|
15
|
+
const times = 1000;
|
|
13
16
|
|
|
14
17
|
// Subscribing to peer events should trigger reception of peer status changes
|
|
15
18
|
test(`Subscribe to peers`, async ({end, equal}) => {
|
|
@@ -21,7 +24,9 @@ test(`Subscribe to peers`, async ({end, equal}) => {
|
|
|
21
24
|
|
|
22
25
|
sub.on('error', () => {});
|
|
23
26
|
|
|
24
|
-
await
|
|
27
|
+
await asyncRetry({interval, times}, async () => {
|
|
28
|
+
await addPeer({lnd, public_key: target.id, socket: target.socket});
|
|
29
|
+
});
|
|
25
30
|
|
|
26
31
|
const disconnect = removePeer({lnd, public_key: target.id});
|
|
27
32
|
const receiveDisconnect = once(sub, 'disconnected');
|
|
@@ -32,7 +37,9 @@ test(`Subscribe to peers`, async ({end, equal}) => {
|
|
|
32
37
|
|
|
33
38
|
equal(disconnected.public_key, target.id, 'Got d/c event');
|
|
34
39
|
|
|
35
|
-
const connect =
|
|
40
|
+
const connect = asyncRetry({interval, times}, async () => {
|
|
41
|
+
return addPeer({lnd, public_key: target.id, socket: target.socket});
|
|
42
|
+
});
|
|
36
43
|
|
|
37
44
|
const receiveConnectMessage = once(sub, 'connected');
|
|
38
45
|
|
|
@@ -2,12 +2,11 @@ const {join} = require('path');
|
|
|
2
2
|
const {spawn} = require('child_process');
|
|
3
3
|
|
|
4
4
|
const asyncAuto = require('async/auto');
|
|
5
|
-
const {ECPair} = require('ecpair');
|
|
6
5
|
const openPortFinder = require('portfinder');
|
|
7
6
|
const {networks} = require('bitcoinjs-lib');
|
|
8
7
|
const {payments} = require('bitcoinjs-lib');
|
|
8
|
+
const tinysecp = require('tiny-secp256k1');
|
|
9
9
|
|
|
10
|
-
const {fromPublicKey} = ECPair;
|
|
11
10
|
const knownDaemons = ['btcd'];
|
|
12
11
|
const localhost = '127.0.0.1';
|
|
13
12
|
const notFoundIndex = -1;
|
|
@@ -37,6 +36,9 @@ const unableToStartServer = /Unable.to.start.server/;
|
|
|
37
36
|
*/
|
|
38
37
|
module.exports = (args, cbk) => {
|
|
39
38
|
return asyncAuto({
|
|
39
|
+
// Import ECPair library
|
|
40
|
+
ecp: async () => (await import('ecpair')).ECPairFactory(tinysecp),
|
|
41
|
+
|
|
40
42
|
// Check arguments
|
|
41
43
|
validate: cbk => {
|
|
42
44
|
if (knownDaemons.indexOf(args.daemon) === notFoundIndex) {
|
|
@@ -85,11 +87,16 @@ module.exports = (args, cbk) => {
|
|
|
85
87
|
}],
|
|
86
88
|
|
|
87
89
|
// Spin up the chain daemon
|
|
88
|
-
spawnDaemon: [
|
|
90
|
+
spawnDaemon: [
|
|
91
|
+
'ecp',
|
|
92
|
+
'listenPort',
|
|
93
|
+
'rpcPort',
|
|
94
|
+
({ecp, listenPort, rpcPort}, cbk) =>
|
|
95
|
+
{
|
|
89
96
|
const miningKey = Buffer.from(args.mining_public_key, 'hex');
|
|
90
97
|
const network = networks.testnet;
|
|
91
98
|
|
|
92
|
-
const pubkey = fromPublicKey(miningKey, network).publicKey;
|
|
99
|
+
const pubkey = ecp.fromPublicKey(miningKey, network).publicKey;
|
|
93
100
|
|
|
94
101
|
const daemon = spawn(args.daemon, [
|
|
95
102
|
'--datadir', args.dir,
|
|
@@ -2,13 +2,13 @@ const {encode} = require('varuint-bitcoin');
|
|
|
2
2
|
|
|
3
3
|
const {address} = require('bitcoinjs-lib');
|
|
4
4
|
const {crypto} = require('bitcoinjs-lib');
|
|
5
|
-
const {ECPair} = require('ecpair');
|
|
6
5
|
const {networks} = require('bitcoinjs-lib');
|
|
7
6
|
const {payments} = require('bitcoinjs-lib');
|
|
8
7
|
const {script} = require('bitcoinjs-lib');
|
|
9
|
-
const scriptBufAsScript = require('./script_buffers_as_script');
|
|
10
8
|
const {Transaction} = require('bitcoinjs-lib');
|
|
11
9
|
|
|
10
|
+
const scriptBufAsScript = require('./script_buffers_as_script');
|
|
11
|
+
|
|
12
12
|
const defaultNetwork = 'testnet';
|
|
13
13
|
const encodeSignature = script.signature.encode;
|
|
14
14
|
const hexBase = 16;
|
|
@@ -20,6 +20,7 @@ const {toOutputScript} = address;
|
|
|
20
20
|
|
|
21
21
|
{
|
|
22
22
|
destination: <Destination Address String>
|
|
23
|
+
ecp: <ECPair Object>
|
|
23
24
|
fee: <Fee Tokens To Remove From Spend Number>
|
|
24
25
|
private_key: <WIF Serialized Private Key String>
|
|
25
26
|
spend_transaction_id: <Transaction Id to Spend Hex String>
|
|
@@ -32,11 +33,15 @@ const {toOutputScript} = address;
|
|
|
32
33
|
transaction: <Transaction Hex Serialized String>
|
|
33
34
|
}
|
|
34
35
|
*/
|
|
35
|
-
module.exports =
|
|
36
|
+
module.exports = args => {
|
|
36
37
|
if (!args.destination) {
|
|
37
38
|
throw new Error('ExpectedDestinationAddressToSendTokensTo');
|
|
38
39
|
}
|
|
39
40
|
|
|
41
|
+
if (!args.ecp) {
|
|
42
|
+
throw new Error('ExpectedEcpairObjectToChainSendTransaction');
|
|
43
|
+
}
|
|
44
|
+
|
|
40
45
|
if (!args.private_key) {
|
|
41
46
|
throw new Error('ExpectedPrivateKeyToAuthorizeSend');
|
|
42
47
|
}
|
|
@@ -55,7 +60,7 @@ module.exports = (args, cbk) => {
|
|
|
55
60
|
|
|
56
61
|
const network = networks[defaultNetwork];
|
|
57
62
|
|
|
58
|
-
const keyPair =
|
|
63
|
+
const keyPair = args.ecp.fromWIF(args.private_key, network);
|
|
59
64
|
const outputScript = toOutputScript(args.destination, network);
|
|
60
65
|
const tx = new Transaction();
|
|
61
66
|
|
|
@@ -6,9 +6,9 @@ const {spawn} = require('child_process');
|
|
|
6
6
|
const asyncAuto = require('async/auto');
|
|
7
7
|
const asyncMapSeries = require('async/mapSeries');
|
|
8
8
|
const asyncRetry = require('async/retry');
|
|
9
|
-
const {ECPair} = require('ecpair');
|
|
10
9
|
const {networks} = require('bitcoinjs-lib');
|
|
11
10
|
const openPortFinder = require('portfinder');
|
|
11
|
+
const tinysecp = require('tiny-secp256k1');
|
|
12
12
|
|
|
13
13
|
const {changePassword} = require('./../../');
|
|
14
14
|
const {createSeed} = require('./../../');
|
|
@@ -53,6 +53,9 @@ const times = 100;
|
|
|
53
53
|
*/
|
|
54
54
|
module.exports = ({network}, cbk) => {
|
|
55
55
|
return asyncAuto({
|
|
56
|
+
// Import ECPair library
|
|
57
|
+
ecp: async () => (await import('ecpair')).ECPairFactory(tinysecp),
|
|
58
|
+
|
|
56
59
|
// Find open ports for the listen, REST and RPC ports
|
|
57
60
|
getPorts: cbk => {
|
|
58
61
|
return asyncMapSeries(['listen', 'rest', 'rpc'], (_, cbk) => {
|
|
@@ -77,14 +80,14 @@ module.exports = ({network}, cbk) => {
|
|
|
77
80
|
},
|
|
78
81
|
|
|
79
82
|
// Make a private key for mining rewards
|
|
80
|
-
miningKey: cbk => {
|
|
81
|
-
const keyPair =
|
|
83
|
+
miningKey: ['ecp', ({ecp}, cbk) => {
|
|
84
|
+
const keyPair = ecp.makeRandom({network: networks.testnet});
|
|
82
85
|
|
|
83
86
|
return cbk(null, {
|
|
84
87
|
private_key: keyPair.toWIF(),
|
|
85
88
|
public_key: keyPair.publicKey.toString('hex'),
|
|
86
89
|
});
|
|
87
|
-
},
|
|
90
|
+
}],
|
|
88
91
|
|
|
89
92
|
// Spawn a backing chain daemon for lnd
|
|
90
93
|
spawnChainDaemon: ['miningKey', ({miningKey}, cbk) => {
|
|
@@ -3,6 +3,7 @@ const {promisify} = require('util');
|
|
|
3
3
|
const asyncAuto = require('async/auto');
|
|
4
4
|
const asyncEach = require('async/each');
|
|
5
5
|
const asyncRetry = require('async/retry');
|
|
6
|
+
const tinysecp = require('tiny-secp256k1');
|
|
6
7
|
|
|
7
8
|
const {addPeer} = require('./../../');
|
|
8
9
|
const chainSendTransaction = require('./chain_send_transaction');
|
|
@@ -62,6 +63,9 @@ const tokens = 50e8;
|
|
|
62
63
|
*/
|
|
63
64
|
module.exports = (args, cbk) => {
|
|
64
65
|
return asyncAuto({
|
|
66
|
+
// Import ECPair library
|
|
67
|
+
ecp: async () => (await import('ecpair')).ECPairFactory(tinysecp),
|
|
68
|
+
|
|
65
69
|
// Create control lnd
|
|
66
70
|
control: cbk => {
|
|
67
71
|
return spawnLnd({
|
|
@@ -225,11 +229,13 @@ module.exports = (args, cbk) => {
|
|
|
225
229
|
funding: [
|
|
226
230
|
'control',
|
|
227
231
|
'controlChainAddress',
|
|
232
|
+
'ecp',
|
|
228
233
|
'generateBlocks',
|
|
229
234
|
'targetChainAddress',
|
|
230
235
|
({
|
|
231
236
|
control,
|
|
232
237
|
controlChainAddress,
|
|
238
|
+
ecp,
|
|
233
239
|
generateBlocks,
|
|
234
240
|
targetChainAddress,
|
|
235
241
|
},
|
|
@@ -243,6 +249,7 @@ module.exports = (args, cbk) => {
|
|
|
243
249
|
const [targetCoinbase] = targetBlock.transaction_ids;
|
|
244
250
|
|
|
245
251
|
const controlChainSend = chainSendTransaction({
|
|
252
|
+
ecp,
|
|
246
253
|
tokens,
|
|
247
254
|
destination: controlChainAddress.address,
|
|
248
255
|
fee: defaultFee,
|
|
@@ -252,6 +259,7 @@ module.exports = (args, cbk) => {
|
|
|
252
259
|
});
|
|
253
260
|
|
|
254
261
|
const targetChainSend = chainSendTransaction({
|
|
262
|
+
ecp,
|
|
255
263
|
tokens,
|
|
256
264
|
destination: targetChainAddress.address,
|
|
257
265
|
fee: defaultFee,
|
|
@@ -2,14 +2,13 @@ const asyncAuto = require('async/auto');
|
|
|
2
2
|
const asyncMap = require('async/map');
|
|
3
3
|
const asyncTimesSeries = require('async/timesSeries');
|
|
4
4
|
const asyncRetry = require('async/retry');
|
|
5
|
-
const {ECPair} = require('ecpair');
|
|
6
5
|
const {networks} = require('bitcoinjs-lib');
|
|
7
6
|
const {payments} = require('bitcoinjs-lib');
|
|
8
7
|
const {returnResult} = require('asyncjs-util');
|
|
8
|
+
const tinysecp = require('tiny-secp256k1');
|
|
9
9
|
|
|
10
10
|
const rpc = require('./rpc');
|
|
11
11
|
|
|
12
|
-
const {fromPublicKey} = ECPair;
|
|
13
12
|
const interval = retryCount => 2000 * Math.random();
|
|
14
13
|
const {p2pkh} = payments;
|
|
15
14
|
const retryTimes = 50;
|
|
@@ -35,6 +34,9 @@ const retryTimes = 50;
|
|
|
35
34
|
module.exports = ({cert, chain, count, host, key, pass, port, user}, cbk) => {
|
|
36
35
|
return new Promise((resolve, reject) => {
|
|
37
36
|
return asyncAuto({
|
|
37
|
+
// Import ECPair library
|
|
38
|
+
ecp: async () => (await import('ecpair')).ECPairFactory(tinysecp),
|
|
39
|
+
|
|
38
40
|
// Check arguments
|
|
39
41
|
validate: cbk => {
|
|
40
42
|
if (!host) {
|
|
@@ -57,7 +59,7 @@ module.exports = ({cert, chain, count, host, key, pass, port, user}, cbk) => {
|
|
|
57
59
|
},
|
|
58
60
|
|
|
59
61
|
// Generate blocks
|
|
60
|
-
generate: ['validate', ({}, cbk) => {
|
|
62
|
+
generate: ['ecp', 'validate', ({ecp}, cbk) => {
|
|
61
63
|
let cmd;
|
|
62
64
|
let params;
|
|
63
65
|
|
|
@@ -66,7 +68,7 @@ module.exports = ({cert, chain, count, host, key, pass, port, user}, cbk) => {
|
|
|
66
68
|
const miningKey = Buffer.from(key, 'hex');
|
|
67
69
|
const network = networks.testnet;
|
|
68
70
|
|
|
69
|
-
const pubkey = fromPublicKey(miningKey, network).publicKey;
|
|
71
|
+
const pubkey = ecp.fromPublicKey(miningKey, network).publicKey;
|
|
70
72
|
|
|
71
73
|
cmd = 'generatetoaddress';
|
|
72
74
|
params = [[count].length, p2pkh({network, pubkey}).address];
|
package/test/macros/spawn_lnd.js
CHANGED
|
@@ -7,9 +7,9 @@ const asyncAuto = require('async/auto');
|
|
|
7
7
|
const asyncMap = require('async/map');
|
|
8
8
|
const asyncMapSeries = require('async/mapSeries');
|
|
9
9
|
const asyncRetry = require('async/retry');
|
|
10
|
-
const {ECPair} = require('ecpair');
|
|
11
10
|
const {networks} = require('bitcoinjs-lib');
|
|
12
11
|
const openPortFinder = require('portfinder');
|
|
12
|
+
const tinysecp = require('tiny-secp256k1');
|
|
13
13
|
|
|
14
14
|
const {authenticatedLndGrpc} = require('./../../');
|
|
15
15
|
const {createSeed} = require('./../../');
|
|
@@ -79,6 +79,9 @@ const times = 30;
|
|
|
79
79
|
*/
|
|
80
80
|
module.exports = (args, cbk) => {
|
|
81
81
|
return asyncAuto({
|
|
82
|
+
// Import ECPair library
|
|
83
|
+
ecp: async () => (await import('ecpair')).ECPairFactory(tinysecp),
|
|
84
|
+
|
|
82
85
|
// Find open ports for the listen, REST and RPC ports
|
|
83
86
|
getPorts: cbk => {
|
|
84
87
|
return asyncRetry({interval: n => round(random() * 100), times: 1000}, cbk => {
|
|
@@ -112,14 +115,14 @@ module.exports = (args, cbk) => {
|
|
|
112
115
|
},
|
|
113
116
|
|
|
114
117
|
// Make a private key for mining rewards
|
|
115
|
-
miningKey: cbk => {
|
|
116
|
-
const keyPair =
|
|
118
|
+
miningKey: ['ecp', ({ecp}, cbk) => {
|
|
119
|
+
const keyPair = ecp.makeRandom({network: networks.testnet});
|
|
117
120
|
|
|
118
121
|
return cbk(null, {
|
|
119
122
|
private_key: keyPair.toWIF(),
|
|
120
123
|
public_key: keyPair.publicKey.toString('hex'),
|
|
121
124
|
});
|
|
122
|
-
},
|
|
125
|
+
}],
|
|
123
126
|
|
|
124
127
|
// Spawn a backing chain daemon for lnd
|
|
125
128
|
spawnChainDaemon: ['miningKey', ({miningKey}, cbk) => {
|
|
@@ -103,7 +103,7 @@ test(`Pay with multiple paths`, async ({end, equal, rejects, strictSame}) => {
|
|
|
103
103
|
total_mtokens: parsed.mtokens,
|
|
104
104
|
});
|
|
105
105
|
|
|
106
|
-
// Pay using routes. Multiple channels must be used
|
|
106
|
+
// Pay using routes. Multiple channels must be used to avoid tempChanFail
|
|
107
107
|
try {
|
|
108
108
|
const routes = [route1.route, route2.route];
|
|
109
109
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const {test} = require('@alexbosworth/tap');
|
|
2
|
+
const tinysecp = require('tiny-secp256k1');
|
|
2
3
|
|
|
3
4
|
const {broadcastChainTransaction} = require('./../../');
|
|
4
5
|
const {chainSendTransaction} = require('./../macros');
|
|
@@ -32,6 +33,7 @@ test(`Send chain transaction`, async ({end, equal}) => {
|
|
|
32
33
|
fee,
|
|
33
34
|
tokens,
|
|
34
35
|
destination: (await createChainAddress({format, lnd})).address,
|
|
36
|
+
ecp: (await import('ecpair')).ECPairFactory(tinysecp),
|
|
35
37
|
private_key: node.mining_key,
|
|
36
38
|
spend_transaction_id: coinbaseTransactionId,
|
|
37
39
|
spend_vout: defaultVout,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const {test} = require('@alexbosworth/tap');
|
|
2
|
+
const tinysecp = require('tiny-secp256k1');
|
|
2
3
|
|
|
3
4
|
const {broadcastChainTransaction} = require('./../../');
|
|
4
5
|
const {chainSendTransaction} = require('./../macros');
|
|
@@ -31,6 +32,7 @@ test(`Request chain fee increase`, async ({end, equal}) => {
|
|
|
31
32
|
fee,
|
|
32
33
|
tokens,
|
|
33
34
|
destination: (await createChainAddress({format, lnd})).address,
|
|
35
|
+
ecp: (await import('ecpair')).ECPairFactory(tinysecp),
|
|
34
36
|
private_key: node.mining_key,
|
|
35
37
|
spend_transaction_id: coinbaseTransactionId,
|
|
36
38
|
spend_vout: defaultVout,
|