@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.
- package/dist/0xsequence-guard.cjs.dev.js +324 -68
- package/dist/0xsequence-guard.cjs.prod.js +324 -68
- package/dist/0xsequence-guard.esm.js +322 -65
- package/dist/declarations/src/guard.gen.d.ts +94 -1
- package/dist/declarations/src/index.d.ts +0 -1
- package/dist/declarations/src/signer.d.ts +43 -9
- package/package.json +5 -3
- package/src/guard.gen.ts +179 -4
- package/src/index.ts +0 -1
- package/src/signer.ts +264 -64
|
@@ -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
|
|
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(
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
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
|
-
|
|
174
|
-
return;
|
|
225
|
+
onRejection('expected sequence signature request metadata');
|
|
226
|
+
return false;
|
|
175
227
|
}
|
|
176
|
-
|
|
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
|
-
|
|
194
|
-
|
|
195
|
-
|
|
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()
|
|
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
|
-
|
|
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
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
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.
|
|
483
|
+
exports.AuthMethod = AuthMethod;
|
|
227
484
|
exports.GuardSigner = GuardSigner;
|
|
228
|
-
exports.
|
|
229
|
-
exports.
|
|
230
|
-
exports.WebRPCVersion = WebRPCVersion;
|
|
485
|
+
exports.getAuthUpdateProofTypedData = getAuthUpdateProofTypedData;
|
|
486
|
+
exports.getOwnershipProofTypedData = getOwnershipProofTypedData;
|