ln-service 53.17.5 → 53.20.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 CHANGED
@@ -1,5 +1,25 @@
1
1
  # Versions
2
2
 
3
+ ## 53.20.0
4
+
5
+ - `closeChannel`: Add support for `max_tokens_per_vbyte` to set max fee rate
6
+ - `getChainTransactions`: Add `inputs` support for previous outpoints
7
+ - `subscribeToTransactions`: Add `inputs` support for previous outpoints
8
+
9
+ ## 53.19.0
10
+
11
+ - `signBytes`: Add `type` and support for specifying `schnorr` type signing
12
+ - `verifyBytesSignature`: Add support for verifying Schnorr signatures
13
+
14
+ ## 53.18.0
15
+
16
+ - `getChannels`: Add support for `is_trusted_funding` and `other_ids`
17
+ - `getClosedChannels`: Add support for `other_ids`
18
+ - `getEphemeralChannelIds`: Add method to get other channel ids
19
+ - `openChannels`: Add support for `is_trusted_funding` for instant opening
20
+ - `subscribeToChannels`: Add support for `is_trusted_funding`, `other_ids`
21
+ - `subscribeToOpenRequests`: Add support for `is_trusted_funding`
22
+
3
23
  ## 53.17.5
4
24
 
5
25
  - `signTransaction`: Add `root_hash` to support Taproot signatures with scripts
package/README.md CHANGED
@@ -13,7 +13,6 @@ Supported LND versions:
13
13
  - v0.14.0-beta to v0.14.3-beta
14
14
  - v0.13.0-beta to v0.13.4-beta
15
15
  - v0.12.0-beta to v0.12.1-beta
16
- - v0.11.0-beta to v0.11.1-beta
17
16
 
18
17
  For typescript-ready methods, check out https://github.com/alexbosworth/lightning#readme
19
18
 
