lightning 5.15.0 → 5.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +14 -0
  3. package/grpc/protos/lightning.proto +19 -3
  4. package/grpc/protos/signer.proto +47 -9
  5. package/lnd_methods/info/get_route_to_destination.js +8 -0
  6. package/lnd_methods/offchain/get_failed_payments.js +3 -1
  7. package/lnd_methods/offchain/get_payments.js +3 -1
  8. package/lnd_methods/offchain/get_pending_payments.js +2 -0
  9. package/lnd_methods/peers/add_external_socket.d.ts +20 -0
  10. package/lnd_methods/peers/index.d.ts +4 -0
  11. package/lnd_methods/peers/remove_external_socket.d.ts +20 -0
  12. package/lnd_methods/peers/update_alias.d.ts +11 -0
  13. package/lnd_methods/peers/update_color.d.ts +11 -0
  14. package/lnd_methods/signer/begin_group_signing_session.d.ts +33 -0
  15. package/lnd_methods/signer/end_group_signing_session.d.ts +21 -0
  16. package/lnd_methods/signer/index.d.ts +3 -0
  17. package/lnd_methods/signer/input_signing_method.js +42 -0
  18. package/lnd_methods/signer/sign_transaction.js +26 -20
  19. package/lnd_methods/signer/update_group_signing_session.d.ts +23 -0
  20. package/lnd_responses/rpc_attempt_htlc_as_attempt.js +39 -5
  21. package/lnd_responses/rpc_payment_as_payment.js +6 -0
  22. package/package.json +2 -2
  23. package/test/lnd_methods/info/test_get_route_to_destination.js +15 -0
  24. package/test/lnd_methods/offchain/test_get_payments.js +2 -0
  25. package/test/lnd_methods/signer/test_input_signing_method.js +53 -0
  26. package/test/lnd_responses/test_rpc_attempt_htlc_as_attempt.js +19 -3
  27. package/test/lnd_responses/test_rpc_payment_as_payment.js +5 -1
  28. package/test/typescript/add_external_socket.test-d.ts +14 -0
  29. package/test/typescript/begin_group_signing_session.test-d.ts +60 -0
  30. package/test/typescript/end_group_signing_session.test-d.ts +32 -0
  31. package/test/typescript/remove_external_socket.test-d.ts +14 -0
  32. package/test/typescript/update_alias.test-d.ts +14 -0
  33. package/test/typescript/update_color.test-d.ts +14 -0
  34. package/test/typescript/update_group_signing_session.test-d.ts +29 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Versions
2
2
 
3
+ ## 5.16.0
4
+
5
+ - `signTransaction`: Add `root_hash` to support Taproot signatures with scripts
6
+
7
+ ## 5.15.2
8
+
9
+ - `getFailedPayments`, `getPayments`, `getPendingPayments`: Remove
10
+ `confirmed_at` date when a payment is not confirmed, add `created_at` and
11
+ `failed_at` dates for attempt start and attempt failed dates.
12
+
3
13
  ## 5.15.0
4
14
 
5
15
  - `beginGroupSigningSession`: Add method to start a MuSig2 signing session
package/README.md CHANGED
@@ -66,9 +66,13 @@ To access unauthenticated methods like the wallet unlocker, use
66
66
 
67
67
  ## Methods
68
68
 
