@0xsequence/guard 1.4.0 → 1.4.2

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.
@@ -2,8 +2,10 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var ethers = require('ethers');
6
5
  var core = require('@0xsequence/core');
6
+ var signhub = require('@0xsequence/signhub');
7
+ var utils = require('@0xsequence/utils');
8
+ var ethers = require('ethers');
7
9
 
8
10
  function _extends() {
9
11
  _extends = Object.assign ? Object.assign.bind() : function (target) {
@@ -20,22 +22,6 @@ function _extends() {
20
22
  return _extends.apply(this, arguments);
21
23
  }
22
24
 
23
- /* eslint-disable */
24
- // sequence-guard v0.4.0 a29651d1d5f63268e8d03b51e46557e0632c144d
25
- // --
26
- // Code generated by webrpc-gen@v0.10.x-dev with typescript generator. DO NOT EDIT.
27
- //
28
- // webrpc-gen -schema=guard.ridl -target=typescript -client -out=./clients/guard.gen.ts
29
-
30
- // WebRPC description and code-gen version
31
- const WebRPCVersion = 'v1';
32
-
33
- // Schema version of your RIDL schema
34
- const WebRPCSchemaVersion = 'v0.4.0';
35
-
36
- // Schema hash generated from your RIDL schema
37
- const WebRPCSchemaHash = 'a29651d1d5f63268e8d03b51e46557e0632c144d';
38
-
39
25
  //
40
26
  // Types
41
27
  //
@@ -99,6 +85,80 @@ class Guard {
99
85
  });
100
86
  });
101
87
  };
88
+ this.authMethods = (args, headers) => {
89
+ return this.fetch(this.url('AuthMethods'), createHTTPRequest(args, headers)).then(res => {
90
+ return buildResponse(res).then(_data => {
91
+ return {
92
+ methods: _data.methods,
93
+ active: _data.active
94
+ };
95
+ });
96
+ });
97
+ };
98
+ this.setPIN = (args, headers) => {
99
+ return this.fetch(this.url('SetPIN'), createHTTPRequest(args, headers)).then(res => {
100
+ return buildResponse(res).then(_data => {
101
+ return {};
102
+ });
103
+ });
104
+ };
105
+ this.resetPIN = (args, headers) => {
106
+ return this.fetch(this.url('ResetPIN'), createHTTPRequest(args, headers)).then(res => {
107
+ return buildResponse(res).then(_data => {
108
+ return {};
109
+ });
110
+ });
111
+ };
112
+ this.createTOTP = (args, headers) => {
113
+ return this.fetch(this.url('CreateTOTP'), createHTTPRequest(args, headers)).then(res => {
114
+ return buildResponse(res).then(_data => {
115
+ return {
116
+ uri: _data.uri
117
+ };
118
+ });
119
+ });
120
+ };
121
+ this.commitTOTP = (args, headers) => {
122
+ return this.fetch(this.url('CommitTOTP'), createHTTPRequest(args, headers)).then(res => {
123
+ return buildResponse(res).then(_data => {
124
+ return {
125
+ codes: _data.codes
126
+ };
127
+ });
128
+ });
129
+ };
130
+ this.resetTOTP = (args, headers) => {
131
+ return this.fetch(this.url('ResetTOTP'), createHTTPRequest(args, headers)).then(res => {
132
+ return buildResponse(res).then(_data => {
133
+ return {};
134
+ });
135
+ });
136
+ };
137
+ this.reset2FA = (args, headers) => {
138
+ return this.fetch(this.url('Reset2FA'), createHTTPRequest(args, headers)).then(res => {
139
+ return buildResponse(res).then(_data => {
140
+ return {};
141
+ });
142
+ });
143
+ };
144
+ this.recoveryCodes = (args, headers) => {
145
+ return this.fetch(this.url('RecoveryCodes'), createHTTPRequest(args, headers)).then(res => {
146
+ return buildResponse(res).then(_data => {
147
+ return {
148
+ codes: _data.codes
149
+ };
150
+ });
151
+ });
152
+ };
153
+ this.resetRecoveryCodes = (args, headers) => {
154
+ return this.fetch(this.url('ResetRecoveryCodes'), createHTTPRequest(args, headers)).then(res => {
155
+ return buildResponse(res).then(_data => {
156
+ return {
157
+ codes: _data.codes
158
+ };
159
+ });
160
+ });
161
+ };
102
162
  this.hostname = hostname;
103
163
  this.fetch = (input, init) => fetch(input, init);
104
164
  }