@@ -151,6 +150,7 @@ for `unlocker` methods.
151
150
  - [getChannels](#getchannels) - Get all open channels
152
151
  - [getClosedChannels](#getclosedchannels) - Get previously open channels
153
152
  - [getConnectedWatchtowers](#getconnectedwatchtowers) - Get connected towers
153
+ - [getEphemeralChannelIds](#getephemeralchannelids) - Get other channel ids
154
154
  - [getFailedPayments](#getfailedpayments) - Get payments that were failed back
155
155
  - [getFeeRates](#getfeerates) - Get current routing fee rates
156
156
  - [getForwardingConfidence](#getforwardingconfidence) - Get pairwise confidence
@@ -528,17 +528,23 @@ Either an id or a transaction id / transaction output index is required
528
528
 
529
529
  If cooperatively closing, pass a public key and socket to connect
530
530
 
531
- Requires `info:read`, `offchain:write`, `onchain:write`, `peers:write` permissions
531
+ `max_tokens_per_vbyte` will be ignored when closing a peer initiated channel
532
+
533
+ Requires `info:read`, `offchain:write`, `onchain:write`, `peers:write`
534
+ permissions
535
+
536
+ `max_tokens_per_vbyte` is not supported in LND 0.15.0 and below
532
537
 
533
538
  {
534
539
  [address]: <Request Sending Local Channel Funds To Address String>
535
540
  [id]: <Standard Format Channel Id String>
536
541
  [is_force_close]: <Is Force Close Bool>
537
542
  lnd: <Authenticated LND API Object>
543
+ [max_tokens_per_vbyte]: <Fail Cooperative Close Above Fee Rate Number>
538
544
  [public_key]: <Peer Public Key String>
539
545
  [socket]: <Peer Socket String>
540
546
  [target_confirmations]: <Confirmation Target Number>
541
- [tokens_per_vbyte]: <Tokens Per Virtual Byte Number>
547
+ [tokens_per_vbyte]: <Target Tokens Per Virtual Byte Number>
542
548
  [transaction_id]: <Transaction Id Hex String>
543
549
  [transaction_vout]: <Transaction Output Index Number>
544
550
  }
@@ -1485,10 +1491,12 @@ Get chain transactions.
1485
1491
 
1486
1492
  Requires `onchain:read` permission
1487
1493
 
1494
+ `inputs` are not supported on LND 0.15.0 and below
1495
+
1488
1496
  {
1489
1497
  [after]: <Confirmed After Current Best Chain Block Height Number>
1490
1498
  [before]: <Confirmed Before Current Best Chain Block Height Number>
1491
- lnd: <Authenticated LND Object>
1499
+ lnd: <Authenticated LND API Object>
1492
1500
  }
1493
1501
 
1494
1502
  @returns via cbk or Promise
@@ -1501,6 +1509,11 @@ Requires `onchain:read` permission
1501
1509
  [description]: <Transaction Label String>
1502
1510
  [fee]: <Fees Paid Tokens Number>
1503
1511
  id: <Transaction Id String>
1512
+ inputs: [{
1513
+ is_local: <Spent Outpoint is Local Bool>
1514
+ transaction_id: <Transaction Id Hex String>
1515
+ transaction_vout: <Transaction Output Index Number>
1516
+ }]
1504
1517
  is_confirmed: <Is Confirmed Bool>
1505
1518
  is_outgoing: <Transaction Outbound Bool>
1506
1519
  output_addresses: [<Address String>]
@@ -1602,6 +1615,8 @@ Requires `offchain:read` permission
1602
1615
  `in_channel`, `in_payment`, `is_forward`, `out_channel`, `out_payment`,
1603
1616
  `payment` are not supported on LND 0.11.1 and below
1604
1617
 
1618
+ `is_trusted_funding` is not supported on LND 0.15.0 and below
1619
+
1605
1620
  {
1606
1621
  [is_active]: <Limit Results To Only Active Channels Bool> // false
1607
1622
  [is_offline]: <Limit Results To Only Offline Channels Bool> // false
@@ -1625,6 +1640,7 @@ Requires `offchain:read` permission
1625
1640
  is_opening: <Channel Is Opening Bool>
1626
1641
  is_partner_initiated: <Channel Partner Opened Channel Bool>
1627
1642
  is_private: <Channel Is Private Bool>
1643
+ [is_trusted_funding]: <Funding Output is Trusted Bool>
1628
1644
  local_balance: <Local Balance Tokens Number>
1629
1645
  [local_csv]: <Local CSV Blocks Delay Number>
1630
1646
  [local_dust]: <Local Non-Enforceable Amount Tokens Number>
@@ -1633,6 +1649,7 @@ Requires `offchain:read` permission
1633
1649
  [local_max_pending_mtokens]: <Local Maximum Pending Millitokens String>
1634
1650
  [local_min_htlc_mtokens]: <Local Minimum HTLC Millitokens String>
1635
1651
  local_reserve: <Local Reserved Tokens Number>
1652
+ other_ids: [<Other Channel Id String>]
1636
1653
  partner_public_key: <Channel Partner Public Key String>
1637
1654
  past_states: <Total Count of Past Channel States Number>
1638
1655
  pending_payments: [{
@@ -1682,6 +1699,8 @@ Multiple close type flags are supported.
1682
1699
 
1683
1700
  Requires `offchain:read` permission
1684
1701
 
1702
+ `other_ids is not supported on LND 0.15.0 and below
1703
+
1685
1704
  {
1686
1705
  [is_breach_close]: <Only Return Breach Close Channels Bool>
1687
1706
  [is_cooperative_close]: <Only Return Cooperative Close Channels Bool>
@@ -1719,6 +1738,7 @@ Requires `offchain:read` permission
1719
1738
  [is_partner_closed]: <Channel Was Closed By Channel Peer Bool>
1720
1739
  [is_partner_initiated]: <Channel Was Initiated By Channel Peer Bool>
1721
1740
  is_remote_force_close: <Is Remote Force Close Bool>
1741
+ other_ids: [<Other Channel Id String>]
1722
1742
  partner_public_key: <Partner Public Key Hex String>
1723
1743
  transaction_id: <Channel Funding Transaction Id Hex String>
1724
1744
  transaction_vout: <Channel Funding Output Index Number>
@@ -1776,6 +1796,35 @@ const {getConnectedWatchtowers} = require('ln-service');
1776
1796
  const {towers} = (await getConnectedWatchtowers({lnd}));
1777
1797
  ```
1778
1798
 
1799
+ ### getEphemeralChannelIds
1800
+
1801
+ Get ephemeral channel ids
1802
+
1803
+ Requires `offchain:read` permission
1804
+
1805
+ This method is not supported on LND 0.15.0 and below
1806
+
1807
+ {
1808
+ lnd: <Authenticated LND API Object>
1809
+ }
1810
+
1811
+ @returns via cbk or Promise
1812
+ {
1813
+ channels: [{
1814
+ other_ids: [<Channel Identifier String>]
1815
+ reference_id: <Top Level Channel Identifier String>
1816
+ }]
1817
+ }
1818
+
1819
+ Example:
1820
+
1821
+ ```node
1822
+ const {getEphemeralChannelIds} = require('ln-service');
1823
+
1824
+ // Get the list of ephemeral ids related to channels
1825
+ const {channels} = await getEphemeralChannelIds({lnd});
1826
+ ```
1827
+
1779
1828
  ### getFailedPayments
1780
1829
 
1781
1830
  Get failed payments made through channels.
@@ -1860,6 +1909,15 @@ Requires `offchain:read` permission
1860
1909
  [next]: <Next Opaque Paging Token String>
1861
1910
  }
1862
1911
 
1912
+ Example:
1913
+
1914
+ ```node
1915
+ const {getFailedPayments} = require('ln-service');
1916
+
1917
+ // Get the list of failed payments
1918
+ const {payments} = await getFailedPayments({lnd});
1919
+ ```
1920
+
1863
1921
  ### getFeeRates
1864
1922
 
1865
1923
  Get a rundown on fees for channels
@@ -3550,12 +3608,17 @@ channel that was not funded.
3550
3608
  Use `is_avoiding_broadcast` only when self-publishing the raw transaction
3551
3609
  after the funding step.
3552
3610
 
3611
+ `is_trusted_funding` is not supported on LND 0.15.0 and below and requires
3612
+ `--protocol.option-scid-alias` and `--protocol.zero-conf` set on both sides
3613
+ as well as a channel open request listener to accept the trusted funding.
3614
+
3553
3615
  {
3554
3616
  channels: [{
3555
3617
  capacity: <Channel Capacity Tokens Number>
3556
3618
  [cooperative_close_address]: <Restrict Coop Close To Address String>
3557
3619
  [give_tokens]: <Tokens to Gift To Partner Number> // Defaults to zero
3558
3620
  [is_private]: <Channel is Private Bool> // Defaults to false
3621
+ [is_trusted_funding]: <Peer Should Avoid Waiting For Confirmation Bool>
3559
3622
  [min_htlc_mtokens]: <Minimum HTLC Millitokens String>
3560
3623
  [partner_csv_delay]: <Peer Output CSV Delay Number>
3561
3624
  partner_public_key: <Public Key Hex String>
@@ -4684,15 +4747,20 @@ await settleHodlInvoice({lnd, secret});
4684
4747
 
4685
4748
  Sign a sha256 hash of arbitrary bytes
4686
4749
 
4750
+ Supported signature types: `ecdsa`, `schnorr`
4751
+
4687
4752
  Requires LND built with `signrpc` build tag
4688
4753
 
4689
4754
  Requires `signer:generate` permission
4690
4755
 
4756
+ `schnorr` signature type is not supported on LND 0.15.0 and below
4757
+
4691
4758
  {
4692
4759
  key_family: <Key Family Number>
4693
4760
  key_index: <Key Index Number>
4694
4761
  lnd: <Authenticated LND gRPC API Object>
4695
4762
  preimage: <Bytes To Hash and Sign Hex Encoded String>
4763
+ [type]: <Signature Type String>
4696
4764
  }
4697
4765
 
4698
4766
  @returns via cbk or Promise
@@ -5002,6 +5070,8 @@ Subscribe to channel updates
5002
5070
 
5003
5071
  Requires `offchain:read` permission
5004
5072
 
5073
+ `is_trusted_funding`, `other_ids` are not supported on LND 0.15.0 and below
5074
+
5005
5075
  {
5006
5076
  lnd: <Authenticated LND API Object>
5007
5077
  }
@@ -5046,6 +5116,7 @@ Requires `offchain:read` permission
5046
5116
  [is_partner_closed]: <Channel Was Closed By Channel Peer Bool>
5047
5117
  [is_partner_initiated]: <Channel Was Initiated By Channel Peer Bool>
5048
5118
  is_remote_force_close: <Is Remote Force Close Bool>
5119
+ other_ids: [<Other Channel Id String>]
5049
5120
  partner_public_key: <Partner Public Key Hex String>
5050
5121
  transaction_id: <Channel Funding Transaction Id Hex String>
5051
5122
  transaction_vout: <Channel Funding Output Index Number>
@@ -5064,6 +5135,7 @@ Requires `offchain:read` permission
5064
5135
  is_opening: <Channel Is Opening Bool>
5065
5136
  is_partner_initiated: <Channel Partner Opened Channel Bool>
5066
5137
  is_private: <Channel Is Private Bool>
5138
+ [is_trusted_funding]: <Funding Output is Trusted Bool>
5067
5139
  local_balance: <Local Balance Tokens Number>
5068
5140
  [local_given]: <Local Initially Pushed Tokens Number>
5069
5141
  local_reserve: <Local Reserved Tokens Number>
@@ -5452,6 +5524,8 @@ listeners to `channel_request`
5452
5524
 
5453
5525
  LND 0.11.1 and below do not support `accept` or `reject` arguments
5454
5526
 
5527
+ LND 0.15.0 and below do not support `is_trusted_funding`
5528
+
5455
5529
  {
5456
5530
  lnd: <Authenticated LND API Object>
5457
5531
  }
@@ -6553,6 +6627,8 @@ Subscribe to transactions
6553
6627
 
6554
6628
  Requires `onchain:read` permission
6555
6629
 
6630
+ `inputs` are not supported on LND 0.15.0 and below
6631
+
6556
6632
  {
6557
6633
  lnd: <Authenticated LND API Object>
6558
6634
  }
@@ -6571,6 +6647,11 @@ Requires `onchain:read` permission
6571
6647
  created_at: <Created ISO 8601 Date String>
6572
6648
  [fee]: <Fees Paid Tokens Number>
6573
6649
  id: <Transaction Id String>
6650
+ inputs: [{
6651
+ is_local: <Spent Outpoint is Local Bool>
6652
+ transaction_id: <Transaction Id Hex String>
6653
+ transaction_vout: <Transaction Output Index Number>
6654
+ }]
6574
6655
  is_confirmed: <Is Confirmed Bool>
6575
6656
  is_outgoing: <Transaction Outbound Bool>
6576
6657
  output_addresses: [<Address String>]
@@ -7039,10 +7120,14 @@ const isValid = (await verifyBackups({backup, channels, lnd})).is_valid;
7039
7120
 
7040
7121
  Verify signature of arbitrary bytes
7041
7122
 
7123
+ When passing a schnorr signature, a BIP-340 x-only public key should be given
7124
+
7042
7125
  Requires LND built with `signrpc` build tag
7043
7126
 
7044
7127
  Requires `signer:read` permission
7045
7128
 
7129
+ Validating `schnorr` signatures is unsupported in LND 0.15.0 and below
7130
+
7046
7131
  {
7047
7132
  lnd: <Authenticated LND API Object>
7048
7133
  preimage: <Message Preimage Bytes Hex Encoded String>
package/index.js CHANGED
@@ -42,6 +42,7 @@ const {getChannelBalance} = require('lightning');
42
42
  const {getChannels} = require('lightning');
43
43
  const {getClosedChannels} = require('lightning');
44
44
  const {getConnectedWatchtowers} = require('lightning');
45
+ const {getEphemeralChannelIds} = require('lightning');
45
46
  const {getFailedPayments} = require('lightning');
46
47
  const {getFeeRates} = require('lightning');
47
48
  const {getForwardingConfidence} = require('lightning');
@@ -191,6 +192,7 @@ module.exports = {
191
192
  getChannels,
192
193
  getClosedChannels,
193
194
  getConnectedWatchtowers,
195
+ getEphemeralChannelIds,
194
196
  getFailedPayments,
195
197
  getFeeRates,
196
198
  getForwardingConfidence,
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "cors": "2.8.5",
12
12
  "express": "4.18.1",
13
13
  "invoices": "2.1.0",
14
- "lightning": "5.16.6",
14
+ "lightning": "5.19.0",
15
15
  "macaroon": "3.0.4",
16
16
  "morgan": "1.10.0",
17
17
  "ws": "8.8.1"
@@ -28,9 +28,9 @@
28
28
  "bn.js": "5.2.1",
29
29
  "bs58check": "2.1.2",
30
30
  "ecpair": "2.0.1",
31
- "ln-docker-daemons": "2.3.2",
31
+ "ln-docker-daemons": "2.3.4",
32
32
  "p2tr": "1.3.1",
33
- "portfinder": "1.0.28",
33
+ "portfinder": "1.0.32",
34
34
  "psbt": "2.7.1",
35
35
  "rimraf": "3.0.2",
36
36
  "secp256k1": "4.0.3",
@@ -56,7 +56,6 @@
56
56
  "url": "https://github.com/alexbosworth/ln-service.git"
57
57
  },
58
58
  "scripts": {
59
- "integration-test-daily-lnd-build": "DOCKER_LND_VERSION=daily-testing-only npm run test",
60
59
  "integration-test-0.15.0": "DOCKER_LND_VERSION=v0.15.0-beta npm run test",
61
60
  "integration-test-0.14.3": "DOCKER_LND_VERSION=v0.14.3-beta npm run test",
62
61
  "integration-test-0.14.2": "DOCKER_LND_VERSION=v0.14.2-beta npm run test",
@@ -71,5 +70,5 @@
71
70
  "integration-test-0.12.0": "DOCKER_LND_VERSION=v0.12.0-beta npm run test",
72
71
  "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/peersrpc-integration/*.js test/routerrpc-integration/*.js test/signerrpc-integration/*.js test/tower_clientrpc-integration/*.js test/tower_serverrpc-integration/*.js test/walletrpc-integration/*.js"
73
72
  },
74
- "version": "53.17.5"
73
+ "version": "53.20.0"
75
74
  }
@@ -8,7 +8,7 @@ const {getPeers} = require('./../../');
8
8
 
9
9
  const interval = 100;
10
10
  const size = 2;
11
- const times = 2000;
11
+ const times = 4000;
12
12
  const timeout = 100;
13
13
 
14
14
  // Adding peers should result in a connected peer
@@ -18,6 +18,7 @@ const {fundPsbt} = require('./../../');
18
18
  const {getChainBalance} = require('./../../');
19
19
  const {getChannels} = require('./../../');
20
20
  const {getLockedUtxos} = require('./../../');
21
+ const {getMasterPublicKeys} = require('./../../');
21
22
  const {getPendingChannels} = require('./../../');
22
23
  const {openChannels} = require('./../../');
23
24
  const {signPsbt} = require('./../../');
@@ -41,6 +42,17 @@ test(`Forfeit pending channel`, async ({end, equal, strictSame}) => {
41
42
 
42
43
  const {generate, lnd} = control;
43
44
 
45
+ try {
46
+ const {keys} = await getMasterPublicKeys({lnd});
47
+ } catch (err) {
48
+ // LND 0.13.3 and below should not be tested
49
+ strictSame(err, [501, 'GetMasterPublicKeysMethodNotSupported'], 'Got err');
50
+
51
+ await kill({});
52
+
53
+ return end();
54
+ }
55
+
44
56
  try {
45
57
  await control.generate({count});
46
58
 
@@ -20,12 +20,16 @@ test(`Get chain transactions`, async ({end, equal, strictSame}) => {
20
20
  // Generate some funds for LND
21
21
  await generate({count});
22
22
 
23
- await asyncRetry({interval: 10, times: 1000}, async () => {
23
+ await asyncRetry({interval: 10, times: 2000}, async () => {
24
24
  const wallet = await getWalletInfo({lnd});
25
25
 
26
26
  if (!wallet.is_synced_to_chain) {
27
27
  throw new Error('ExpectedWalletSyncedToChain');
28
28
  }
29
+
30
+ if (wallet.current_block_height !== count + 1) {
31
+ throw new Error('ExpectedFullySyncedToChain');
32
+ }
29
33
  });
30
34
 
31
35
  // Wait for generation to be over
@@ -72,11 +72,13 @@ test(`Get closed channels`, async ({end, equal}) => {
72
72
 
73
73
  equal(channels.length, [channelOpen].length, 'Channel close listed');
74
74
 
75
+ const spend = maxChanTokens - channel.final_local_balance;
76
+
75
77
  // LND 0.11.1 and below do not use anchors
76
78
  if (isAnchors) {
77
- equal(maxChanTokens - channel.final_local_balance, 2810, 'Final');
79
+ equal([53345, 2810].includes(spend), true, 'Final');
78
80
  } else {
79
- equal(maxChanTokens - channel.final_local_balance, 9050, 'Final');
81
+ equal(spend, 9050, 'Final');
80
82
  }
81
83
 
82
84
  equal(channel.capacity, maxChanTokens, 'Channel capacity reflected');
@@ -217,14 +219,14 @@ test(`Get closed channels`, async ({end, equal}) => {
217
219
  equal(!!settleHtlc.transaction_id, true, 'Output tx id');
218
220
  equal(settleHtlc.transaction_vout !== undefined, true, 'Output tx vout');
219
221
 
220
- const alsoDead = await asyncRetry({interval: 2000, times: 99}, async () => {
222
+ const alsoDead = await asyncRetry({interval: 20, times: 7000}, async () => {
221
223
  const {channels} = await getClosedChannels({lnd: target.lnd});
222
224
 
223
225
  if (channels.length === [toForceClose, channelOpen].length) {
224
226
  return channels;
225
227
  }
226
228
 
227
- await target.generate({count: 100});
229
+ await target.generate({});
228
230
 
229
231
  throw new Error('WaitingForTargetForceClose');
230
232
  });
@@ -56,8 +56,6 @@ test(`Get node`, async ({end, equal, strictSame}) => {
56
56
  });
57
57
  });
58
58
 
59
- await delay(3000);
60
-
61
59
  const node = await getNode({lnd, public_key: id});
62
60
 
63
61
  {
@@ -17,60 +17,64 @@ test(`Get pending channels`, async ({end, equal}) => {
17
17
 
18
18
  const [{generate, lnd}, target] = nodes;
19
19
 
20
- const {features} = await getWalletInfo({lnd});
20
+ try {
21
+ const {features} = await getWalletInfo({lnd});
21
22
 
22
- const isAnchors = !!features.find(n => n.bit === anchorsFeatureBit);
23
+ const isAnchors = !!features.find(n => n.bit === anchorsFeatureBit);
23
24
 
24
- // Target starts a channel with control
25
- const coopChan = await setupChannel({generate, give, lnd, to: target});
25
+ // Target starts a channel with control
26
+ const coopChan = await setupChannel({generate, give, lnd, to: target});
26
27
 
27
- // Target closes the channel
28
- const niceClose = await closeChannel({
29
- lnd: target.lnd,
30
- tokens_per_vbyte: defaultFee,
31
- transaction_id: coopChan.transaction_id,
32
- transaction_vout: coopChan.transaction_vout,
33
- });
28
+ // Target closes the channel
29
+ const niceClose = await closeChannel({
30
+ lnd: target.lnd,
31
+ tokens_per_vbyte: 100,
32
+ transaction_id: coopChan.transaction_id,
33
+ transaction_vout: coopChan.transaction_vout,
34
+ });
34
35
 
35
- // Control views their pending channels
36
- const {channel} = await waitForPendingChannel({
37
- lnd,
38
- id: coopChan.transaction_id,
39
- });
36
+ // Control views their pending channels
37
+ const {channel} = await waitForPendingChannel({
38
+ lnd,
39
+ id: coopChan.transaction_id,
40
+ });
40
41
 
41
- if (channel.is_partner_initiated !== undefined) {
42
- equal(channel.is_partner_initiated, false, 'Channel was initiated');
43
- }
42
+ if (channel.is_partner_initiated !== undefined) {
43
+ equal(channel.is_partner_initiated, false, 'Channel was initiated');
44
+ }
44
45
 
45
- // LND 0.11.1 and below do not support anchor channels
46
- if (isAnchors) {
47
- equal(channel.local_balance, 986530, 'Original balance');
48
- equal(channel.pending_balance, 986530, 'Waiting on balance');
49
- } else {
50
- equal(channel.local_balance, 980950, 'Original balance');
51
- equal(channel.pending_balance, 980950, 'Waiting on balance');
52
- }
46
+ // LND 0.11.1 and below do not support anchor channels
47
+ if (isAnchors) {
48
+ equal(channel.local_balance, 986530, 'Original balance');
49
+ equal(channel.pending_balance, 986530, 'Waiting on balance');
50
+ } else {
51
+ equal(channel.local_balance, 980950, 'Original balance');
52
+ equal(channel.pending_balance, 980950, 'Waiting on balance');
53
+ }
53
54
 
54
- equal(channel.capacity, 1000000, 'Got channel capacity');
55
- equal(channel.close_transaction_id, undefined, 'No close tx id');
56
- equal(channel.is_active, false, 'Ended');
57
- equal(channel.is_closing, true, 'Closing');
58
- equal(channel.is_opening, false, 'Not Opening');
59
- equal(channel.local_reserve, 10000, 'Local reserve');
60
- equal(channel.partner_public_key, target.id, 'Target public key');
61
- equal(channel.pending_payments, undefined, 'No pending payments');
62
- equal(channel.received, 0, 'Never received');
63
- equal(channel.recovered_tokens, undefined, 'Nothing to recover in sweep');
64
- equal(channel.remote_reserve, 10000, 'Remote reserve');
65
- equal(channel.sent, 0, 'Never sent anything');
66
- equal(channel.timelock_expiration, undefined, 'No timelock in coop mode');
67
- equal(channel.transaction_fee, null, 'No transaction fee data');
68
- equal(channel.transaction_id, coopChan.transaction_id, 'funding tx id');
69
- equal(channel.transaction_vout, coopChan.transaction_vout, 'funding vout');
70
- equal(channel.transaction_weight, null, 'No funding tx weight data');
55
+ equal(channel.capacity, 1000000, 'Got channel capacity');
56
+ equal(channel.close_transaction_id, undefined, 'No close tx id');
57
+ equal(channel.is_active, false, 'Ended');
58
+ equal(channel.is_closing, true, 'Closing');
59
+ equal(channel.is_opening, false, 'Not Opening');
60
+ equal(channel.local_reserve, 10000, 'Local reserve');
61
+ equal(channel.partner_public_key, target.id, 'Target public key');
62
+ equal(channel.pending_payments, undefined, 'No pending payments');
63
+ equal(channel.received, 0, 'Never received');
64
+ equal(channel.recovered_tokens, undefined, 'Nothing to recover in sweep');
65
+ equal(channel.remote_reserve, 10000, 'Remote reserve');
66
+ equal(channel.sent, 0, 'Never sent anything');
67
+ equal(channel.timelock_expiration, undefined, 'No timelock in coop mode');
68
+ equal(channel.transaction_fee, null, 'No transaction fee data');
69
+ equal(channel.transaction_id, coopChan.transaction_id, 'funding tx id');
70
+ equal(channel.transaction_vout, coopChan.transaction_vout, 'funding vout');
71
+ equal(channel.transaction_weight, null, 'No funding tx weight data');
71
72
 
72
- if (!!channel.remote_balance) {
73
- equal(channel.remote_balance, give, 'Opposing channel balance');
73
+ if (!!channel.remote_balance) {
74
+ equal(channel.remote_balance, give, 'Opposing channel balance');
75
+ }
76
+ } catch (err) {
77
+ equal(err, null, 'Expected no error');
74
78
  }
75
79
 
76
80
  await kill({});
@@ -334,7 +334,7 @@ test(`Propose a channel with a coop delay`, async ({end, equal, ok}) => {
334
334
  });
335
335
 
336
336
  const coopCloseAddress = await createChainAddress({
337
- format: 'np2wpkh',
337
+ format: 'p2wpkh',
338
338
  lnd: control.lnd,
339
339
  });
340
340
 
@@ -6,7 +6,9 @@ const {addPeer} = require('./../../');
6
6
  const {getPeers} = require('./../../');
7
7
  const {removePeer} = require('./../../');
8
8
 
9
+ const interval = 10;
9
10
  const size = 2;
11
+ const times = 2000;
10
12
 
11
13
  // Removing peers should result in a removed peer
12
14
  test(`Remove a peer`, async ({end, equal}) => {
@@ -15,7 +17,7 @@ test(`Remove a peer`, async ({end, equal}) => {
15
17
  const [{id, lnd}, target] = nodes;
16
18
 
17
19
  try {
18
- await asyncRetry({interval: 10, times: 2000}, async () => {
20
+ await asyncRetry({interval, times}, async () => {
19
21
  await addPeer({lnd, public_key: target.id, socket: target.socket});
20
22
  });
21
23
 
@@ -27,9 +29,15 @@ test(`Remove a peer`, async ({end, equal}) => {
27
29
 
28
30
  await removePeer({lnd, public_key: targetPeer.public_key});
29
31
 
30
- const postRemovalPeers = await getPeers({lnd});
32
+ await asyncRetry({interval, times}, async () => {
33
+ const postRemovalPeers = await getPeers({lnd});
31
34
 
32
- equal(postRemovalPeers.peers.length, [].length, 'Peer is removed');
35
+ if (!!postRemovalPeers.peers.length) {
36
+ throw new Error('ExpectedPeerRemoved');
37
+ }
38
+
39
+ equal(postRemovalPeers.peers.length, [].length, 'Peer is removed');
40
+ });
33
41
  } catch (err) {
34
42
  equal(err, null, 'Expected no error');
35
43
  }
@@ -148,7 +148,9 @@ test('Subscribe to channels', async ({end, equal, fail}) => {
148
148
  const closeEvent = channelClosed.pop();
149
149
 
150
150
  if (isAnchors) {
151
- equal(closeEvent.final_local_balance, 897190, 'Close final local balance');
151
+ const final = closeEvent.final_local_balance;
152
+
153
+ equal([897190, 846655].includes(final), true, 'Close final local balance');
152
154
  } else {
153
155
  equal(closeEvent.final_local_balance, 890950, 'Close final local balance');
154
156
  }
@@ -0,0 +1,248 @@
1
+ const asyncRetry = require('async/retry');
2
+ const {spawnLightningCluster} = require('ln-docker-daemons');
3
+ const {test} = require('@alexbosworth/tap');
4
+
5
+ const {addPeer} = require('./../../');
6
+ const {broadcastChainTransaction} = require('./../../');
7
+ const {closeChannel} = require('./../../');
8
+ const {createInvoice} = require('./../../');
9
+ const {fundPendingChannels} = require('./../../');
10
+ const {fundPsbt} = require('./../../');
11
+ const {getChannels} = require('./../../');
12
+ const {getClosedChannels} = require('./../../');
13
+ const {getEphemeralChannelIds} = require('./../../');
14
+ const {getPendingChannels} = require('./../../');
15
+ const {openChannels} = require('./../../');
16
+ const {pay} = require('./../../');
17
+ const {signPsbt} = require('./../../');
18
+ const {subscribeToChannels} = require('./../../');
19
+ const {subscribeToOpenRequests} = require('./../../');
20
+
21
+ const capacity = 1e6;
22
+ const interval = 10;
23
+ const maturity = 100;
24
+ const size = 2;
25
+ const times = 2000;
26
+
27
+ // Opening unconfirmed channels should in immediate channel opening
28
+ test(`Open unconfirmed channels`, async ({end, equal, match, strictSame}) => {
29
+ // Unconfirmed channels are not supported on LND 0.15.0 and below
30
+ {
31
+ const {kill, nodes} = await spawnLightningCluster({});
32
+
33
+ const [{lnd}] = nodes;
34
+
35
+ try {
36
+ await getEphemeralChannelIds({lnd});
37
+ } catch (err) {
38
+ strictSame(err, [501, 'ListAliasesMethodNotSupported']);
39
+
40
+ await kill({});
41
+
42
+ return end();
43
+ }
44
+ }
45
+
46
+ const {kill, nodes} = await spawnLightningCluster({
47
+ size,
48
+ lnd_configuration: [
49
+ '--maxpendingchannels=10',
50
+ '--protocol.option-scid-alias',
51
+ '--protocol.zero-conf',
52
+ ],
53
+ });
54
+
55
+ const [{generate, lnd}, target] = nodes;
56
+
57
+ try {
58
+ // Make some funds to use
59
+ await generate({count: maturity});
60
+
61
+ // Connect to the peer
62
+ await addPeer({lnd, public_key: target.id, socket: target.socket});
63
+
64
+ // Wait for channel to be receptive to opens
65
+ await asyncRetry({interval, times}, async () => {
66
+ return await openChannels({
67
+ lnd,
68
+ channels: [{capacity, partner_public_key: target.id}],
69
+ });
70
+ });
71
+
72
+ const acceptSub = subscribeToOpenRequests({lnd: target.lnd});
73
+ const channelsSub = subscribeToChannels({lnd});
74
+
75
+ const closings = [];
76
+ const opened = [];
77
+
78
+ channelsSub.on('channel_closed', update => closings.push(update));
79
+ channelsSub.on('channel_opened', update => opened.push(update));
80
+
81
+ acceptSub.on('channel_request', request => {
82
+ equal(request.is_trusted_funding, true, 'Request is trusted funding');
83
+
84
+ return request.accept({is_trusted_funding: true});
85
+ });
86
+
87
+ // Propose the channel to the peer
88
+ const {pending} = await openChannels({
89
+ lnd,
90
+ channels: [{
91
+ capacity,
92
+ is_trusted_funding: true,
93
+ partner_public_key: target.id,
94
+ }],
95
+ });
96
+
97
+ // Setup funding to the 2:2 output
98
+ const fundTarget = await fundPsbt({lnd, outputs: pending});
99
+
100
+ // Sign the funding to the 2:2 output
101
+ const {psbt, transaction} = await signPsbt({lnd, psbt: fundTarget.psbt});
102
+
103
+ // Fund the channel
104
+ await fundPendingChannels({
105
+ lnd,
106
+ channels: pending.map(({id}) => id),
107
+ funding: psbt,
108
+ });
109
+
110
+ const invoice = await createInvoice({
111
+ lnd: target.lnd,
112
+ tokens: 100,
113
+ });
114
+
115
+ const channel = await asyncRetry({interval, times}, async () => {
116
+ const {channels} = await getChannels({lnd, is_active: true});
117
+
118
+ if (!channels.length) {
119
+ throw new Error('ExpectedTrustedChannelToAppear');
120
+ }
121
+
122
+ const [channel] = channels;
123
+
124
+ return channel;
125
+ });
126
+
127
+ // Make sure the channel reflects that it is trusted funding
128
+ strictSame(channel.other_ids, [], 'Got no ephemeral ids');
129
+ match(channel.id, /16000000x0/, 'Channel id is faked');
130
+ equal(channel.is_trusted_funding, true, 'Channel funding is trusted');
131
+
132
+ // Make sure the open channel event reflected that it was trusted funding
133
+ const [event] = opened;
134
+
135
+ strictSame(event.other_ids, [], 'Got no event ephemeral ids');
136
+ match(event.id, /16000000x0/, 'Channel event id is faked');
137
+ equal(event.is_trusted_funding, true, 'Channel event funding is trusted');
138
+
139
+ // Make sure the channel can be used immediately
140
+ await pay({lnd, request: invoice.request});
141
+
142
+ // Generate the channel into a block
143
+ await broadcastChainTransaction({lnd, transaction});
144
+
145
+ const confirmed = await asyncRetry({interval, times}, async () => {
146
+ await generate({});
147
+
148
+ const [confirmed] = (await getChannels({lnd})).channels;
149
+
150
+ if (confirmed.id === channel.id) {
151
+ throw new Error('ExpectedChangeToRealChannelId');
152
+ }
153
+
154
+ return confirmed;
155
+ });
156
+
157
+ equal(confirmed.id, '102x1x0', 'Channel id is real now');
158
+ equal(confirmed.is_trusted_funding, true, 'Channel funding was trusted');
159
+ equal(confirmed.other_ids.length, 1, 'Got ephemeral id');
160
+
161
+ const [otherId] = confirmed.other_ids;
162
+
163
+ match(otherId, /16000000x0/, 'Got ephemeral id');
164
+
165
+ await closeChannel({lnd, id: confirmed.id});
166
+
167
+ // Propose a private channel to the peer
168
+ const openPrivate = await asyncRetry({interval, times}, async () => {
169
+ return await openChannels({
170
+ lnd,
171
+ channels: [{
172
+ capacity,
173
+ is_private: true,
174
+ is_trusted_funding: true,
175
+ partner_public_key: target.id,
176
+ }],
177
+ });
178
+ });
179
+
180
+ // Setup funding to the 2:2 output for the private channel
181
+ const fundPrivate = await fundPsbt({lnd, outputs: openPrivate.pending});
182
+
183
+ // Sign the private funding
184
+ const signedPrivate = await signPsbt({lnd, psbt: fundPrivate.psbt});
185
+
186
+ // Fund the private channel
187
+ await fundPendingChannels({
188
+ lnd,
189
+ channels: openPrivate.pending.map(({id}) => id),
190
+ funding: signedPrivate.psbt,
191
+ });
192
+
193
+ // Generate the channel into a block
194
+ await broadcastChainTransaction({
195
+ lnd,
196
+ transaction: signedPrivate.transaction,
197
+ });
198
+
199
+ const privateConfirmed = await asyncRetry({interval, times}, async () => {
200
+ await generate({});
201
+
202
+ const [confirmed] = (await getChannels({lnd})).channels;
203
+
204
+ const shut = await getClosedChannels({lnd});
205
+
206
+ if (!shut.channels.length) {
207
+ throw new Error('ExpectedClosedChannel');
208
+ }
209
+
210
+ if (!confirmed.other_ids.length) {
211
+ throw new Error('ExpectedChangeToRealPrivateChannelId');
212
+ }
213
+
214
+ return confirmed;
215
+ });
216
+
217
+ equal(privateConfirmed.other_ids.length, 1, 'Got private ephemeral ids');
218
+
219
+ const [privateOtherId] = privateConfirmed.other_ids;
220
+
221
+ match(privateOtherId, /16000000x0/, 'Got private id');
222
+
223
+ const [closedChannel] = (await getClosedChannels({lnd})).channels;
224
+
225
+ equal(closedChannel.id, confirmed.id, 'Closed channel shows confirmed id');
226
+ strictSame(closedChannel.other_ids, confirmed.other_ids, 'Saved temp id');
227
+
228
+ const [closeEvent] = closings;
229
+
230
+ equal(closeEvent.id, confirmed.id, 'Closed event shows confirmed id');
231
+ strictSame(closeEvent.other_ids, confirmed.other_ids, 'Got temporary id');
232
+
233
+ const ephemeralIds = await getEphemeralChannelIds({lnd});
234
+
235
+ equal(ephemeralIds.channels.length, 2, 'Got ephemeral channel ids');
236
+
237
+ const [firstChannel, secondChannel] = ephemeralIds.channels;
238
+
239
+ match(firstChannel.reference_id, /16000000x0/, 'Got first channel id');
240
+ match(secondChannel.reference_id, /16000000x0/, 'Got second channel id');
241
+ } catch (err) {
242
+ equal(err, null, 'No error is reported');
243
+ } finally {
244
+ return await kill({});
245
+ }
246
+
247
+ return end();
248
+ });
@@ -26,9 +26,9 @@ const channelCapacityTokens = 1e6;
26
26
  const confirmationCount = 6;
27
27
  const defaultFee = 1e3;
28
28
  const give = 1e5;
29
- const interval = 200;
29
+ const interval = 50;
30
30
  const size = 2;
31
- const times = 1000;
31
+ const times = 10000;
32
32
  const tokens = 100;
33
33
 
34
34
  // Force close a channel and get the resulting sweep transaction
@@ -76,8 +76,15 @@ test(`Get sweep transactions`, async ({end, equal}) => {
76
76
  .map(n => n.tokens).sort();
77
77
 
78
78
  equal(transactions.length, 2, 'Got closed channel sweep');
79
- equal(anchorTokens, 149, 'Sweep has tokens amount');
80
- equal(sweepTokens, 890455, 'Sweep has tokens amount');
79
+
80
+ // LND 0.15.0 and before have different sweep tokens
81
+ if (sweepTokens === 890455) {
82
+ equal(anchorTokens, 149, 'Sweep has tokens amount');
83
+ equal(sweepTokens, 890455, 'Sweep has tokens amount');
84
+ } else {
85
+ equal(anchorTokens, 136, 'Sweep has tokens amount');
86
+ equal(sweepTokens, 889855, 'Sweep has tokens amount');
87
+ }
81
88
  } else {
82
89
  equal(transactions.length, [channel].length, 'Got closed channel sweep');
83
90
  equal(transaction.spends.length, 1, 'Sweep has spends');
@@ -1,7 +1,10 @@
1
+ const asyncRetry = require('async/retry');
1
2
  const {spawnLightningCluster} = require('ln-docker-daemons');
2
3
  const {test} = require('@alexbosworth/tap');
3
4
 
4
5
  const {createInvoice} = require('./../../');
6
+ const {getChannelBalance} = require('./../../');
7
+ const {getChannels} = require('./../../');
5
8
  const {getInvoice} = require('./../../');
6
9
  const {getRouteToDestination} = require('./../../');
7
10
  const {parsePaymentRequest} = require('./../../');
@@ -13,8 +16,11 @@ const {waitForRoute} = require('./../macros');
13
16
  const all = promise => Promise.all(promise);
14
17
  const capacity = 1e6;
15
18
  const {ceil} = Math;
19
+ const interval = 10;
20
+ const maturity = 100;
16
21
  const {round} = Math;
17
22
  const size = 2;
23
+ const times = 2000;
18
24
 
19
25
  // Paying using multiple paths should execute the payment across paths
20
26
  test(`Pay with multiple paths`, async ({end, equal, rejects, strictSame}) => {
@@ -22,22 +28,50 @@ test(`Pay with multiple paths`, async ({end, equal, rejects, strictSame}) => {
22
28
 
23
29
  const [{generate, lnd}, target] = nodes;
24
30
 
25
- await generate({count: 400});
31
+ await generate({count: maturity});
26
32
 
27
33
  const channel1 = await setupChannel({
28
34
  capacity,
29
35
  generate,
30
36
  lnd,
37
+ hidden: true,
31
38
  to: target,
32
39
  });
33
40
 
41
+ await asyncRetry({interval, times}, async () => {
42
+ const {channels} = await getChannels({lnd});
43
+
44
+ await generate({});
45
+
46
+ if (!channels.length) {
47
+ throw new Error('ExpectedChannelCreated');
48
+ }
49
+ });
50
+
34
51
  const channel2 = await setupChannel({
35
52
  capacity,
36
53
  generate,
37
54
  lnd,
55
+ hidden: true,
38
56
  to: target,
39
57
  });
40
58
 
59
+ await asyncRetry({interval, times}, async () => {
60
+ const {channels} = await getChannels({lnd, is_active: true});
61
+
62
+ await generate({});
63
+
64
+ if (channels.length < size) {
65
+ throw new Error('ExpectedSecondChannelCreated');
66
+ }
67
+
68
+ const balance = await getChannelBalance({lnd});
69
+
70
+ if (balance.channel_balance < capacity) {
71
+ throw new Error('ExpectedChannelBalancePresent');
72
+ }
73
+ });
74
+
41
75
  const channels = [channel1, channel2];
42
76
 
43
77
  const payParts = [
@@ -50,15 +84,23 @@ test(`Pay with multiple paths`, async ({end, equal, rejects, strictSame}) => {
50
84
  const {request} = await createInvoice({tokens, lnd: target.lnd});
51
85
 
52
86
  // Payment should fail with only 1 path
53
- try {
54
- await payViaPaymentRequest({lnd, request, max_paths: [channel1].length});
55
- } catch (err) {
56
- strictSame(
57
- err,
58
- [503, 'PaymentPathfindingFailedToFindPossibleRoute'],
59
- 'No path'
60
- );
61
- }
87
+ await asyncRetry({interval, times}, async () => {
88
+ try {
89
+ await payViaPaymentRequest({lnd, request, max_paths: [channel1].length});
90
+ } catch (err) {
91
+ const [, message] = err;
92
+
93
+ if (message !== 'PaymentPathfindingFailedToFindPossibleRoute') {
94
+ throw err;
95
+ }
96
+
97
+ strictSame(
98
+ err,
99
+ [503, 'PaymentPathfindingFailedToFindPossibleRoute'],
100
+ 'No path'
101
+ );
102
+ }
103
+ });
62
104
 
63
105
  // Payment should succeed with 2 paths
64
106
  try {
@@ -75,10 +75,15 @@ test(`Subscribe to requests`, async ({end, equal, rejects, strictSame}) => {
75
75
 
76
76
  await once(pay, 'failed');
77
77
 
78
+ equal(failures.length, 1, 'Got a failure');
79
+
80
+ const [failed] = failures;
81
+
82
+ delete failed.channel;
83
+
78
84
  strictSame(
79
- failures,
80
- [{
81
- channel: channel.id,
85
+ failed,
86
+ {
82
87
  index: 1,
83
88
  mtokens: '101000',
84
89
  public_key: target.id,
@@ -114,7 +119,7 @@ test(`Subscribe to requests`, async ({end, equal, rejects, strictSame}) => {
114
119
  tokens: 101,
115
120
  total_mtokens: '100000',
116
121
  },
117
- }],
122
+ },
118
123
  'Failure is emitted'
119
124
  );
120
125
 
@@ -135,10 +140,13 @@ test(`Subscribe to requests`, async ({end, equal, rejects, strictSame}) => {
135
140
  equal(!!pending.created_at, true, 'Has creation date');
136
141
  equal(pending.id, invoice.id, 'Payment id is present');
137
142
  equal(pending.mtokens, invoice.mtokens, 'Pending payment mtokens');
143
+ equal(pending.paths.length, 1, 'Path is present');
144
+
145
+ const [path] = pending.paths;
138
146
 
139
147
  strictSame(
140
- pending.paths,
141
- [{
148
+ path,
149
+ {
142
150
  fee: 1,
143
151
  fee_mtokens: '1000',
144
152
  hops: [
@@ -168,7 +176,7 @@ test(`Subscribe to requests`, async ({end, equal, rejects, strictSame}) => {
168
176
  timeout: height + 40 + 43,
169
177
  tokens: 101,
170
178
  total_mtokens: '100000',
171
- }],
179
+ },
172
180
  'Paths are present'
173
181
  );
174
182
 
@@ -51,6 +51,23 @@ test(`Sign bytes`, async ({end, equal}) => {
51
51
  equal(message, 'ExpectedSignerRpcLndBuildTagToSignBytes', 'Invalid LND');
52
52
  }
53
53
 
54
+ try {
55
+ const schnorr = await signBytes({
56
+ lnd,
57
+ key_family: 6,
58
+ key_index: 0,
59
+ preimage: Buffer.alloc(32).toString('hex'),
60
+ type: 'schnorr',
61
+ });
62
+
63
+ equal(schnorr.signature.length, 64 * 2, 'Got schnorr signature for bytes');
64
+ } catch (err) {
65
+ const [code, message] = Array.isArray(err) ? err : [];
66
+
67
+ equal(code, 503, 'A 503 code is thrown if schnorr is unsupported');
68
+ equal(message, 'UnexpectedSignatureLengthInSignBytesResponse', 'Sig len');
69
+ }
70
+
54
71
  await kill({});
55
72
 
56
73
  return end();
@@ -72,6 +72,30 @@ test(`Verify bytes signature`, async ({end, equal}) => {
72
72
  equal(message, 'ExpectedSignerRpcLndBuildTagToSignBytes', 'Invalid LND');
73
73
  }
74
74
 
75
+ try {
76
+ const schnorr = await signBytes({
77
+ lnd,
78
+ key_family: 6,
79
+ key_index: 0,
80
+ preimage: Buffer.alloc(32).toString('hex'),
81
+ type: 'schnorr',
82
+ });
83
+
84
+ const validity = await verifyBytesSignature({
85
+ lnd,
86
+ preimage: Buffer.alloc(32).toString('hex'),
87
+ public_key: id.slice(2),
88
+ signature: schnorr.signature,
89
+ });
90
+
91
+ equal(validity.is_valid, true, 'Schnorr signature is valid');
92
+ } catch (err) {
93
+ const [code, message] = Array.isArray(err) ? err : [];
94
+
95
+ equal(code, 503, 'A 503 code is thrown if schnorr is unsupported');
96
+ equal(message, 'UnexpectedSignatureLengthInSignBytesResponse', 'Sig len');
97
+ }
98
+
75
99
  await kill({});
76
100
 
77
101
  return end();
@@ -10,7 +10,6 @@ const {broadcastChainTransaction} = require('./../../');
10
10
  const {createChainAddress} = require('./../../');
11
11
  const {fundPsbt} = require('./../../');
12
12
  const {getChainBalance} = require('./../../');
13
- const {getChainTransactions} = require('./../../');
14
13
  const {getUtxos} = require('./../../');
15
14
  const {sendToChainAddress} = require('./../../');
16
15
  const {signPsbt} = require('./../../');