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 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,
@@ -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 permissions = (args.methods || []).map(method => {
84
- return urisForMethod({method}).uris.map(uriAsPermission);
84
+ const uris = (args.methods || []).map(method => {
85
+ return urisForMethod({method}).uris;
85
86
  });
86
87
 
87
- return cbk(null, flatten(permissions));
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 = {getAccessIds, grantAccess, revokeAccess, verifyAccess};
7
+ module.exports = {
8
+ getAccessIds,
9
+ grantAccess,
10
+ revokeAccess,
11
+ subscribeToRpcRequests,
12
+ verifyAccess,
13
+ };
@@ -449,6 +449,10 @@
449
449
  "subscribeToPayViaRoutes"
450
450
  ]
451
451
  },
452
+ "subscribeToRpcRequests": {
453
+ "method": "RegisterRPCMiddleware",
454
+ "type": "default"
455
+ },
452
456
  "subscribeToTransactions": {
453
457
  "method": "SubscribeTransactions",
454
458
  "type": "default"
@@ -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>
@@ -1,7 +1,7 @@
1
- const {addPeer} = require('./../peers');
2
1
  const asyncAuto = require('async/auto');
3
2
  const {returnResult} = require('asyncjs-util');
4
3
 
4
+ const {addPeer} = require('./../peers');
5
5
  const {isLnd} = require('./../../lnd_requests');
6
6
 
7
7
  const defaultMinConfs = 1;
@@ -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.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.9.0"
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,
@@ -260,6 +260,7 @@ const tests = [
260
260
  local_min_htlc_mtokens: '1',
261
261
  local_reserve: 1,
262
262
  partner_public_key: '000000000000000000000000000000000000000000000000000000000000000000',
263
+ past_states: 1,
263
264
  pending_payments: [],
264
265
  received: 1,
265
266
  remote_balance: 1,
@@ -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
+ });