@@ -137,12 +197,10 @@ const buildResponse = res => {
137
197
 
138
198
  const fetch = typeof global === 'object' ? global.fetch : window.fetch;
139
199
  class GuardSigner {
140
- constructor(address, url, appendSuffix = false, onError) {
141
- this.requests = new Map();
200
+ constructor(address, url, appendSuffix = false) {
142
201
  this.address = address;
143
202
  this.url = url;
144
203
  this.appendSuffix = appendSuffix;
145
- this.onError = onError;
146
204
  this.guard = new Guard(url, fetch);
147
205
  }
148
206
  async getAddress() {
@@ -157,32 +215,18 @@ class GuardSigner {
157
215
  async decorateTransactions(bundle, _metadata) {
158
216
  return bundle;
159
217
  }
160
- async requestSignature(id, _message, metadata, callbacks) {
161
- if (!core.commons.isWalletSignRequestMetadata(metadata)) {
162
- callbacks.onRejection('Expected Sequence-like metadata');
163
- } else {
164
- // Queue the request first, this method only does that
165
- // the requesting to the API is later handled on every status change
166
- this.requests.set(id, callbacks);
167
- }
168
- return true;
169
- }
170
- notifyStatusChange(id, status, metadata) {
171
- if (!this.requests.has(id)) return;
218
+ async requestSignature(_id, message, metadata, callbacks) {
219
+ var _metadata$parts;
220
+ const {
221
+ onSignature,
222
+ onRejection
223
+ } = callbacks;
172
224
  if (!core.commons.isWalletSignRequestMetadata(metadata)) {
173
- this.requests.get(id).onRejection('Expected Sequence-like metadata (status update)');
174
- return;
225
+ onRejection('expected sequence signature request metadata');
226
+ return false;
175
227
  }
176
- this.evaluateRequest(id, status.message, status, metadata);
177
- }
178
- packMsgAndSig(address, msg, sig, chainId) {
179
- return ethers.ethers.utils.defaultAbiCoder.encode(['address', 'uint256', 'bytes', 'bytes'], [address, chainId, msg, sig]);
180
- }
181
- keyOfRequest(signer, msg, auxData, chainId) {
182
- return ethers.ethers.utils.solidityKeccak256(['address', 'uint256', 'bytes', 'bytes'], [signer, chainId, msg, auxData]);
183
- }
184
- async evaluateRequest(id, message, _, metadata) {
185
- var _metadata$parts;
228
+ const guardTotpCode = metadata.guardTotpCode;
229
+
186
230
  // Building auxData, notice: this uses the old v1 format
187
231
  // TODO: We should update the guard API so we can pass the metadata directly
188
232
  const coder = core.universal.genericCoderFor(metadata.config.version);
@@ -190,41 +234,253 @@ class GuardSigner {
190
234
  encoded
191
235
  } = coder.signature.encodeSigners(metadata.config, (_metadata$parts = metadata.parts) != null ? _metadata$parts : new Map(), [], metadata.chainId);
192
236
  try {
193
- var _this$requests$get;
194
- const key = this.keyOfRequest(this.address, message, encoded, metadata.chainId);
195
- const lastAttempt = (_this$requests$get = this.requests.get(id)) == null ? void 0 : _this$requests$get.lastAttempt;
196
- if (lastAttempt === key) {
197
- return;
198
- }
199
- this.requests.get(id).lastAttempt = key;
200
- const result = await this.guard.signWith({
237
+ const {
238
+ sig: signature
239
+ } = await this.guard.signWith({
201
240
  signer: this.address,
202
241
  request: {
203
242
  msg: ethers.ethers.utils.hexlify(message),
204
243
  auxData: this.packMsgAndSig(metadata.address, metadata.digest, encoded, metadata.chainId),
205
- chainId: ethers.ethers.BigNumber.from(metadata.chainId).toNumber() // TODO: This should be a string (in the API)
206
- }
244
+ chainId: ethers.ethers.BigNumber.from(metadata.chainId).toNumber()
245
+ },
246
+ token: guardTotpCode ? {
247
+ id: AuthMethod.TOTP,
248
+ token: guardTotpCode
249
+ } : undefined
207
250
  });
208
-
209
- if (ethers.ethers.utils.arrayify(result.sig).length !== 0) {
210
- this.requests.get(id).onSignature(result.sig);
211
- this.requests.delete(id);
251
+ if (ethers.ethers.utils.arrayify(signature).length === 0) {
252
+ throw new Error('guard response contained no signature data');
212
253
  }
213
- } catch (e) {
214
- var _this$onError;
215
- // The guard signer may reject the request for a number of reasons
216
- // like for example, if it's being the first signer (it waits for other signers to sign first)
217
- // We always forward the error here and filter on client side.
218
- (_this$onError = this.onError) == null ? void 0 : _this$onError.call(this, e);
254
+ onSignature(signature);
255
+ return true;
256
+ } catch (error) {
257
+ var _ref, _error$message;
258
+ onRejection(`unable to request guard signature: ${(_ref = (_error$message = error.message) != null ? _error$message : error.msg) != null ? _ref : error}`);
259
+ return false;
260
+ }
261
+ }
262
+ notifyStatusChange(_id, _status, _metadata) {}
263
+ async getAuthMethods(proof) {
264
+ let response;
265
+ if ('jwt' in proof) {
266
+ response = await this.guard.authMethods({}, {
267
+ Authorization: `BEARER ${proof.jwt}`
268
+ });
269
+ } else {
270
+ const signedProof = await signOwnershipProof(proof);
271
+ response = await this.guard.authMethods({
272
+ proof: {
273
+ wallet: signedProof.walletAddress,
274
+ timestamp: signedProof.timestamp.getTime(),
275
+ signer: signedProof.signerAddress,
276
+ signature: signedProof.signature
277
+ }
278
+ });
279
+ }
280
+ return response.methods.map(parseAuthMethod);
281
+ }
282
+ async setPin(pin, proof) {
283
+ const signedProof = await signAuthUpdateProof(proof);
284
+ if (pin === undefined) {
285
+ await this.guard.resetPIN({
286
+ timestamp: signedProof.timestamp.getTime(),
287
+ signature: signedProof.signature
288
+ }, {
289
+ Authorization: `BEARER ${proof.jwt}`
290
+ });
291
+ } else {
292
+ await this.guard.setPIN({
293
+ pin,
294
+ timestamp: signedProof.timestamp.getTime(),
295
+ signature: signedProof.signature
296
+ }, {
297
+ Authorization: `BEARER ${proof.jwt}`
298
+ });
219
299
  }
220
300
  }
301
+ resetPin(proof) {
302
+ return this.setPin(undefined, proof);
303
+ }
304
+ async createTotp(proof) {
305
+ const signedProof = await signAuthUpdateProof(proof);
306
+ const {
307
+ uri
308
+ } = await this.guard.createTOTP({
309
+ timestamp: signedProof.timestamp.getTime(),
310
+ signature: signedProof.signature
311
+ }, {
312
+ Authorization: `BEARER ${proof.jwt}`
313
+ });
314
+ return new URL(uri);
315
+ }
316
+ async commitTotp(token, jwt) {
317
+ const {
318
+ codes
319
+ } = await this.guard.commitTOTP({
320
+ token
321
+ }, {
322
+ Authorization: `BEARER ${jwt}`
323
+ });
324
+ return codes;
325
+ }
326
+ async resetTotp(proof) {
327
+ const signedProof = await signAuthUpdateProof(proof);
328
+ await this.guard.resetTOTP({
329
+ timestamp: signedProof.timestamp.getTime(),
330
+ signature: signedProof.signature
331
+ }, {
332
+ Authorization: `BEARER ${proof.jwt}`
333
+ });
334
+ }
335
+ async reset2fa(recoveryCode, proof) {
336
+ if ('jwt' in proof) {
337
+ await this.guard.reset2FA({
338
+ code: recoveryCode
339
+ }, {
340
+ Authorization: `BEARER ${proof.jwt}`
341
+ });
342
+ } else {
343
+ const signedProof = await signOwnershipProof(proof);
344
+ await this.guard.reset2FA({
345
+ code: recoveryCode,
346
+ proof: {
347
+ wallet: signedProof.walletAddress,
348
+ timestamp: signedProof.timestamp.getTime(),
349
+ signer: signedProof.signerAddress,
350
+ signature: signedProof.signature
351
+ }
352
+ });
353
+ }
354
+ }
355
+ async getRecoveryCodes(proof) {
356
+ const signedProof = await signAuthUpdateProof(proof);
357
+ const {
358
+ codes
359
+ } = await this.guard.recoveryCodes({
360
+ timestamp: signedProof.timestamp.getTime(),
361
+ signature: signedProof.signature
362
+ }, {
363
+ Authorization: `BEARER ${proof.jwt}`
364
+ });
365
+ return codes;
366
+ }
367
+ async resetRecoveryCodes(proof) {
368
+ const signedProof = await signAuthUpdateProof(proof);
369
+ const {
370
+ codes
371
+ } = await this.guard.resetRecoveryCodes({
372
+ timestamp: signedProof.timestamp.getTime(),
373
+ signature: signedProof.signature
374
+ }, {
375
+ Authorization: `BEARER ${proof.jwt}`
376
+ });
377
+ return codes;
378
+ }
379
+ packMsgAndSig(address, msg, sig, chainId) {
380
+ return ethers.ethers.utils.defaultAbiCoder.encode(['address', 'uint256', 'bytes', 'bytes'], [address, chainId, msg, sig]);
381
+ }
221
382
  suffix() {
222
383
  return this.appendSuffix ? [3] : [];
223
384
  }
224
385
  }
386
+ let AuthMethod = /*#__PURE__*/function (AuthMethod) {
387
+ AuthMethod["PIN"] = "PIN";
388
+ AuthMethod["TOTP"] = "TOTP";
389
+ return AuthMethod;
390
+ }({});
391
+ function parseAuthMethod(method) {
392
+ switch (method) {
393
+ case AuthMethod.PIN:
394
+ case AuthMethod.TOTP:
395
+ return method;
396
+ default:
397
+ throw new Error(`unknown auth method '${method}'`);
398
+ }
399
+ }
400
+ function isSignedOwnershipProof(proof) {
401
+ return 'signerAddress' in proof && typeof proof.signerAddress === 'string';
402
+ }
403
+ async function signOwnershipProof(proof) {
404
+ if (isSignedOwnershipProof(proof)) {
405
+ return proof;
406
+ } else {
407
+ const signer = signhub.signers.isSapientSigner(proof.signer) ? proof.signer : new signhub.signers.SignerWrapper(proof.signer);
408
+ const signerAddress = await signer.getAddress();
409
+ const timestamp = new Date();
410
+ const typedData = getOwnershipProofTypedData(proof.walletAddress, timestamp);
411
+ const digest = utils.encodeTypedDataDigest(typedData);
412
+ const randomId = ethers.ethers.utils.hexlify(ethers.ethers.utils.randomBytes(32));
413
+ return new Promise((resolve, reject) => signer.requestSignature(randomId, digest, {}, {
414
+ onSignature(signature) {
415
+ resolve({
416
+ walletAddress: proof.walletAddress,
417
+ timestamp,
418
+ signerAddress,
419
+ signature: ethers.ethers.utils.hexlify(signature)
420
+ });
421
+ },
422
+ onRejection: reject,
423
+ onStatus(_situation) {}
424
+ }));
425
+ }
426
+ }
427
+ async function signAuthUpdateProof(proof) {
428
+ if ('wallet' in proof) {
429
+ var _typedData$domain$cha;
430
+ const timestamp = new Date();
431
+ const typedData = getAuthUpdateProofTypedData(timestamp);
432
+ const signature = await proof.wallet.signTypedData(typedData.domain, typedData.types, typedData.message, (_typedData$domain$cha = typedData.domain.chainId) != null ? _typedData$domain$cha : 1, 'eip6492');
433
+ return {
434
+ jwt: proof.jwt,
435
+ timestamp,
436
+ signature
437
+ };
438
+ } else {
439
+ return proof;
440
+ }
441
+ }
442
+ function getOwnershipProofTypedData(wallet, timestamp) {
443
+ return {
444
+ domain,
445
+ types: {
446
+ AuthMethods: [{
447
+ name: 'wallet',
448
+ type: 'address'
449
+ }, {
450
+ name: 'timestamp',
451
+ type: 'string'
452
+ }]
453
+ },
454
+ message: {
455
+ wallet: ethers.ethers.utils.getAddress(wallet),
456
+ timestamp: toUTCString(timestamp)
457
+ }
458
+ };
459
+ }
460
+ function getAuthUpdateProofTypedData(timestamp) {
461
+ return {
462
+ domain,
463
+ types: {
464
+ AuthUpdate: [{
465
+ name: 'timestamp',
466
+ type: 'string'
467
+ }]
468
+ },
469
+ message: {
470
+ timestamp: toUTCString(timestamp)
471
+ }
472
+ };
473
+ }
474
+ const domain = {
475
+ name: 'Sequence Guard',
476
+ version: '1',
477
+ chainId: 1
478
+ };
479
+ function toUTCString(date) {
480
+ return date.toUTCString().replace('GMT', 'UTC');
481
+ }
225
482
 
226
- exports.Guard = Guard;
483
+ exports.AuthMethod = AuthMethod;
227
484
  exports.GuardSigner = GuardSigner;
228
- exports.WebRPCSchemaHash = WebRPCSchemaHash;
229
- exports.WebRPCSchemaVersion = WebRPCSchemaVersion;
230
- exports.WebRPCVersion = WebRPCVersion;
485
+ exports.getAuthUpdateProofTypedData = getAuthUpdateProofTypedData;
486
+ exports.getOwnershipProofTypedData = getOwnershipProofTypedData;