lightning 4.9.0 → 4.10.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 +5 -0
- package/grpc/handle_remove_listener.js +25 -0
- package/grpc/index.js +2 -0
- package/lnd_methods/index.js +2 -0
- package/lnd_methods/macaroon/grant_access.js +6 -3
- package/lnd_methods/macaroon/index.js +8 -1
- package/lnd_methods/macaroon/methods.json +4 -0
- package/lnd_methods/macaroon/subscribe_to_rpc_requests.js +113 -0
- package/lnd_methods/offchain/get_channels.d.ts +2 -0
- package/lnd_methods/offchain/get_channels.js +1 -0
- package/lnd_methods/offchain/subscribe_to_channels.d.ts +2 -0
- package/lnd_methods/offchain/subscribe_to_channels.js +1 -0
- package/lnd_methods/onchain/open_channel.js +1 -1
- package/lnd_responses/index.js +2 -0
- package/lnd_responses/rpc_channel_as_channel.js +2 -4
- package/lnd_responses/rpc_request_update_as_event.js +121 -0
- package/package.json +2 -2
- package/test/grpc/test_handle_remove_listener.js +34 -0
- package/test/lnd_methods/offchain/test_get_channels.js +1 -0
- package/test/lnd_methods/offchain/test_subscribe_to_channels.js +1 -0
- package/test/lnd_responses/test_rpc_channel_as_channel.js +1 -5
- package/test/lnd_responses/test_rpc_request_update_as_event.js +130 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# Versions
|
|
2
2
|
|
|
3
|
+
## 4.10.0
|
|
4
|
+
|
|
5
|
+
- `getChannels`: Add `past_states` to reflect the number of updates
|
|
6
|
+
- `subscribeToChannels`: Add `past_states` to reflect to number of updates
|
|
7
|
+
|
|
3
8
|
## 4.9.0
|
|
4
9
|
|
|
5
10
|
- `grantAccess`: Add support for specifying `methods` for permissions
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
const sumOf = arr => arr.reduce((sum, n) => sum + n, Number());
|
|
2
|
+
|
|
3
|
+
/** Get a function that emits an error from a gRPC subscription proxy
|
|
4
|
+
|
|
5
|
+
{
|
|
6
|
+
emitter: <EventEmitter Subscription Proxy Object>
|
|
7
|
+
events: [<Event Name String>]
|
|
8
|
+
subscription: <gRPC Subscription Object>
|
|
9
|
+
}
|
|
10
|
+
*/
|
|
11
|
+
module.exports = ({emitter, events, subscription}) => {
|
|
12
|
+
// Cancel the subscription when all listeners are removed
|
|
13
|
+
emitter.on('removeListener', () => {
|
|
14
|
+
const counts = events.map(n => emitter.listenerCount(n));
|
|
15
|
+
|
|
16
|
+
// Exit early when there are still active listeners
|
|
17
|
+
if (!!sumOf(counts)) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
subscription.cancel();
|
|
22
|
+
|
|
23
|
+
return;
|
|
24
|
+
});
|
|
25
|
+
};
|
package/grpc/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const {defaultSocket} = require('./grpc_services');
|
|
2
2
|
const emitSubscriptionError = require('./emit_subscription_error');
|
|
3
3
|
const {grpcSslCipherSuites} = require('./grpc_services');
|
|
4
|
+
const handleRemoveListener = require('./handle_remove_listener');
|
|
4
5
|
const {maxReceiveMessageLength} = require('./grpc_services');
|
|
5
6
|
const {packageTypes} = require('./grpc_services');
|
|
6
7
|
const {protoFiles} = require('./grpc_services');
|
|
@@ -13,6 +14,7 @@ module.exports = {
|
|
|
13
14
|
defaultSocket,
|
|
14
15
|
emitSubscriptionError,
|
|
15
16
|
grpcSslCipherSuites,
|
|
17
|
+
handleRemoveListener,
|
|
16
18
|
maxReceiveMessageLength,
|
|
17
19
|
packageTypes,
|
|
18
20
|
protoFiles,
|
package/lnd_methods/index.js
CHANGED
|
@@ -111,6 +111,7 @@ const {subscribeToPayViaRequest} = require('./offchain');
|
|
|
111
111
|
const {subscribeToPayViaRoutes} = require('./offchain');
|
|
112
112
|
const {subscribeToPeers} = require('./peers');
|
|
113
113
|
const {subscribeToProbeForRoute} = require('./offchain');
|
|
114
|
+
const {subscribeToRpcRequests} = require('./macaroon');
|
|
114
115
|
const {subscribeToTransactions} = require('./onchain');
|
|
115
116
|
const {subscribeToWalletStatus} = require('./unauthenticated');
|
|
116
117
|
const {unlockUtxo} = require('./onchain');
|
|
@@ -239,6 +240,7 @@ module.exports = {
|
|
|
239
240
|
subscribeToPayViaRoutes,
|
|
240
241
|
subscribeToPeers,
|
|
241
242
|
subscribeToProbeForRoute,
|
|
243
|
+
subscribeToRpcRequests,
|
|
242
244
|
subscribeToTransactions,
|
|
243
245
|
subscribeToWalletStatus,
|
|
244
246
|
unlockUtxo,
|
|
@@ -14,6 +14,7 @@ const method = 'bakeMacaroon';
|
|
|
14
14
|
const notSupported = 'unknown service lnrpc.Lightning';
|
|
15
15
|
const permissionSeparator = ':';
|
|
16
16
|
const type = 'default';
|
|
17
|
+
const uniq = arr => Array.from(new Set(arr));
|
|
17
18
|
const uriAsPermission = uri => `uri:${uri}`;
|
|
18
19
|
|
|
19
20
|
/** Give access to the node by making a macaroon access credential
|
|
@@ -80,11 +81,13 @@ module.exports = (args, cbk) => {
|
|
|
80
81
|
// Derive URI permissions
|
|
81
82
|
uris: ['validate', ({}, cbk) => {
|
|
82
83
|
try {
|
|
83
|
-
const
|
|
84
|
-
return urisForMethod({method}).uris
|
|
84
|
+
const uris = (args.methods || []).map(method => {
|
|
85
|
+
return urisForMethod({method}).uris;
|
|
85
86
|
});
|
|
86
87
|
|
|
87
|
-
|
|
88
|
+
const permissions = uniq(flatten(uris)).map(uriAsPermission);
|
|
89
|
+
|
|
90
|
+
return cbk(null, permissions);
|
|
88
91
|
} catch (err) {
|
|
89
92
|
return cbk([400, err.message]);
|
|
90
93
|
}
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
const getAccessIds = require('./get_access_ids');
|
|
2
2
|
const grantAccess = require('./grant_access');
|
|
3
3
|
const revokeAccess = require('./revoke_access');
|
|
4
|
+
const subscribeToRpcRequests = require('./subscribe_to_rpc_requests');
|
|
4
5
|
const verifyAccess = require('./verify_access');
|
|
5
6
|
|
|
6
|
-
module.exports = {
|
|
7
|
+
module.exports = {
|
|
8
|
+
getAccessIds,
|
|
9
|
+
grantAccess,
|
|
10
|
+
revokeAccess,
|
|
11
|
+
subscribeToRpcRequests,
|
|
12
|
+
verifyAccess,
|
|
13
|
+
};
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
const EventEmitter = require('events');
|
|
2
|
+
const {randomBytes} = require('crypto');
|
|
3
|
+
|
|
4
|
+
const asyncAuto = require('async/auto');
|
|
5
|
+
const {returnResult} = require('asyncjs-util');
|
|
6
|
+
|
|
7
|
+
const {emitSubscriptionError} = require('./../../grpc');
|
|
8
|
+
const {handleRemoveListener} = require('./../../grpc');
|
|
9
|
+
const {isLnd} = require('./../../lnd_requests');
|
|
10
|
+
const {rpcRequestUpdateAsEvent} = require('./../../lnd_responses');
|
|
11
|
+
|
|
12
|
+
const cancelError = 'Cancelled on client';
|
|
13
|
+
const events = ['request', 'response'];
|
|
14
|
+
const makeId = () => randomBytes(32).toString('hex');
|
|
15
|
+
const method = 'RegisterRPCMiddleware';
|
|
16
|
+
const sumOf = arr => arr.reduce((sum, n) => sum + n, Number());
|
|
17
|
+
const type = 'default';
|
|
18
|
+
|
|
19
|
+
/** Subscribe to RPC requests and their responses
|
|
20
|
+
|
|
21
|
+
Requires `macaroon:write` permission
|
|
22
|
+
|
|
23
|
+
LND must be running with rpc middleware enabled: `rpcmiddleware.enable=1`
|
|
24
|
+
|
|
25
|
+
This method is not supported in LND 0.13.2 and below
|
|
26
|
+
|
|
27
|
+
{
|
|
28
|
+
lnd: <Authenticated LND API Object>
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
@returns via cbk or Promise
|
|
32
|
+
{
|
|
33
|
+
subscription: <RPC Request Subscription EventEmitter Object>
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
@event 'request'
|
|
37
|
+
{
|
|
38
|
+
id: <Request Id Number>
|
|
39
|
+
[macaroon]: <Base64 Encoded Macaroon String>
|
|
40
|
+
[uri]: <RPC URI String>
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
@event 'response'
|
|
44
|
+
{
|
|
45
|
+
id: <Request Id Number>
|
|
46
|
+
[macaroon]: <Base64 Encoded Macaroon String>
|
|
47
|
+
[uri]: <RPC URI String>
|
|
48
|
+
}
|
|
49
|
+
*/
|
|
50
|
+
module.exports = ({lnd}, cbk) => {
|
|
51
|
+
return new Promise((resolve, reject) => {
|
|
52
|
+
return asyncAuto({
|
|
53
|
+
// Check arguments
|
|
54
|
+
validate: cbk => {
|
|
55
|
+
if (!isLnd({lnd, method, type})) {
|
|
56
|
+
return cbk([400, 'ExpectedLndToSubscribeToRpcRequests']);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return cbk();
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
// Intercept RPC requests
|
|
63
|
+
intercept: ['validate', ({}, cbk) => {
|
|
64
|
+
const emitter = new EventEmitter();
|
|
65
|
+
|
|
66
|
+
try {
|
|
67
|
+
const subscription = lnd[type][method]({});
|
|
68
|
+
|
|
69
|
+
subscription.write({
|
|
70
|
+
register: {middleware_name: makeId(), read_only_mode: true},
|
|
71
|
+
},
|
|
72
|
+
err => {
|
|
73
|
+
if (!!err) {
|
|
74
|
+
return cbk([503, 'UnexpectedErrInterceptingRpcRequests', {err}]);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return cbk(null, {subscription: emitter});
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
handleRemoveListener({subscription, emitter, events});
|
|
81
|
+
|
|
82
|
+
const errored = emitSubscriptionError({emitter, subscription});
|
|
83
|
+
|
|
84
|
+
subscription.on('data', update => {
|
|
85
|
+
try {
|
|
86
|
+
const details = rpcRequestUpdateAsEvent(update);
|
|
87
|
+
|
|
88
|
+
emitter.emit(details.event, {
|
|
89
|
+
id: details.id,
|
|
90
|
+
macaroon: details.macaroon,
|
|
91
|
+
uri: details.uri,
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
return subscription.write({
|
|
95
|
+
feedback: {replace_response: false},
|
|
96
|
+
request_id: details.id,
|
|
97
|
+
});
|
|
98
|
+
} catch (err) {
|
|
99
|
+
return errored([503, err.message]);
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
subscription.on('end', () => emitter.emit('end'));
|
|
104
|
+
subscription.on('error', err => errored(err));
|
|
105
|
+
subscription.on('status', n => emitter.emit('status', n));
|
|
106
|
+
} catch (err) {
|
|
107
|
+
return cbk([503, 'UnexpectedErrorSubscribingToRpcRequests', {err}]);
|
|
108
|
+
}
|
|
109
|
+
}],
|
|
110
|
+
},
|
|
111
|
+
returnResult({reject, resolve, of: 'intercept'}, cbk));
|
|
112
|
+
});
|
|
113
|
+
};
|
|
@@ -60,6 +60,8 @@ export type GetChannelsResult = {
|
|
|
60
60
|
local_reserve: number;
|
|
61
61
|
/** Channel Partner Public Key */
|
|
62
62
|
partner_public_key: string;
|
|
63
|
+
/** Past Channel States Count */
|
|
64
|
+
past_states: number;
|
|
63
65
|
pending_payments: {
|
|
64
66
|
/** Payment Preimage Hash Hex */
|
|
65
67
|
id: string;
|
|
@@ -50,6 +50,7 @@ const type = 'default';
|
|
|
50
50
|
[local_min_htlc_mtokens]: <Local Minimum HTLC Millitokens String>
|
|
51
51
|
local_reserve: <Local Reserved Tokens Number>
|
|
52
52
|
partner_public_key: <Channel Partner Public Key String>
|
|
53
|
+
past_states: <Total Count of Past Channel States Number>
|
|
53
54
|
pending_payments: [{
|
|
54
55
|
id: <Payment Preimage Hash Hex String>
|
|
55
56
|
[in_channel]: <Forward Inbound From Channel Id String>
|
|
@@ -99,6 +99,8 @@ export type SubscribeToChannelsChannelOpenedEvent = {
|
|
|
99
99
|
local_reserve: number;
|
|
100
100
|
/** Channel Partner Public Key */
|
|
101
101
|
partner_public_key: string;
|
|
102
|
+
/** Total Count of Past Channel States */
|
|
103
|
+
past_states: number;
|
|
102
104
|
pending_payments: {
|
|
103
105
|
/** Payment Preimage Hash Hex */
|
|
104
106
|
id: string;
|
|
@@ -94,6 +94,7 @@ const updateOpening = 'pending_open_channel';
|
|
|
94
94
|
local_given: <Local Initially Pushed Tokens Number>
|
|
95
95
|
local_reserve: <Local Reserved Tokens Number>
|
|
96
96
|
partner_public_key: <Channel Partner Public Key String>
|
|
97
|
+
past_states: <Total Count of Past Channel States Number>
|
|
97
98
|
pending_payments: [{
|
|
98
99
|
id: <Payment Preimage Hash Hex String>
|
|
99
100
|
is_outgoing: <Payment Is Outgoing Bool>
|
package/lnd_responses/index.js
CHANGED
|
@@ -31,6 +31,7 @@ const rpcNodeAsNode = require('./rpc_node_as_node');
|
|
|
31
31
|
const rpcOutpointAsUpdate = require('./rpc_outpoint_as_update');
|
|
32
32
|
const rpcPaymentAsPayment = require('./rpc_payment_as_payment');
|
|
33
33
|
const rpcPeerAsPeer = require('./rpc_peer_as_peer');
|
|
34
|
+
const rpcRequestUpdateAsEvent = require('./rpc_request_update_as_event');
|
|
34
35
|
const rpcResolutionAsResolution = require('./rpc_resolution_as_resolution');
|
|
35
36
|
const rpcRouteAsRoute = require('./rpc_route_as_route');
|
|
36
37
|
const rpcTxAsTransaction = require('./rpc_tx_as_transaction');
|
|
@@ -71,6 +72,7 @@ module.exports = {
|
|
|
71
72
|
rpcOutpointAsUpdate,
|
|
72
73
|
rpcPaymentAsPayment,
|
|
73
74
|
rpcPeerAsPeer,
|
|
75
|
+
rpcRequestUpdateAsEvent,
|
|
74
76
|
rpcResolutionAsResolution,
|
|
75
77
|
rpcRouteAsRoute,
|
|
76
78
|
rpcTxAsTransaction,
|
|
@@ -90,6 +90,7 @@ const outpointDelimiter = ':';
|
|
|
90
90
|
local_min_htlc_mtokens: <Local Minimum HTLC Millitokens String>
|
|
91
91
|
local_reserve: <Local Reserved Tokens Number>
|
|
92
92
|
partner_public_key: <Channel Partner Public Key String>
|
|
93
|
+
past_states: <Total Count of Past States Number>
|
|
93
94
|
pending_payments: [{
|
|
94
95
|
id: <Payment Preimage Hash Hex String>
|
|
95
96
|
[in_channel]: <Forwarding from Channel Id String>
|
|
@@ -144,10 +145,6 @@ module.exports = args => {
|
|
|
144
145
|
throw new Error('ExpectedCommitWeightInChannelMessage');
|
|
145
146
|
}
|
|
146
147
|
|
|
147
|
-
if (!args.commitment_type) {
|
|
148
|
-
throw new Error('ExpectedCommitmentTypeInChannelMessage');
|
|
149
|
-
}
|
|
150
|
-
|
|
151
148
|
if (args.fee_per_kw === undefined) {
|
|
152
149
|
throw new Error('ExpectedFeePerKwInChannelMessage');
|
|
153
150
|
}
|
|
@@ -243,6 +240,7 @@ module.exports = args => {
|
|
|
243
240
|
local_min_htlc_mtokens: own.min_htlc_msat,
|
|
244
241
|
local_reserve: Number(own.chan_reserve_sat),
|
|
245
242
|
partner_public_key: args.remote_pubkey,
|
|
243
|
+
past_states: Number(args.num_updates),
|
|
246
244
|
pending_payments: args.pending_htlcs.map(rpcHtlcAsPayment),
|
|
247
245
|
received: Number(args.total_satoshis_received),
|
|
248
246
|
remote_balance: Number(args.remote_balance),
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
const bufferAsBase64 = n => !!n.length ? n.toString('base64') : undefined;
|
|
2
|
+
const {isBuffer} = Buffer;
|
|
3
|
+
const request = 'request';
|
|
4
|
+
const response = 'response';
|
|
5
|
+
const streamAuth = 'stream_auth';
|
|
6
|
+
|
|
7
|
+
/** Derive request details from an RPC request update
|
|
8
|
+
|
|
9
|
+
{
|
|
10
|
+
request_id: <Request Id Number String>
|
|
11
|
+
raw_macaroon: <Raw Macaroon Buffer Object>
|
|
12
|
+
custom_caveat_condition: <Custom Caveat Condition String>
|
|
13
|
+
[request]: {
|
|
14
|
+
method_full_uri: <Method URI String>
|
|
15
|
+
stream_rpc: <Is String RPC Bool>
|
|
16
|
+
type_name: <RPC Message Type String>
|
|
17
|
+
serialized: <Raw Protobuf Request Buffer Object>
|
|
18
|
+
}
|
|
19
|
+
[response]: {
|
|
20
|
+
method_full_uri: <Method URI String>
|
|
21
|
+
stream_rpc: <Is String RPC Bool>
|
|
22
|
+
type_name: <RPC Message Type String>
|
|
23
|
+
serialized: <Raw Protobuf Response Buffer Object>
|
|
24
|
+
}
|
|
25
|
+
[stream_auth]: {
|
|
26
|
+
method_full_uri: <Method URI String>
|
|
27
|
+
}
|
|
28
|
+
intercept_type: <RPC Update Type String>
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
@throws
|
|
32
|
+
<Error>
|
|
33
|
+
|
|
34
|
+
@returns
|
|
35
|
+
{
|
|
36
|
+
[event]: <Event Type String>
|
|
37
|
+
id: <Request Id Number>
|
|
38
|
+
[macaroon]: <Base64 Encoded Macaroon String>
|
|
39
|
+
[uri]: <RPC URI String>
|
|
40
|
+
}
|
|
41
|
+
*/
|
|
42
|
+
module.exports = args => {
|
|
43
|
+
if (!args) {
|
|
44
|
+
throw new Error('ExpectedRpcRequestUpdateDetailsToDeriveUpdateEvent');
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (args.custom_caveat_condition === undefined) {
|
|
48
|
+
throw new Error('ExpectedCustomCaveatConditionInRpcRequestUpdate');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (args.intercept_type === undefined) {
|
|
52
|
+
throw new Error('ExpectedInterceptTypeInRpcRequestUpdate');
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (!isBuffer(args.raw_macaroon)) {
|
|
56
|
+
throw new Error('ExpectedCompleteMacaroonCredentialsInRequestUpdate');
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (args.request_id === undefined) {
|
|
60
|
+
throw new Error('ExpectedRequestIdInRpcRequestUpdate');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const id = Number(args.request_id);
|
|
64
|
+
|
|
65
|
+
switch (args.intercept_type) {
|
|
66
|
+
// New subscription
|
|
67
|
+
case streamAuth:
|
|
68
|
+
if (!args[streamAuth]) {
|
|
69
|
+
throw new Error('ExpectedStreamAuthDetailsInRpcRequestUpdate');
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (!args[streamAuth].method_full_uri) {
|
|
73
|
+
throw new Error('ExpectedFullUriForStreamAuthRpcRequestUpdate');
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return {
|
|
77
|
+
id,
|
|
78
|
+
event: request,
|
|
79
|
+
macaroon: bufferAsBase64(args.raw_macaroon),
|
|
80
|
+
uri: args[streamAuth].method_full_uri,
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
// New request
|
|
84
|
+
case request:
|
|
85
|
+
if (!args[request]) {
|
|
86
|
+
throw new Error('ExpectedRequestDetailsInRpcRequestUpdate');
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (!args[request].method_full_uri) {
|
|
90
|
+
throw new Error('ExpectedFullUriForRequestRpcRequestUpdate');
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return {
|
|
94
|
+
id,
|
|
95
|
+
event: request,
|
|
96
|
+
macaroon: bufferAsBase64(args.raw_macaroon),
|
|
97
|
+
uri: args[request].method_full_uri,
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
// Response to past request
|
|
101
|
+
case response:
|
|
102
|
+
if (!args[response]) {
|
|
103
|
+
throw new Error('ExpectedResponseDetailsInRpcRequestUpdate');
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (!args[response].method_full_uri) {
|
|
107
|
+
throw new Error('ExpectedFullUriForResponseRpcRequestUpdate');
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return {
|
|
111
|
+
id,
|
|
112
|
+
event: response,
|
|
113
|
+
macaroon: bufferAsBase64(args.raw_macaroon),
|
|
114
|
+
uri: args[response].method_full_uri,
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
// Unknown update
|
|
118
|
+
default:
|
|
119
|
+
return {id, macaroon: bufferAsBase64(args.raw_macaroon)};
|
|
120
|
+
}
|
|
121
|
+
};
|
package/package.json
CHANGED
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"@alexbosworth/tap": "15.0.10",
|
|
32
32
|
"tsd": "0.17.0",
|
|
33
33
|
"typescript": "4.4.3",
|
|
34
|
-
"ws": "8.2.
|
|
34
|
+
"ws": "8.2.3"
|
|
35
35
|
},
|
|
36
36
|
"engines": {
|
|
37
37
|
"node": ">=12"
|
|
@@ -56,5 +56,5 @@
|
|
|
56
56
|
"directory": "test/typescript"
|
|
57
57
|
},
|
|
58
58
|
"types": "index.d.ts",
|
|
59
|
-
"version": "4.
|
|
59
|
+
"version": "4.10.0"
|
|
60
60
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
const {test} = require('@alexbosworth/tap');
|
|
2
|
+
|
|
3
|
+
const {handleRemoveListener} = require('./../../grpc');
|
|
4
|
+
|
|
5
|
+
const tests = [
|
|
6
|
+
{
|
|
7
|
+
args: {
|
|
8
|
+
emitter: {listenerCount: () => 0, on: (eventName, cbk) => cbk()},
|
|
9
|
+
events: ['event'],
|
|
10
|
+
subscription: {cancel: () => {}},
|
|
11
|
+
},
|
|
12
|
+
description: 'An error is emitted',
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
args: {
|
|
16
|
+
emitter: {listenerCount: () => 1, on: (eventName, cbk) => cbk()},
|
|
17
|
+
events: ['event'],
|
|
18
|
+
subscription: {
|
|
19
|
+
cancel: () => {
|
|
20
|
+
throw new Error('SubscriptionShouldNotBeCanceled');
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
description: 'An error is emitted',
|
|
25
|
+
},
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
tests.forEach(({args, description, expected}) => {
|
|
29
|
+
return test(description, ({end, equal}) => {
|
|
30
|
+
handleRemoveListener(args);
|
|
31
|
+
|
|
32
|
+
return end();
|
|
33
|
+
});
|
|
34
|
+
});
|
|
@@ -27,6 +27,7 @@ const makeExpected = overrides => {
|
|
|
27
27
|
local_max_pending_mtokens: '1',
|
|
28
28
|
local_reserve: 1,
|
|
29
29
|
partner_public_key: 'b',
|
|
30
|
+
past_states: 1,
|
|
30
31
|
pending_payments: [{
|
|
31
32
|
id: '0000000000000000000000000000000000000000000000000000000000000000',
|
|
32
33
|
in_channel: undefined,
|
|
@@ -85,6 +85,7 @@ const makeExpected = overrides => {
|
|
|
85
85
|
local_min_htlc_mtokens: '1',
|
|
86
86
|
local_reserve: 1,
|
|
87
87
|
partner_public_key: '00',
|
|
88
|
+
past_states: 1,
|
|
88
89
|
pending_payments: [{
|
|
89
90
|
id: '0000000000000000000000000000000000000000000000000000000000000000',
|
|
90
91
|
in_channel: undefined,
|
|
@@ -150,11 +151,6 @@ const tests = [
|
|
|
150
151
|
description: 'Channel commit weight is expected',
|
|
151
152
|
error: 'ExpectedCommitWeightInChannelMessage',
|
|
152
153
|
},
|
|
153
|
-
{
|
|
154
|
-
args: makeArgs({commitment_type: undefined}),
|
|
155
|
-
description: 'Channel commit type is expected',
|
|
156
|
-
error: 'ExpectedCommitmentTypeInChannelMessage',
|
|
157
|
-
},
|
|
158
154
|
{
|
|
159
155
|
args: makeArgs({fee_per_kw: undefined}),
|
|
160
156
|
description: 'Channel fee per kw is expected',
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
const {test} = require('@alexbosworth/tap');
|
|
2
|
+
|
|
3
|
+
const method = require('./../../lnd_responses/rpc_request_update_as_event');
|
|
4
|
+
|
|
5
|
+
const makeArgs = overrides => {
|
|
6
|
+
const args = {
|
|
7
|
+
request_id: '1',
|
|
8
|
+
raw_macaroon: Buffer.alloc(0),
|
|
9
|
+
custom_caveat_condition: '',
|
|
10
|
+
intercept_type: 'unknown type',
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
Object.keys(overrides).forEach(k => args[k] = overrides[k]);
|
|
14
|
+
|
|
15
|
+
return args;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const makeExpected = overrides => {
|
|
19
|
+
const expected = {id: 1, macaroon: undefined};
|
|
20
|
+
|
|
21
|
+
Object.keys(overrides).forEach(k => expected[k] = overrides[k]);
|
|
22
|
+
|
|
23
|
+
return expected;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const tests = [
|
|
27
|
+
{
|
|
28
|
+
args: undefined,
|
|
29
|
+
description: 'Request details expected',
|
|
30
|
+
error: 'ExpectedRpcRequestUpdateDetailsToDeriveUpdateEvent',
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
args: makeArgs({custom_caveat_condition: undefined}),
|
|
34
|
+
description: 'A custom caveat is expected',
|
|
35
|
+
error: 'ExpectedCustomCaveatConditionInRpcRequestUpdate',
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
args: makeArgs({intercept_type: undefined}),
|
|
39
|
+
description: 'An intercept type is expected',
|
|
40
|
+
error: 'ExpectedInterceptTypeInRpcRequestUpdate',
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
args: makeArgs({raw_macaroon: undefined}),
|
|
44
|
+
description: 'A raw macaroon is expected',
|
|
45
|
+
error: 'ExpectedCompleteMacaroonCredentialsInRequestUpdate',
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
args: makeArgs({request_id: undefined}),
|
|
49
|
+
description: 'A request id is expected',
|
|
50
|
+
error: 'ExpectedRequestIdInRpcRequestUpdate',
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
args: makeArgs({intercept_type: 'stream_auth'}),
|
|
54
|
+
description: 'Stream auth details are expected',
|
|
55
|
+
error: 'ExpectedStreamAuthDetailsInRpcRequestUpdate',
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
args: makeArgs({intercept_type: 'stream_auth', stream_auth: {}}),
|
|
59
|
+
description: 'Stream auth URI is expected',
|
|
60
|
+
error: 'ExpectedFullUriForStreamAuthRpcRequestUpdate',
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
args: makeArgs({intercept_type: 'request'}),
|
|
64
|
+
description: 'Request details are expected',
|
|
65
|
+
error: 'ExpectedRequestDetailsInRpcRequestUpdate',
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
args: makeArgs({intercept_type: 'request', request: {}}),
|
|
69
|
+
description: 'Request URI is expected',
|
|
70
|
+
error: 'ExpectedFullUriForRequestRpcRequestUpdate',
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
args: makeArgs({intercept_type: 'response'}),
|
|
74
|
+
description: 'Response details are expected',
|
|
75
|
+
error: 'ExpectedResponseDetailsInRpcRequestUpdate',
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
args: makeArgs({intercept_type: 'response', response: {}}),
|
|
79
|
+
description: 'Response URI is expected',
|
|
80
|
+
error: 'ExpectedFullUriForResponseRpcRequestUpdate',
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
args: makeArgs({}),
|
|
84
|
+
description: 'Request mapped to event details',
|
|
85
|
+
expected: makeExpected({}),
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
args: makeArgs({raw_macaroon: Buffer.alloc(1)}),
|
|
89
|
+
description: 'Raw macaroon is returned',
|
|
90
|
+
expected: makeExpected({macaroon: 'AA=='}),
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
args: makeArgs({
|
|
94
|
+
intercept_type: 'stream_auth',
|
|
95
|
+
stream_auth: {method_full_uri: 'uri'},
|
|
96
|
+
}),
|
|
97
|
+
description: 'Stream request mapped to event details',
|
|
98
|
+
expected: makeExpected({event: 'request', uri: 'uri'}),
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
args: makeArgs({
|
|
102
|
+
intercept_type: 'request',
|
|
103
|
+
request: {method_full_uri: 'uri'},
|
|
104
|
+
}),
|
|
105
|
+
description: 'Request mapped to event details',
|
|
106
|
+
expected: makeExpected({event: 'request', uri: 'uri'}),
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
args: makeArgs({
|
|
110
|
+
intercept_type: 'response',
|
|
111
|
+
response: {method_full_uri: 'uri'},
|
|
112
|
+
}),
|
|
113
|
+
description: 'Response mapped to event details',
|
|
114
|
+
expected: makeExpected({event: 'response', uri: 'uri'}),
|
|
115
|
+
},
|
|
116
|
+
];
|
|
117
|
+
|
|
118
|
+
tests.forEach(({args, description, error, expected}) => {
|
|
119
|
+
return test(description, ({end, strictSame, throws}) => {
|
|
120
|
+
if (!!error) {
|
|
121
|
+
throws(() => method(args), new Error(error), 'Error');
|
|
122
|
+
} else {
|
|
123
|
+
const res = method(args);
|
|
124
|
+
|
|
125
|
+
strictSame(res, expected, 'RPC request update as event');
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return end();
|
|
129
|
+
});
|
|
130
|
+
});
|