69
+ - [addExternalSocket](https://github.com/alexbosworth/ln-service#addexternalsocket):
70
+ Add a new LN p2p network socket to node advertisement
69
71
  - [addPeer](https://github.com/alexbosworth/ln-service#addpeer): Connect to a new peer
70
72
  - [authenticatedLndGrpc](https://github.com/alexbosworth/ln-service#authenticatedlndgrpc):
71
73
  Instantiate connection to authenticated lnd methods.
74
+ - [beginGroupSigningSession](https://github.com/alexbosworth/ln-service#begingroupsigningsession):
75
+ Start a new MuSig2 signing session
72
76
  - [broadcastChainTransaction](https://github.com/alexbosworth/ln-service#broadcastchaintransaction):
73
77
  Publish an on-chain transaction to the network.
74
78
  - [cancelHodlInvoice](https://github.com/alexbosworth/ln-service#cancelhodlinvoice): Cancel an
@@ -111,6 +115,8 @@ To access unauthenticated methods like the wallet unlocker, use
111
115
  Remove a connected watchtower
112
116
  - [enableChannel](https://github.com/alexbosworth/ln-service#enablechannel): Signal forwarding
113
117
  enabled towards a peer.
118
+ - [endGroupSigningSession](https://github.com/alexbosworth/ln-service#endgroupsigningsession):
119
+ End a MuSig2 signing session
114
120
  - [fundPendingChannels](https://github.com/alexbosworth/ln-service#fundpendingchannels):
115
121
  Provide a signed funding source for opening channels.
116
122
  - [fundPsbt](https://github.com/alexbosworth/ln-service#fundpsbt): Make a PSBT with funds and
@@ -235,6 +241,8 @@ To access unauthenticated methods like the wallet unlocker, use
235
241
  Attempt to recover channel funds from a specific channel backup.
236
242
  - [recoverFundsFromChannels](https://github.com/alexbosworth/ln-service#recoverfundsfromchannels):
237
243
  Attempt to recover funds from multiple channels using a multiple channel backup.
244
+ - [removeExternalSocket](https://github.com/alexbosworth/ln-service#removeexternalsocket):
245
+ Remove a LN p2p network socket from the node advertisement
238
246
  - [removePeer](https://github.com/alexbosworth/ln-service#removepeer): Disconnect from a
239
247
  connected peer.
240
248
  - [requestChainFeeIncrease](https://github.com/alexbosworth/ln-service#requestchainfeeincrease):
@@ -313,10 +321,16 @@ To access unauthenticated methods like the wallet unlocker, use
313
321
  UTXO to allow it to be selected for spending again.
314
322
  - [unlockWallet](https://github.com/alexbosworth/ln-service#unlockwallet): Decrypt the wallet and
315
323
  start the daemon
324
+ - [updateAlias](https://github.com/alexbosworth/ln-service#updatealias):
325
+ Update the advertised node alias
316
326
  - [updateChainTransaction](https://github.com/alexbosworth/ln-service#updatechaintransaction):
317
327
  Edit the metadata of an on-chain transaction record.
328
+ - [updateColor](https://github.com/alexbosworth/ln-service#updatecolor):
329
+ Update the advertised node color
318
330
  - [updateConnectedWatchtower](https://github.com/alexbosworth/ln-service#updateconnectedwatchtower):
319
331
  Edit the settings on an added watchtower
332
+ - [updateGroupSigningSession](https://github.com/alexbosworth/ln-service#updategroupsigningsession):
333
+ Update a MuSig2 signing session with nonces and get a partial signature
320
334
  - [updatePathfindingSettings](https://github.com/alexbosworth/ln-service#updatepathfindingsettings):
321
335
  Edit the configuration for routing calculations
322
336
  - [updateRoutingFees](https://github.com/alexbosworth/ln-service#updateroutingfees): Set the
@@ -2369,9 +2369,6 @@ message PendingChannelsResponse {
2369
2369
  // The pending channel
2370
2370
  PendingChannel channel = 1;
2371
2371
 
2372
- // The height at which this channel will be confirmed
2373
- uint32 confirmation_height = 2;
2374
-
2375
2372
  /*
2376
2373
  The amount calculated to be paid in fees for the current set of
2377
2374
  commitment transactions. The fee amount is persisted with the channel
@@ -2390,6 +2387,9 @@ message PendingChannelsResponse {
2390
2387
  transaction. This value can later be updated once the channel is open.
2391
2388
  */
2392
2389
  int64 fee_per_kw = 6;
2390
+
2391
+ // Previously used for confirmation_height. Do not reuse.
2392
+ reserved 2;
2393
2393
  }
2394
2394
 
2395
2395
  message WaitingCloseChannel {
@@ -3633,6 +3633,14 @@ message ListPaymentsRequest {
3633
3633
  of the returned payments is always oldest first (ascending index order).
3634
3634
  */
3635
3635
  bool reversed = 4;
3636
+
3637
+ /*
3638
+ If set, all payments (complete and incomplete, independent of the
3639
+ max_payments parameter) will be counted. Note that setting this to true will
3640
+ increase the run time of the call significantly on systems that have a lot
3641
+ of payments, as all of them have to be iterated through to be counted.
3642
+ */
3643
+ bool count_total_payments = 5;
3636
3644
  }
3637
3645
 
3638
3646
  message ListPaymentsResponse {
@@ -3650,6 +3658,14 @@ message ListPaymentsResponse {
3650
3658
  as the index_offset to continue seeking forwards in the next request.
3651
3659
  */
3652
3660
  uint64 last_index_offset = 3;
3661
+
3662
+ /*
3663
+ Will only be set if count_total_payments in the request was set. Represents
3664
+ the total number of payments (complete and incomplete, independent of the
3665
+ number of payments requested in the query) currently present in the payments
3666
+ database.
3667
+ */
3668
+ uint64 total_num_payments = 4;
3653
3669
  }
3654
3670
 
3655
3671
  message DeletePaymentRequest {
@@ -137,6 +137,7 @@ service Signer {
137
137
  MuSig2Cleanup (experimental!) allows a caller to clean up a session early in
138
138
  cases where it's obvious that the signing session won't succeed and the
139
139
  resources can be released.
140
+
140
141
  NOTE: The MuSig2 BIP is not final yet and therefore this API must be
141
142
  considered to be HIGHLY EXPERIMENTAL and subject to change in upcoming
142
143
  releases. Backward compatibility is not guaranteed!
@@ -174,6 +175,32 @@ message TxOut {
174
175
  bytes pk_script = 2;
175
176
  }
176
177
 
178
+ enum SignMethod {
179
+ /*
180
+ Specifies that a SegWit v0 (p2wkh, np2wkh, p2wsh) input script should be
181
+ signed.
182
+ */
183
+ SIGN_METHOD_WITNESS_V0 = 0;
184
+
185
+ /*
186
+ Specifies that a SegWit v1 (p2tr) input should be signed by using the
187
+ BIP0086 method (commit to internal key only).
188
+ */
189
+ SIGN_METHOD_TAPROOT_KEY_SPEND_BIP0086 = 1;
190
+
191
+ /*
192
+ Specifies that a SegWit v1 (p2tr) input should be signed by using a given
193
+ taproot hash to commit to in addition to the internal key.
194
+ */
195
+ SIGN_METHOD_TAPROOT_KEY_SPEND = 2;
196
+
197
+ /*
198
+ Specifies that a SegWit v1 (p2tr) input should be spent using the script
199
+ path and that a specific leaf script should be signed for.
200
+ */
201
+ SIGN_METHOD_TAPROOT_SCRIPT_SPEND = 3;
202
+ }
203
+
177
204
  message SignDescriptor {
178
205
  /*
179
206
  A descriptor that precisely describes *which* key to use for signing. This
@@ -208,12 +235,23 @@ message SignDescriptor {
208
235
  */
209
236
  bytes double_tweak = 3;
210
237
 
238
+ /*
239
+ The 32 byte input to the taproot tweak derivation that is used to derive
240
+ the output key from an internal key: outputKey = internalKey +
241
+ tagged_hash("tapTweak", internalKey || tapTweak).
242
+
243
+ When doing a BIP 86 spend, this field can be an empty byte slice.
244
+
245
+ When doing a normal key path spend, with the output key committing to an
246
+ actual script root, then this field should be: the tapscript root hash.
247
+ */
248
+ bytes tap_tweak = 10;
249
+
211
250
  /*
212
251
  The full script required to properly redeem the output. This field will
213
- only be populated if a p2tr, p2wsh or a p2sh output is being signed. In case
214
- taproot_key_spend is set to true then this value must correspond to the
215
- taproot root hash (in case of a tapscript output) or the tap hashed internal
216
- public key (in case of a BIP-0086 output).
252
+ only be populated if a p2tr, p2wsh or a p2sh output is being signed. If a
253
+ taproot script path spend is being attempted, then this should be the raw
254
+ leaf script.
217
255
  */
218
256
  bytes witness_script = 4;
219
257
 
@@ -235,12 +273,12 @@ message SignDescriptor {
235
273
  int32 input_index = 8;
236
274
 
237
275
  /*
238
- Indicates that this should produce a signature that can be used for the key
239
- spend path of a taproot input. This requires the witness_script field to be
240
- set to the taproot root hash (in case of a tapscript output) or the tap
241
- hashed internal public key (in case of a BIP-0086 output).
276
+ The sign method specifies how the input should be signed. Depending on the
277
+ method, either the tap_tweak, witness_script or both need to be specified.
278
+ Defaults to SegWit v0 signing to be backward compatible with older RPC
279
+ clients.
242
280
  */
243
- bool taproot_key_spend = 9;
281
+ SignMethod sign_method = 9;
244
282
  }
245
283
 
246
284
  message SignReq {
@@ -129,6 +129,14 @@ module.exports = (args, cbk) => {
129
129
  return cbk([400, 'ExpectedLndApiObjectToGetRouteToDestination']);
130
130
  }
131
131
 
132
+ if (!!args.outgoing_channel) {
133
+ try {
134
+ chanNumber({channel: args.outgoing_channel});
135
+ } catch (err) {
136
+ return cbk([400, 'ExpectedStandardFormatChannelIdForOutChannel']);
137
+ }
138
+ }
139
+
132
140
  if (!!args.total_mtokens && !args.payment) {
133
141
  return cbk([400, 'ExpectedTotalMtokensWithPaymentIdentifier']);
134
142
  }
@@ -56,7 +56,9 @@ const type = 'default';
56
56
  message: <Error Message String>
57
57
  }
58
58
  [index]: <Payment Add Index Number>
59
- [confirmed_at]: <Payment Confirmed At ISO 8601 Date String>
59
+ [confirmed_at]: <Payment Attempt Succeeded At ISO 8601 Date String>
60
+ created_at: <Attempt Was Started At ISO 8601 Date String>
61
+ [failed_at]: <Payment Attempt Failed At ISO 8601 Date String>
60
62
  is_confirmed: <Payment Attempt Succeeded Bool>
61
63
  is_failed: <Payment Attempt Failed Bool>
62
64
  is_pending: <Payment Attempt is Waiting For Resolution Bool>
@@ -55,7 +55,9 @@ const type = 'default';
55
55
  message: <Error Message String>
56
56
  }
57
57
  [index]: <Payment Add Index Number>
58
- [confirmed_at]: <Payment Confirmed At ISO 8601 Date String>
58
+ [confirmed_at]: <Payment Attempt Succeeded At ISO 8601 Date String>
59
+ created_at: <Attempt Was Started At ISO 8601 Date String>
60
+ [failed_at]: <Payment Attempt Failed At ISO 8601 Date String>
59
61
  is_confirmed: <Payment Attempt Succeeded Bool>
60
62
  is_failed: <Payment Attempt Failed Bool>
61
63
  is_pending: <Payment Attempt is Waiting For Resolution Bool>
@@ -57,6 +57,8 @@ const type = 'default';
57
57
  }
58
58
  [index]: <Payment Add Index Number>
59
59
  [confirmed_at]: <Payment Confirmed At ISO 8601 Date String>
60
+ created_at: <Attempt Was Started At ISO 8601 Date String>
61
+ [failed_at]: <Payment Attempt Failed At ISO 8601 Date String>
60
62
  is_confirmed: <Payment Attempt Succeeded Bool>
61
63
  is_failed: <Payment Attempt Failed Bool>
62
64
  is_pending: <Payment Attempt is Waiting For Resolution Bool>
@@ -0,0 +1,20 @@
1
+ import {
2
+ AuthenticatedLightningArgs,
3
+ AuthenticatedLightningMethod,
4
+ } from '../../typescript/shared';
5
+
6
+ export type AddExternalSocketArgs = AuthenticatedLightningArgs<{
7
+ /** Add Socket Address String */
8
+ socket: string;
9
+ }>;
10
+
11
+ /**
12
+ * Add a new advertised p2p socket address
13
+ *
14
+ * Note: this method is not supported in LND versions 0.14.3 and below
15
+ *
16
+ * Requires LND built with `peersrpc` build tag
17
+ *
18
+ * Requires `peers:write` permissions
19
+ */
20
+ export const addExternalSocket: AuthenticatedLightningMethod<AddExternalSocketArgs>;
@@ -1,4 +1,8 @@
1
+ export * from './add_external_socket';
1
2
  export * from './add_peer';
2
3
  export * from './get_peers';
4
+ export * from './remove_external_socket';
3
5
  export * from './remove_peer';
4
6
  export * from './subscribe_to_peers';
7
+ export * from './update_alias';
8
+ export * from './update_color';
@@ -0,0 +1,20 @@
1
+ import {
2
+ AuthenticatedLightningArgs,
3
+ AuthenticatedLightningMethod,
4
+ } from '../../typescript/shared';
5
+
6
+ export type RemoveExternalSocketArgs = AuthenticatedLightningArgs<{
7
+ /** Remove Socket Address String */
8
+ socket: string;
9
+ }>;
10
+
11
+ /**
12
+ * Remove an existing advertised p2p socket address
13
+ *
14
+ * Note: this method is not supported in LND versions 0.14.3 and below
15
+ *
16
+ * Requires LND built with `peersrpc` build tag
17
+ *
18
+ * Requires `peers:write` permissions
19
+ */
20
+ export const removeExternalSocket: AuthenticatedLightningMethod<RemoveExternalSocketArgs>;
@@ -0,0 +1,11 @@
1
+ import {
2
+ AuthenticatedLightningArgs,
3
+ AuthenticatedLightningMethod,
4
+ } from '../../typescript/shared';
5
+
6
+ export type UpdateAliasArgs = AuthenticatedLightningArgs<{
7
+ /** Node Alias String */
8
+ node: string;
9
+ }>;
10
+
11
+ export const updateAlias: AuthenticatedLightningMethod<UpdateAliasArgs>;
@@ -0,0 +1,11 @@
1
+ import {
2
+ AuthenticatedLightningArgs,
3
+ AuthenticatedLightningMethod,
4
+ } from '../../typescript/shared';
5
+
6
+ export type UpdateColorArgs = AuthenticatedLightningArgs<{
7
+ /** Node Color String */
8
+ color: string;
9
+ }>;
10
+
11
+ export const updateColor: AuthenticatedLightningMethod<UpdateColorArgs>;
@@ -0,0 +1,33 @@
1
+ import {
2
+ AuthenticatedLightningArgs,
3
+ AuthenticatedLightningMethod,
4
+ } from '../../typescript/shared';
5
+
6
+ export type BeginGroupSigningSessionArgs = AuthenticatedLightningArgs<{
7
+ /** Key Is BIP 86 Key Spend Key Bool */
8
+ is_key_spend?: boolean;
9
+ /** HD Seed Key Family Number */
10
+ key_family: number;
11
+ /** Key Index Number */
12
+ key_index: number;
13
+ /** External Public Key Hex String */
14
+ public_keys: string[];
15
+ /** Taproot Script Root Hash Hex String */
16
+ root_hash?: string;
17
+ }>;
18
+
19
+ export type BeginGroupSigningSessionResult = {
20
+ /** Final Script or Top Level Public Key Hex String */
21
+ external_key: string;
22
+ /** Session Id Hex String */
23
+ id: string;
24
+ /** Internal Top Level Public Key Hex String */
25
+ internal_key?: string;
26
+ /** Session Compound Nonces Hex String */
27
+ nonce: string;
28
+ };
29
+
30
+ export const beginGroupSigningSession: AuthenticatedLightningMethod<
31
+ BeginGroupSigningSessionArgs,
32
+ BeginGroupSigningSessionResult
33
+ >;
@@ -0,0 +1,21 @@
1
+ import {
2
+ AuthenticatedLightningArgs,
3
+ AuthenticatedLightningMethod,
4
+ } from '../../typescript/shared';
5
+
6
+ export type EndGroupSigningSessionArgs = AuthenticatedLightningArgs<{
7
+ /** Session Id Hex String */
8
+ id: string;
9
+ /** Combine External Partial Signature Hex Strings */
10
+ signatures?: string[];
11
+ }>;
12
+
13
+ export type EndGroupSigningSessionResult = {
14
+ /** Combined Signature Hex String */
15
+ signature?: string;
16
+ };
17
+
18
+ export const endGroupSigningSession: AuthenticatedLightningMethod<
19
+ EndGroupSigningSessionArgs,
20
+ EndGroupSigningSessionResult
21
+ >;
@@ -1,4 +1,7 @@
1
+ export * from './begin_group_signing_session';
1
2
  export * from './diffie_hellman_compute_secret';
3
+ export * from './end_group_signing_session';
2
4
  export * from './sign_bytes';
3
5
  export * from './sign_transaction';
6
+ export * from './update_group_signing_session';
4
7
  export * from './verify_bytes_signature';
@@ -0,0 +1,42 @@
1
+ const v0SpendMethod = 0;
2
+ const v1Bip86Method = 1;
3
+ const v1SpendMethod = 2;
4
+ const v1ScriptSpend = 3;
5
+
6
+ /** Determine a signing method for an input
7
+
8
+ {
9
+ input: [{
10
+ [root_hash]: <Taproot Root Hash Hex String>
11
+ [witness_script]: <Witness Script Hex String>
12
+ }]
13
+ [outputs]: [{
14
+ pk_script: <UTXO Output Script Buffer Object>
15
+ value: <UTXO Tokens Number>
16
+ }]
17
+ }
18
+
19
+ @returns
20
+ {
21
+ method: <Signing Method Number>
22
+ }
23
+ */
24
+ module.exports = ({input, outputs}, cbk) => {
25
+ // Exit early when lack of previous outputs indicates a v0 spend
26
+ if (!outputs) {
27
+ return {method: v0SpendMethod};
28
+ }
29
+
30
+ // Exit early when no leaf script or script commitment is present
31
+ if (!input.root_hash && !input.witness_script) {
32
+ return {method: v1Bip86Method};
33
+ }
34
+
35
+ // Exit early when there is no leaf script, just a top level key spend
36
+ if (!input.witness_script) {
37
+ return {method: v1SpendMethod};
38
+ }
39
+
40
+ // Sign for a leaf script for a key that commits to the scripts root hash
41
+ return {method: v1ScriptSpend};
42
+ };
@@ -1,10 +1,11 @@
1
1
  const asyncAuto = require('async/auto');
2
2
  const {returnResult} = require('asyncjs-util');
3
3
 
4
+ const inputSigningMethod = require('./input_signing_method');
4
5
  const {isLnd} = require('./../../lnd_requests');
5
6
 
6
7
  const bufferAsHex = buffer => buffer.toString('hex');
7
- const hexAsBuffer = hex => Buffer.from(hex, 'hex');
8
+ const hexAsBuffer = hex => Buffer.from(hex || '', 'hex');
8
9
  const {isArray} = Array;
9
10
  const isV1 = scriptHex => scriptHex.length === 68 && /5120/.test(scriptHex);
10
11
  const method = 'signOutputRaw';
@@ -28,9 +29,10 @@ const unimplementedError = '12 UNIMPLEMENTED: unknown service signrpc.Signer';
28
29
  key_index: <Key Index Number>
29
30
  output_script: <Output Script Hex String>
30
31
  output_tokens: <Output Tokens Number>
32
+ [root_hash]: <Taproot Root Hash Hex String>
31
33
  sighash: <Sighash Type Number>
32
34
  vin: <Input Index To Sign Number>
33
- witness_script: <Witness Script Hex String>
35
+ [witness_script]: <Witness Script Hex String>
34
36
  }]
35
37
  lnd: <Authenticated LND API Object>
36
38
  [spending]: [{
@@ -65,8 +67,8 @@ module.exports = ({inputs, lnd, spending, transaction}, cbk) => {
65
67
  return cbk();
66
68
  },
67
69
 
68
- // Derive the previous outputs set
69
- previousOutputs: ['validate', ({}, cbk) => {
70
+ // Derive the previous outputs set for Taproot spends
71
+ outputs: ['validate', ({}, cbk) => {
70
72
  const outputs = [].concat(inputs).concat(spending || []).map(utxo => ({
71
73
  pk_script: hexAsBuffer(utxo.output_script),
72
74
  value: utxo.output_tokens,
@@ -83,25 +85,29 @@ module.exports = ({inputs, lnd, spending, transaction}, cbk) => {
83
85
  }],
84
86
 
85
87
  // Get signatures
86
- signTransaction: ['previousOutputs', ({previousOutputs}, cbk) => {
88
+ signTransaction: ['outputs', ({outputs}, cbk) => {
87
89
  return lnd[type][method]({
88
- prev_outputs: previousOutputs,
90
+ prev_outputs: outputs,
89
91
  raw_tx_bytes: hexAsBuffer(transaction),
90
- sign_descs: inputs.map(input => ({
91
- input_index: input.vin,
92
- key_desc: {
93
- key_loc: {
94
- key_family: input.key_family,
95
- key_index: input.key_index,
92
+ sign_descs: inputs.map(input => {
93
+ return {
94
+ input_index: input.vin,
95
+ key_desc: {
96
+ key_loc: {
97
+ key_family: input.key_family,
98
+ key_index: input.key_index,
99
+ },
96
100
  },
97
- },
98
- output: {
99
- pk_script: hexAsBuffer(input.output_script),
100
- value: input.output_tokens,
101
- },
102
- sighash: input.sighash,
103
- witness_script: hexAsBuffer(input.witness_script),
104
- })),
101
+ output: {
102
+ pk_script: hexAsBuffer(input.output_script),
103
+ value: input.output_tokens,
104
+ },
105
+ sighash: input.sighash,
106
+ sign_method: inputSigningMethod({input, outputs}).method,
107
+ tap_tweak: hexAsBuffer(input.root_hash),
108
+ witness_script: hexAsBuffer(input.witness_script),
109
+ };
110
+ }),
105
111
  },
106
112
  (err, res) => {
107
113
  if (!!err && err.message === unimplementedError) {
@@ -0,0 +1,23 @@
1
+ import {
2
+ AuthenticatedLightningArgs,
3
+ AuthenticatedLightningMethod,
4
+ } from '../../typescript/shared';
5
+
6
+ export type UpdateGroupSigningSessionArgs = AuthenticatedLightningArgs<{
7
+ /** Hash to Sign Hex String */
8
+ hash: string;
9
+ /** MuSig2 Session Id Hex String */
10
+ id: string;
11
+ /** Nonce Hex Strings */
12
+ nonces: string[];
13
+ }>;
14
+
15
+ export type UpdateGroupSigningSessionResult = {
16
+ /** Partial Signature Hex String */
17
+ signature: string;
18
+ };
19
+
20
+ export const updateGroupSigningSession: AuthenticatedLightningMethod<
21
+ UpdateGroupSigningSessionArgs,
22
+ UpdateGroupSigningSessionResult
23
+ >;
@@ -61,7 +61,9 @@ const nsAsMs = ns => Number(BigInt(ns) / BigInt(1e6));
61
61
 
62
62
  @returns
63
63
  {
64
- confirmed_at: <Payment Succeeded At ISO 8601 Date String>
64
+ [confirmed_at]: <Payment Attempt Succeeded At ISO 8601 Date String>
65
+ created_at: <Attempt Was Started At ISO 8601 Date String>
66
+ [failed_at]: <Payment Attempt Failed At ISO 8601 Date String>
65
67
  is_confirmed: <Payment Attempt Succeeded Bool>
66
68
  is_failed: <Payment Attempt Failed Bool>
67
69
  is_pending: <Payment Attempt is Waiting For Resolution Bool>
@@ -91,6 +93,10 @@ module.exports = attempt => {
91
93
  throw new Error('ExpectedRpcAttemptDetailsToDeriveAttempt');
92
94
  }
93
95
 
96
+ if (!attempt.attempt_time_ns) {
97
+ throw new Error('ExpectedRpcAttemptStartTimeNs');
98
+ }
99
+
94
100
  if (!attempt.resolve_time_ns) {
95
101
  throw new Error('ExpectedRpcAttemptResolveTimeNs');
96
102
  }
@@ -103,11 +109,39 @@ module.exports = attempt => {
103
109
  throw new Error('ExpectedAttemptStatusInRpcAttemptDetails');
104
110
  }
105
111
 
112
+ const route = rpcRouteAsRoute(attempt.route);
113
+
114
+ if (attempt.status === attemptStates.confirmed) {
115
+ return {
116
+ route,
117
+ confirmed_at: new Date(nsAsMs(attempt.resolve_time_ns)).toISOString(),
118
+ created_at: new Date(nsAsMs(attempt.attempt_time_ns)).toISOString(),
119
+ failed_at: undefined,
120
+ is_confirmed: true,
121
+ is_failed: false,
122
+ is_pending: false,
123
+ };
124
+ }
125
+
126
+ if (attempt.status === attemptStates.failed) {
127
+ return {
128
+ route,
129
+ confirmed_at: undefined,
130
+ created_at: new Date(nsAsMs(attempt.attempt_time_ns)).toISOString(),
131
+ failed_at: new Date(nsAsMs(attempt.resolve_time_ns)).toISOString(),
132
+ is_confirmed: false,
133
+ is_failed: true,
134
+ is_pending: false,
135
+ };
136
+ }
137
+
106
138
  return {
107
- confirmed_at: new Date(nsAsMs(attempt.resolve_time_ns)).toISOString(),
108
- is_confirmed: attempt.status === attemptStates.confirmed,
109
- is_failed: attempt.status === attemptStates.failed,
139
+ route,
140
+ confirmed_at: undefined,
141
+ created_at: new Date(nsAsMs(attempt.attempt_time_ns)).toISOString(),
142
+ failed_at: undefined,
143
+ is_confirmed: false,
144
+ is_failed: false,
110
145
  is_pending: attempt.status === attemptStates.pending,
111
- route: rpcRouteAsRoute(attempt.route),
112
146
  };
113
147
  };
@@ -81,6 +81,9 @@ const routePublicKeys = route => route.hops.map(n => n.public_key);
81
81
  @returns
82
82
  {
83
83
  attempts: [{
84
+ [confirmed_at]: <Payment Attempt Succeeded At ISO 8601 Date String>
85
+ created_at: <Attempt Was Started At ISO 8601 Date String>
86
+ [failed_at]: <Payment Attempt Failed At ISO 8601 Date String>
84
87
  [failure]: {
85
88
  code: <Error Type Code Number>
86
89
  [details]: {
@@ -108,6 +111,9 @@ const routePublicKeys = route => route.hops.map(n => n.public_key);
108
111
  }
109
112
  message: <Error Message String>
110
113
  }
114
+ [confirmed_at]: <Payment Attempt Succeeded At ISO 8601 Date String>
115
+ created_at: <Attempt Was Started At ISO 8601 Date String>
116
+ [failed_at]: <Payment Attempt Failed At ISO 8601 Date String>
111
117
  is_confirmed: <Payment Attempt Succeeded Bool>
112
118
  is_failed: <Payment Attempt Failed Bool>
113
119
  is_pending: <Payment Attempt is Waiting For Resolution Bool>
package/package.json CHANGED
@@ -10,7 +10,7 @@
10
10
  "@grpc/grpc-js": "1.6.7",
11
11
  "@grpc/proto-loader": "0.6.12",
12
12
  "@types/express": "4.17.13",
13
- "@types/node": "17.0.31",
13
+ "@types/node": "17.0.33",
14
14
  "@types/request": "2.48.8",
15
15
  "@types/ws": "8.5.3",
16
16
  "async": "3.2.3",
@@ -59,5 +59,5 @@
59
59
  "directory": "test/typescript"
60
60
  },
61
61
  "types": "index.d.ts",
62
- "version": "5.15.0"
62
+ "version": "5.16.0"
63
63
  }
@@ -70,6 +70,11 @@ const makeArgs = override => {
70
70
  };
71
71
 
72
72
  const tests = [
73
+ {
74
+ args: makeArgs({confidence: NaN}),
75
+ description: 'Valid confidence is required',
76
+ error: [400, 'ExpectedConfidenceInPartsPerMillionForQuery'],
77
+ },
73
78
  {
74
79
  args: makeArgs({destination: undefined}),
75
80
  description: 'A destination is required',
@@ -85,6 +90,11 @@ const tests = [
85
90
  description: 'LND is required',
86
91
  error: [400, 'ExpectedLndApiObjectToGetRouteToDestination'],
87
92
  },
93
+ {
94
+ args: makeArgs({outgoing_channel: 12345}),
95
+ description: 'Outgoing channel is expected in standard format',
96
+ error: [400, 'ExpectedStandardFormatChannelIdForOutChannel'],
97
+ },
88
98
  {
89
99
  args: makeArgs({payment: undefined}),
90
100
  description: 'Total mtokens requires linking payment identifier',
@@ -132,6 +142,11 @@ const tests = [
132
142
  description: 'No route is found with error',
133
143
  expected: {},
134
144
  },
145
+ {
146
+ args: makeArgs({lnd: makeLnd({err: {details: 'is too large'}})}),
147
+ description: 'Payment cannot exceed maximum size',
148
+ error: [400, 'PaymentTooLargeToFindRoute'],
149
+ },
135
150
  {
136
151
  args: makeArgs({lnd: makeLnd({res: {routes: []}})}),
137
152
  description: 'No route is found',
@@ -65,6 +65,8 @@ const makeExpectedPayment = ({}) => {
65
65
  destination: '020202020202020202020202020202020202020202020202020202020202020202',
66
66
  attempts: [{
67
67
  confirmed_at: '1970-01-01T00:00:00.000Z',
68
+ created_at: '1970-01-01T00:00:00.000Z',
69
+ failed_at: undefined,
68
70
  is_confirmed: true,
69
71
  is_failed: false,
70
72
  is_pending: false,
@@ -0,0 +1,53 @@
1
+ const {test} = require('@alexbosworth/tap');
2
+
3
+ const method = require('./../../../lnd_methods/signer/input_signing_method');
4
+
5
+ const makeArgs = override => {
6
+ const args = {
7
+ input: {
8
+ root_hash: '00',
9
+ witness_script: '00',
10
+ },
11
+ outputs: [{
12
+ pk_script: Buffer.alloc(1),
13
+ value: 1,
14
+ }],
15
+ };
16
+
17
+ Object.keys(override || {}).forEach(key => args[key] = override[key]);
18
+
19
+ return args;
20
+ };
21
+
22
+ const tests = [
23
+ {
24
+ args: makeArgs({}),
25
+ description: 'Input signing method is returned for a leaf spend',
26
+ expected: {method: 3},
27
+ },
28
+ {
29
+ args: makeArgs({input: {}, outputs: undefined}),
30
+ description: 'Input signing method is returned for a regular spend',
31
+ expected: {method: 0},
32
+ },
33
+ {
34
+ args: makeArgs({input: {}}),
35
+ description: 'Input signing method is returned for a bip86 spend',
36
+ expected: {method: 1},
37
+ },
38
+ {
39
+ args: makeArgs({input: {root_hash: '00'}}),
40
+ description: 'Input signing method is returned for a top key script spend',
41
+ expected: {method: 2},
42
+ },
43
+ ];
44
+
45
+ tests.forEach(({args, description, expected}) => {
46
+ return test(description, async ({end, strictSame}) => {
47
+ const res = method(args);
48
+
49
+ strictSame(res, expected, 'Got expected result');
50
+
51
+ return end();
52
+ });
53
+ });
@@ -19,7 +19,12 @@ const route = {
19
19
  };
20
20
 
21
21
  const makeArgs = overrides => {
22
- const args = {route, resolve_time_ns: '1', status: 'IN_FLIGHT'};
22
+ const args = {
23
+ route,
24
+ attempt_time_ns: '1',
25
+ resolve_time_ns: '1',
26
+ status: 'IN_FLIGHT',
27
+ };
23
28
 
24
29
  Object.keys(overrides).forEach(k => args[k] = overrides[k]);
25
30
 
@@ -29,6 +34,8 @@ const makeArgs = overrides => {
29
34
  const makeExpected = overrides => {
30
35
  const attempt = {
31
36
  confirmed_at: '1970-01-01T00:00:00.000Z',
37
+ created_at: '1970-01-01T00:00:00.000Z',
38
+ failed_at: undefined,
32
39
  is_confirmed: false,
33
40
  is_failed: false,
34
41
  is_pending: false,
@@ -64,6 +71,11 @@ const tests = [
64
71
  description: 'An rpc attempt is required to map to an attempt',
65
72
  error: 'ExpectedRpcAttemptDetailsToDeriveAttempt',
66
73
  },
74
+ {
75
+ args: makeArgs({attempt_time_ns: undefined}),
76
+ description: 'Expected attempt time in rpc attempt details',
77
+ error: 'ExpectedRpcAttemptStartTimeNs',
78
+ },
67
79
  {
68
80
  args: makeArgs({resolve_time_ns: undefined}),
69
81
  description: 'Expected resolve time in rpc attempt details',
@@ -82,7 +94,7 @@ const tests = [
82
94
  {
83
95
  args: makeArgs({}),
84
96
  description: 'An in flight rpc attempt is mapped to an attempt',
85
- expected: makeExpected({is_pending: true}),
97
+ expected: makeExpected({confirmed_at: undefined, is_pending: true}),
86
98
  },
87
99
  {
88
100
  args: makeArgs({status: 'SUCCEEDED'}),
@@ -92,7 +104,11 @@ const tests = [
92
104
  {
93
105
  args: makeArgs({status: 'FAILED'}),
94
106
  description: 'An rpc attempt is mapped to an attempt',
95
- expected: makeExpected({is_failed: true}),
107
+ expected: makeExpected({
108
+ confirmed_at: undefined,
109
+ failed_at: '1970-01-01T00:00:00.000Z',
110
+ is_failed: true,
111
+ }),
96
112
  },
97
113
  ];
98
114
 
@@ -73,7 +73,9 @@ const makeArgs = overrides => {
73
73
  const makeExpected = overrides => {
74
74
  const expected = {
75
75
  attempts: [{
76
- confirmed_at: '1970-01-01T00:00:00.001Z',
76
+ confirmed_at: undefined,
77
+ created_at: '1970-01-01T00:00:00.001Z',
78
+ failed_at: '1970-01-01T00:00:00.001Z',
77
79
  is_confirmed: false,
78
80
  is_failed: true,
79
81
  is_pending: false,
@@ -272,6 +274,8 @@ const tests = [
272
274
  expected: makeExpected({
273
275
  attempts: [{
274
276
  confirmed_at: '2020-04-20T19:17:16.160Z',
277
+ created_at: '2020-04-20T19:17:15.428Z',
278
+ failed_at: undefined,
275
279
  is_confirmed: true,
276
280
  is_failed: false,
277
281
  is_pending: false,
@@ -0,0 +1,14 @@
1
+ import {expectError, expectType} from 'tsd';
2
+ import {addExternalSocket} from '../../lnd_methods';
3
+ import {AuthenticatedLnd} from '../../lnd_grpc';
4
+
5
+ const lnd = {} as AuthenticatedLnd;
6
+ const socket = 'socket';
7
+
8
+ expectError(addExternalSocket());
9
+ expectError(addExternalSocket({}));
10
+ expectError(addExternalSocket({lnd}));
11
+ expectError(addExternalSocket({socket}));
12
+
13
+ expectType<void>(await addExternalSocket({lnd, socket}));
14
+ expectType<void>(addExternalSocket({lnd, socket}, () => {}));
@@ -0,0 +1,60 @@
1
+ import {expectError, expectType} from 'tsd';
2
+ import {
3
+ beginGroupSigningSession,
4
+ BeginGroupSigningSessionResult,
5
+ } from '../../lnd_methods';
6
+ import {AuthenticatedLnd} from '../../lnd_grpc';
7
+
8
+ const lnd = {} as AuthenticatedLnd;
9
+ const is_key_spend = true;
10
+ const key_family = 0;
11
+ const key_index = 0;
12
+ const public_keys = ['pubkey'];
13
+ const root_hash = 'root hash';
14
+
15
+ expectError(beginGroupSigningSession());
16
+ expectError(beginGroupSigningSession({}));
17
+ expectError(beginGroupSigningSession({lnd}));
18
+ expectError(beginGroupSigningSession({key_family}));
19
+ expectError(beginGroupSigningSession({key_index}));
20
+ expectError(beginGroupSigningSession({public_keys}));
21
+ expectError(beginGroupSigningSession({lnd, key_family}));
22
+ expectError(beginGroupSigningSession({lnd, key_index}));
23
+ expectError(beginGroupSigningSession({lnd, public_keys}));
24
+ expectError(beginGroupSigningSession({key_family, key_index}));
25
+ expectError(beginGroupSigningSession({key_family, public_keys}));
26
+ expectError(beginGroupSigningSession({key_index, public_keys}));
27
+ expectError(beginGroupSigningSession({lnd, key_family, key_index}));
28
+ expectError(beginGroupSigningSession({lnd, key_family, public_keys}));
29
+ expectError(beginGroupSigningSession({lnd, key_index, public_keys}));
30
+ expectError(beginGroupSigningSession({key_family, key_index, public_keys}));
31
+
32
+ expectType<BeginGroupSigningSessionResult>(
33
+ await beginGroupSigningSession({lnd, key_family, key_index, public_keys})
34
+ );
35
+ expectType<BeginGroupSigningSessionResult>(
36
+ await beginGroupSigningSession({
37
+ lnd,
38
+ key_family,
39
+ key_index,
40
+ public_keys,
41
+ is_key_spend,
42
+ root_hash,
43
+ })
44
+ );
45
+ expectType<void>(
46
+ beginGroupSigningSession(
47
+ {lnd, key_family, key_index, public_keys},
48
+ (err, res) => {
49
+ expectType<BeginGroupSigningSessionResult>(res);
50
+ }
51
+ )
52
+ );
53
+ expectType<void>(
54
+ beginGroupSigningSession(
55
+ {lnd, key_family, key_index, public_keys, is_key_spend, root_hash},
56
+ (err, res) => {
57
+ expectType<BeginGroupSigningSessionResult>(res);
58
+ }
59
+ )
60
+ );
@@ -0,0 +1,32 @@
1
+ import {expectError, expectType} from 'tsd';
2
+ import {
3
+ endGroupSigningSession,
4
+ EndGroupSigningSessionResult,
5
+ } from '../../lnd_methods';
6
+ import {AuthenticatedLnd} from '../../lnd_grpc';
7
+
8
+ const lnd = {} as AuthenticatedLnd;
9
+ const id = 'id';
10
+ const signatures = ['signature'];
11
+
12
+ expectError(endGroupSigningSession());
13
+ expectError(endGroupSigningSession({}));
14
+ expectError(endGroupSigningSession({lnd}));
15
+ expectError(endGroupSigningSession({id}));
16
+
17
+ expectType<EndGroupSigningSessionResult>(
18
+ await endGroupSigningSession({lnd, id})
19
+ );
20
+ expectType<EndGroupSigningSessionResult>(
21
+ await endGroupSigningSession({lnd, id, signatures})
22
+ );
23
+ expectType<void>(
24
+ endGroupSigningSession({lnd, id}, (err, res) => {
25
+ expectType<EndGroupSigningSessionResult>(res);
26
+ })
27
+ );
28
+ expectType<void>(
29
+ endGroupSigningSession({lnd, id, signatures}, (err, res) => {
30
+ expectType<EndGroupSigningSessionResult>(res);
31
+ })
32
+ );
@@ -0,0 +1,14 @@
1
+ import {expectError, expectType} from 'tsd';
2
+ import {removeExternalSocket} from '../../lnd_methods';
3
+ import {AuthenticatedLnd} from '../../lnd_grpc';
4
+
5
+ const lnd = {} as AuthenticatedLnd;
6
+ const socket = 'socket';
7
+
8
+ expectError(removeExternalSocket());
9
+ expectError(removeExternalSocket({}));
10
+ expectError(removeExternalSocket({lnd}));
11
+ expectError(removeExternalSocket({socket}));
12
+
13
+ expectType<void>(await removeExternalSocket({lnd, socket}));
14
+ expectType<void>(removeExternalSocket({lnd, socket}, () => {}));
@@ -0,0 +1,14 @@
1
+ import {expectError, expectType} from 'tsd';
2
+ import {updateAlias} from '../../lnd_methods';
3
+ import {AuthenticatedLnd} from '../../lnd_grpc';
4
+
5
+ const lnd = {} as AuthenticatedLnd;
6
+ const node = 'node';
7
+
8
+ expectError(updateAlias());
9
+ expectError(updateAlias({}));
10
+ expectError(updateAlias({lnd}));
11
+ expectError(updateAlias({node}));
12
+
13
+ expectType<void>(await updateAlias({lnd, node}));
14
+ expectType<void>(updateAlias({lnd, node}, () => {}));
@@ -0,0 +1,14 @@
1
+ import {expectError, expectType} from 'tsd';
2
+ import {updateColor} from '../../lnd_methods';
3
+ import {AuthenticatedLnd} from '../../lnd_grpc';
4
+
5
+ const lnd = {} as AuthenticatedLnd;
6
+ const color = 'color';
7
+
8
+ expectError(updateColor());
9
+ expectError(updateColor({}));
10
+ expectError(updateColor({lnd}));
11
+ expectError(updateColor({color}));
12
+
13
+ expectType<void>(await updateColor({lnd, color}));
14
+ expectType<void>(updateColor({lnd, color}, () => {}));
@@ -0,0 +1,29 @@
1
+ import {expectError, expectType} from 'tsd';
2
+ import {
3
+ updateGroupSigningSession,
4
+ UpdateGroupSigningSessionResult,
5
+ } from '../../lnd_methods';
6
+ import {AuthenticatedLnd} from '../../lnd_grpc';
7
+
8
+ const lnd = {} as AuthenticatedLnd;
9
+ const hash = 'hash';
10
+ const id = 'id';
11
+ const nonces = ['nonce'];
12
+
13
+ expectError(updateGroupSigningSession());
14
+ expectError(updateGroupSigningSession({}));
15
+ expectError(updateGroupSigningSession({lnd}));
16
+ expectError(updateGroupSigningSession({hash}));
17
+ expectError(updateGroupSigningSession({id}));
18
+ expectError(updateGroupSigningSession({nonces}));
19
+ expectError(updateGroupSigningSession({lnd, hash}));
20
+ expectError(updateGroupSigningSession({lnd, id}));
21
+ expectError(updateGroupSigningSession({lnd, nonces}));
22
+ expectError(updateGroupSigningSession({lnd, hash, id}));
23
+ expectError(updateGroupSigningSession({lnd, hash, nonces}));
24
+ expectError(updateGroupSigningSession({lnd, id, nonces}));
25
+
26
+ expectType<UpdateGroupSigningSessionResult>(
27
+ await updateGroupSigningSession({lnd, hash, id, nonces})
28
+ );
29
+ expectType<void>(updateGroupSigningSession({lnd, hash, id, nonces}, () => {}));