@@ -12,6 +12,7 @@ import (
12
12
"net/http"
13
13
"os"
14
14
"runtime/debug"
15
+ "strings"
15
16
"syscall/js"
16
17
17
18
"github.com/btcsuite/btcd/btcec/v2"
@@ -34,6 +35,8 @@ import (
34
35
"github.com/lightningnetwork/lnd/lnrpc/wtclientrpc"
35
36
"github.com/lightningnetwork/lnd/signal"
36
37
"google.golang.org/grpc"
38
+ "gopkg.in/macaroon-bakery.v2/bakery/checkers"
39
+ "gopkg.in/macaroon.v2"
37
40
)
38
41
39
42
type stubPackageRegistration func (map [string ]func (context.Context ,
@@ -104,6 +107,7 @@ func main() {
104
107
callbacks .Set ("wasmClientDisconnect" , js .FuncOf (wc .Disconnect ))
105
108
callbacks .Set ("wasmClientInvokeRPC" , js .FuncOf (wc .InvokeRPC ))
106
109
callbacks .Set ("wasmClientStatus" , js .FuncOf (wc .Status ))
110
+ callbacks .Set ("wasmClientGetExpiry" , js .FuncOf (wc .GetExpiry ))
107
111
js .Global ().Set (cfg .NameSpace , callbacks )
108
112
109
113
for _ , registration := range registrations {
@@ -127,6 +131,8 @@ type wasmClient struct {
127
131
128
132
statusChecker func () mailbox.ConnStatus
129
133
134
+ mac * macaroon.Macaroon
135
+
130
136
registry map [string ]func (context.Context , * grpc.ClientConn ,
131
137
string , func (string , error ))
132
138
}
@@ -202,10 +208,28 @@ func (w *wasmClient) ConnectServer(_ js.Value, args []js.Value) interface{} {
202
208
),
203
209
)
204
210
}, func (data []byte ) error {
211
+ parts := strings .Split (string (data ), ": " )
212
+ if len (parts ) != 2 || parts [0 ] != "Macaroon" {
213
+ return fmt .Errorf ("authdata does " +
214
+ "not contain a macaroon" )
215
+ }
216
+
217
+ macBytes , err := hex .DecodeString (parts [1 ])
218
+ if err != nil {
219
+ return err
220
+ }
221
+
222
+ mac := & macaroon.Macaroon {}
223
+ err = mac .UnmarshalBinary (macBytes )
224
+ if err != nil {
225
+ return fmt .Errorf ("unable to decode " +
226
+ "macaroon: %v" , err )
227
+ }
228
+
229
+ w .mac = mac
230
+
205
231
return callJsCallback (
206
- w .cfg .OnAuthData , hex .EncodeToString (
207
- data ,
208
- ),
232
+ w .cfg .OnAuthData , string (data ),
209
233
)
210
234
},
211
235
)
@@ -281,6 +305,49 @@ func (w *wasmClient) InvokeRPC(_ js.Value, args []js.Value) interface{} {
281
305
282
306
}
283
307
308
+ func (w * wasmClient ) GetExpiry (_ js.Value , _ []js.Value ) interface {} {
309
+ if w .mac == nil {
310
+ log .Errorf ("macaroon not obtained yet. GetExpiry should " +
311
+ "only be called once the connection is complete" )
312
+ return nil
313
+ }
314
+
315
+ expiry , found := checkers .ExpiryTime (nil , w .mac .Caveats ())
316
+ if ! found {
317
+ return nil
318
+ }
319
+
320
+ return js .ValueOf (expiry .Unix ())
321
+ }
322
+ if len (args ) != 1 {
323
+ return js .ValueOf ("invalid use of wasmClientExtractExpiry, " +
324
+ "need 1 parameters: macaroon string" )
325
+ }
326
+
327
+ parts := strings .Split (args [0 ].String (), ": " )
328
+ if len (parts ) != 2 || parts [0 ] != "Macaroon" {
329
+ return js .ValueOf ("macaroon missing from auth data" )
330
+ }
331
+
332
+ macBytes , err := hex .DecodeString (parts [1 ])
333
+ if err != nil {
334
+ return js .ValueOf (err .Error ())
335
+ }
336
+
337
+ mac := & macaroon.Macaroon {}
338
+ if err := mac .UnmarshalBinary (macBytes ); err != nil {
339
+ return js .ValueOf (fmt .Sprintf ("unable to decode macaroon: %v" ,
340
+ err ))
341
+ }
342
+
343
+ expiry , found := checkers .ExpiryTime (nil , mac .Caveats ())
344
+ if ! found {
345
+ return nil
346
+ }
347
+
348
+ return js .ValueOf (expiry .Unix ())
349
+ }
350
+
284
351
// validateArgs checks that the correct keys and callback functions have been
285
352
// provided.
286
353
func validateArgs (cfg * config , localPrivKey , remotePubKey string ) error {
0 commit comments