@0xsequence/guard 0.0.0-20231027021244 → 0.0.0-20231102200515
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 +50 -65
- package/dist/0xsequence-guard.cjs.prod.js +50 -65
- package/dist/0xsequence-guard.esm.js +50 -65
- package/dist/declarations/src/guard.gen.d.ts +6 -1
- package/dist/declarations/src/signer.d.ts +5 -8
- package/package.json +5 -5
- package/src/guard.gen.ts +13 -4
- package/src/signer.ts +37 -79
|
@@ -21,7 +21,7 @@ function _extends() {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
/* eslint-disable */
|
|
24
|
-
// sequence-guard v0.4.0
|
|
24
|
+
// sequence-guard v0.4.0 af5ad0623aec0b231a462052edaea1823f620a1e
|
|
25
25
|
// --
|
|
26
26
|
// Code generated by webrpc-gen@v0.12.x-dev with typescript@v0.10.0 generator. DO NOT EDIT.
|
|
27
27
|
//
|
|
@@ -34,7 +34,7 @@ const WebRPCVersion = 'v1';
|
|
|
34
34
|
const WebRPCSchemaVersion = 'v0.4.0';
|
|
35
35
|
|
|
36
36
|
// Schema hash generated from your RIDL schema
|
|
37
|
-
const WebRPCSchemaHash = '
|
|
37
|
+
const WebRPCSchemaHash = 'af5ad0623aec0b231a462052edaea1823f620a1e';
|
|
38
38
|
|
|
39
39
|
//
|
|
40
40
|
// Types
|
|
@@ -134,7 +134,9 @@ class Guard {
|
|
|
134
134
|
this.commitTOTP = (args, headers) => {
|
|
135
135
|
return this.fetch(this.url('CommitTOTP'), createHTTPRequest(args, headers)).then(res => {
|
|
136
136
|
return buildResponse(res).then(_data => {
|
|
137
|
-
return {
|
|
137
|
+
return {
|
|
138
|
+
codes: _data.codes
|
|
139
|
+
};
|
|
138
140
|
});
|
|
139
141
|
});
|
|
140
142
|
};
|
|
@@ -183,35 +185,59 @@ const buildResponse = res => {
|
|
|
183
185
|
|
|
184
186
|
const fetch = typeof global === 'object' ? global.fetch : window.fetch;
|
|
185
187
|
class GuardSigner {
|
|
186
|
-
constructor(address, url, appendSuffix = false
|
|
187
|
-
this.requests = new Map();
|
|
188
|
+
constructor(address, url, appendSuffix = false) {
|
|
188
189
|
this.address = address;
|
|
189
190
|
this.url = url;
|
|
190
191
|
this.appendSuffix = appendSuffix;
|
|
191
|
-
this.onError = onError;
|
|
192
192
|
this.guard = new Guard(url, fetch);
|
|
193
193
|
}
|
|
194
194
|
async getAddress() {
|
|
195
195
|
return this.address;
|
|
196
196
|
}
|
|
197
|
-
async requestSignature(
|
|
197
|
+
async requestSignature(_id, message, metadata, callbacks) {
|
|
198
|
+
const {
|
|
199
|
+
onSignature,
|
|
200
|
+
onRejection
|
|
201
|
+
} = callbacks;
|
|
198
202
|
if (!core.commons.isWalletSignRequestMetadata(metadata)) {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
// Queue the request first, this method only does that
|
|
202
|
-
// the requesting to the API is later handled on every status change
|
|
203
|
-
this.requests.set(id, callbacks);
|
|
203
|
+
onRejection('expected sequence signature request metadata');
|
|
204
|
+
return false;
|
|
204
205
|
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
206
|
+
try {
|
|
207
|
+
var _metadata$parts;
|
|
208
|
+
const guardTotpCode = metadata.guardTotpCode;
|
|
209
|
+
|
|
210
|
+
// Building auxData, notice: this uses the old v1 format
|
|
211
|
+
// TODO: We should update the guard API so we can pass the metadata directly
|
|
212
|
+
const coder = core.universal.genericCoderFor(metadata.config.version);
|
|
213
|
+
const {
|
|
214
|
+
encoded
|
|
215
|
+
} = coder.signature.encodeSigners(metadata.config, (_metadata$parts = metadata.parts) != null ? _metadata$parts : new Map(), [], metadata.chainId);
|
|
216
|
+
const {
|
|
217
|
+
sig: signature
|
|
218
|
+
} = await this.guard.signWith({
|
|
219
|
+
signer: this.address,
|
|
220
|
+
request: {
|
|
221
|
+
msg: ethers.ethers.utils.hexlify(message),
|
|
222
|
+
auxData: this.packMsgAndSig(metadata.address, metadata.digest, encoded, metadata.chainId),
|
|
223
|
+
chainId: ethers.ethers.BigNumber.from(metadata.chainId).toNumber()
|
|
224
|
+
},
|
|
225
|
+
token: guardTotpCode ? {
|
|
226
|
+
id: AuthMethod.TOTP,
|
|
227
|
+
token: guardTotpCode
|
|
228
|
+
} : undefined
|
|
229
|
+
});
|
|
230
|
+
if (ethers.ethers.utils.arrayify(signature).length === 0) {
|
|
231
|
+
throw new Error('guard response contained no signature data');
|
|
232
|
+
}
|
|
233
|
+
onSignature(signature);
|
|
234
|
+
return true;
|
|
235
|
+
} catch (error) {
|
|
236
|
+
onRejection(`unable to request guard signature: ${error}`);
|
|
237
|
+
return false;
|
|
212
238
|
}
|
|
213
|
-
this.evaluateRequest(id, status.message, status, metadata);
|
|
214
239
|
}
|
|
240
|
+
notifyStatusChange(_id, _status, _metadata) {}
|
|
215
241
|
async getAuthMethods(token) {
|
|
216
242
|
let response;
|
|
217
243
|
if ('jwt' in token) {
|
|
@@ -263,11 +289,14 @@ class GuardSigner {
|
|
|
263
289
|
return new URL(uri);
|
|
264
290
|
}
|
|
265
291
|
async commitTotp(token, jwt) {
|
|
266
|
-
|
|
292
|
+
const {
|
|
293
|
+
codes
|
|
294
|
+
} = await this.guard.commitTOTP({
|
|
267
295
|
token
|
|
268
296
|
}, {
|
|
269
297
|
Authorization: `BEARER ${jwt}`
|
|
270
298
|
});
|
|
299
|
+
return codes;
|
|
271
300
|
}
|
|
272
301
|
async resetTotp(token) {
|
|
273
302
|
const signedToken = await signUpdateAuthMethodToken(token);
|
|
@@ -281,50 +310,6 @@ class GuardSigner {
|
|
|
281
310
|
packMsgAndSig(address, msg, sig, chainId) {
|
|
282
311
|
return ethers.ethers.utils.defaultAbiCoder.encode(['address', 'uint256', 'bytes', 'bytes'], [address, chainId, msg, sig]);
|
|
283
312
|
}
|
|
284
|
-
keyOfRequest(signer, msg, auxData, chainId) {
|
|
285
|
-
return ethers.ethers.utils.solidityKeccak256(['address', 'uint256', 'bytes', 'bytes'], [signer, chainId, msg, auxData]);
|
|
286
|
-
}
|
|
287
|
-
async evaluateRequest(id, message, _, metadata) {
|
|
288
|
-
var _metadata$parts;
|
|
289
|
-
// Building auxData, notice: this uses the old v1 format
|
|
290
|
-
// TODO: We should update the guard API so we can pass the metadata directly
|
|
291
|
-
const coder = core.universal.genericCoderFor(metadata.config.version);
|
|
292
|
-
const {
|
|
293
|
-
encoded
|
|
294
|
-
} = coder.signature.encodeSigners(metadata.config, (_metadata$parts = metadata.parts) != null ? _metadata$parts : new Map(), [], metadata.chainId);
|
|
295
|
-
try {
|
|
296
|
-
var _this$requests$get;
|
|
297
|
-
const key = this.keyOfRequest(this.address, message, encoded, metadata.chainId);
|
|
298
|
-
const lastAttempt = (_this$requests$get = this.requests.get(id)) == null ? void 0 : _this$requests$get.lastAttempt;
|
|
299
|
-
if (lastAttempt === key) {
|
|
300
|
-
return;
|
|
301
|
-
}
|
|
302
|
-
this.requests.get(id).lastAttempt = key;
|
|
303
|
-
const result = await this.guard.signWith({
|
|
304
|
-
signer: this.address,
|
|
305
|
-
request: {
|
|
306
|
-
msg: ethers.ethers.utils.hexlify(message),
|
|
307
|
-
auxData: this.packMsgAndSig(metadata.address, metadata.digest, encoded, metadata.chainId),
|
|
308
|
-
chainId: ethers.ethers.BigNumber.from(metadata.chainId).toNumber() // TODO: This should be a string (in the API)
|
|
309
|
-
},
|
|
310
|
-
|
|
311
|
-
token: metadata.guardTotpCode ? {
|
|
312
|
-
id: AuthMethod.TOTP,
|
|
313
|
-
token: metadata.guardTotpCode
|
|
314
|
-
} : undefined
|
|
315
|
-
});
|
|
316
|
-
if (ethers.ethers.utils.arrayify(result.sig).length !== 0) {
|
|
317
|
-
this.requests.get(id).onSignature(result.sig);
|
|
318
|
-
this.requests.delete(id);
|
|
319
|
-
}
|
|
320
|
-
} catch (e) {
|
|
321
|
-
var _this$onError;
|
|
322
|
-
// The guard signer may reject the request for a number of reasons
|
|
323
|
-
// like for example, if it's being the first signer (it waits for other signers to sign first)
|
|
324
|
-
// We always forward the error here and filter on client side.
|
|
325
|
-
(_this$onError = this.onError) == null ? void 0 : _this$onError.call(this, e);
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
313
|
suffix() {
|
|
329
314
|
return this.appendSuffix ? [3] : [];
|
|
330
315
|
}
|
|
@@ -21,7 +21,7 @@ function _extends() {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
/* eslint-disable */
|
|
24
|
-
// sequence-guard v0.4.0
|
|
24
|
+
// sequence-guard v0.4.0 af5ad0623aec0b231a462052edaea1823f620a1e
|
|
25
25
|
// --
|
|
26
26
|
// Code generated by webrpc-gen@v0.12.x-dev with typescript@v0.10.0 generator. DO NOT EDIT.
|
|
27
27
|
//
|
|
@@ -34,7 +34,7 @@ const WebRPCVersion = 'v1';
|
|
|
34
34
|
const WebRPCSchemaVersion = 'v0.4.0';
|
|
35
35
|
|
|
36
36
|
// Schema hash generated from your RIDL schema
|
|
37
|
-
const WebRPCSchemaHash = '
|
|
37
|
+
const WebRPCSchemaHash = 'af5ad0623aec0b231a462052edaea1823f620a1e';
|
|
38
38
|
|
|
39
39
|
//
|
|
40
40
|
// Types
|
|
@@ -134,7 +134,9 @@ class Guard {
|
|
|
134
134
|
this.commitTOTP = (args, headers) => {
|
|
135
135
|
return this.fetch(this.url('CommitTOTP'), createHTTPRequest(args, headers)).then(res => {
|
|
136
136
|
return buildResponse(res).then(_data => {
|
|
137
|
-
return {
|
|
137
|
+
return {
|
|
138
|
+
codes: _data.codes
|
|
139
|
+
};
|
|
138
140
|
});
|
|
139
141
|
});
|
|
140
142
|
};
|
|
@@ -183,35 +185,59 @@ const buildResponse = res => {
|
|
|
183
185
|
|
|
184
186
|
const fetch = typeof global === 'object' ? global.fetch : window.fetch;
|
|
185
187
|
class GuardSigner {
|
|
186
|
-
constructor(address, url, appendSuffix = false
|
|
187
|
-
this.requests = new Map();
|
|
188
|
+
constructor(address, url, appendSuffix = false) {
|
|
188
189
|
this.address = address;
|
|
189
190
|
this.url = url;
|
|
190
191
|
this.appendSuffix = appendSuffix;
|
|
191
|
-
this.onError = onError;
|
|
192
192
|
this.guard = new Guard(url, fetch);
|
|
193
193
|
}
|
|
194
194
|
async getAddress() {
|
|
195
195
|
return this.address;
|
|
196
196
|
}
|
|
197
|
-
async requestSignature(
|
|
197
|
+
async requestSignature(_id, message, metadata, callbacks) {
|
|
198
|
+
const {
|
|
199
|
+
onSignature,
|
|
200
|
+
onRejection
|
|
201
|
+
} = callbacks;
|
|
198
202
|
if (!core.commons.isWalletSignRequestMetadata(metadata)) {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
// Queue the request first, this method only does that
|
|
202
|
-
// the requesting to the API is later handled on every status change
|
|
203
|
-
this.requests.set(id, callbacks);
|
|
203
|
+
onRejection('expected sequence signature request metadata');
|
|
204
|
+
return false;
|
|
204
205
|
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
206
|
+
try {
|
|
207
|
+
var _metadata$parts;
|
|
208
|
+
const guardTotpCode = metadata.guardTotpCode;
|
|
209
|
+
|
|
210
|
+
// Building auxData, notice: this uses the old v1 format
|
|
211
|
+
// TODO: We should update the guard API so we can pass the metadata directly
|
|
212
|
+
const coder = core.universal.genericCoderFor(metadata.config.version);
|
|
213
|
+
const {
|
|
214
|
+
encoded
|
|
215
|
+
} = coder.signature.encodeSigners(metadata.config, (_metadata$parts = metadata.parts) != null ? _metadata$parts : new Map(), [], metadata.chainId);
|
|
216
|
+
const {
|
|
217
|
+
sig: signature
|
|
218
|
+
} = await this.guard.signWith({
|
|
219
|
+
signer: this.address,
|
|
220
|
+
request: {
|
|
221
|
+
msg: ethers.ethers.utils.hexlify(message),
|
|
222
|
+
auxData: this.packMsgAndSig(metadata.address, metadata.digest, encoded, metadata.chainId),
|
|
223
|
+
chainId: ethers.ethers.BigNumber.from(metadata.chainId).toNumber()
|
|
224
|
+
},
|
|
225
|
+
token: guardTotpCode ? {
|
|
226
|
+
id: AuthMethod.TOTP,
|
|
227
|
+
token: guardTotpCode
|
|
228
|
+
} : undefined
|
|
229
|
+
});
|
|
230
|
+
if (ethers.ethers.utils.arrayify(signature).length === 0) {
|
|
231
|
+
throw new Error('guard response contained no signature data');
|
|
232
|
+
}
|
|
233
|
+
onSignature(signature);
|
|
234
|
+
return true;
|
|
235
|
+
} catch (error) {
|
|
236
|
+
onRejection(`unable to request guard signature: ${error}`);
|
|
237
|
+
return false;
|
|
212
238
|
}
|
|
213
|
-
this.evaluateRequest(id, status.message, status, metadata);
|
|
214
239
|
}
|
|
240
|
+
notifyStatusChange(_id, _status, _metadata) {}
|
|
215
241
|
async getAuthMethods(token) {
|
|
216
242
|
let response;
|
|
217
243
|
if ('jwt' in token) {
|
|
@@ -263,11 +289,14 @@ class GuardSigner {
|
|
|
263
289
|
return new URL(uri);
|
|
264
290
|
}
|
|
265
291
|
async commitTotp(token, jwt) {
|
|
266
|
-
|
|
292
|
+
const {
|
|
293
|
+
codes
|
|
294
|
+
} = await this.guard.commitTOTP({
|
|
267
295
|
token
|
|
268
296
|
}, {
|
|
269
297
|
Authorization: `BEARER ${jwt}`
|
|
270
298
|
});
|
|
299
|
+
return codes;
|
|
271
300
|
}
|
|
272
301
|
async resetTotp(token) {
|
|
273
302
|
const signedToken = await signUpdateAuthMethodToken(token);
|
|
@@ -281,50 +310,6 @@ class GuardSigner {
|
|
|
281
310
|
packMsgAndSig(address, msg, sig, chainId) {
|
|
282
311
|
return ethers.ethers.utils.defaultAbiCoder.encode(['address', 'uint256', 'bytes', 'bytes'], [address, chainId, msg, sig]);
|
|
283
312
|
}
|
|
284
|
-
keyOfRequest(signer, msg, auxData, chainId) {
|
|
285
|
-
return ethers.ethers.utils.solidityKeccak256(['address', 'uint256', 'bytes', 'bytes'], [signer, chainId, msg, auxData]);
|
|
286
|
-
}
|
|
287
|
-
async evaluateRequest(id, message, _, metadata) {
|
|
288
|
-
var _metadata$parts;
|
|
289
|
-
// Building auxData, notice: this uses the old v1 format
|
|
290
|
-
// TODO: We should update the guard API so we can pass the metadata directly
|
|
291
|
-
const coder = core.universal.genericCoderFor(metadata.config.version);
|
|
292
|
-
const {
|
|
293
|
-
encoded
|
|
294
|
-
} = coder.signature.encodeSigners(metadata.config, (_metadata$parts = metadata.parts) != null ? _metadata$parts : new Map(), [], metadata.chainId);
|
|
295
|
-
try {
|
|
296
|
-
var _this$requests$get;
|
|
297
|
-
const key = this.keyOfRequest(this.address, message, encoded, metadata.chainId);
|
|
298
|
-
const lastAttempt = (_this$requests$get = this.requests.get(id)) == null ? void 0 : _this$requests$get.lastAttempt;
|
|
299
|
-
if (lastAttempt === key) {
|
|
300
|
-
return;
|
|
301
|
-
}
|
|
302
|
-
this.requests.get(id).lastAttempt = key;
|
|
303
|
-
const result = await this.guard.signWith({
|
|
304
|
-
signer: this.address,
|
|
305
|
-
request: {
|
|
306
|
-
msg: ethers.ethers.utils.hexlify(message),
|
|
307
|
-
auxData: this.packMsgAndSig(metadata.address, metadata.digest, encoded, metadata.chainId),
|
|
308
|
-
chainId: ethers.ethers.BigNumber.from(metadata.chainId).toNumber() // TODO: This should be a string (in the API)
|
|
309
|
-
},
|
|
310
|
-
|
|
311
|
-
token: metadata.guardTotpCode ? {
|
|
312
|
-
id: AuthMethod.TOTP,
|
|
313
|
-
token: metadata.guardTotpCode
|
|
314
|
-
} : undefined
|
|
315
|
-
});
|
|
316
|
-
if (ethers.ethers.utils.arrayify(result.sig).length !== 0) {
|
|
317
|
-
this.requests.get(id).onSignature(result.sig);
|
|
318
|
-
this.requests.delete(id);
|
|
319
|
-
}
|
|
320
|
-
} catch (e) {
|
|
321
|
-
var _this$onError;
|
|
322
|
-
// The guard signer may reject the request for a number of reasons
|
|
323
|
-
// like for example, if it's being the first signer (it waits for other signers to sign first)
|
|
324
|
-
// We always forward the error here and filter on client side.
|
|
325
|
-
(_this$onError = this.onError) == null ? void 0 : _this$onError.call(this, e);
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
313
|
suffix() {
|
|
329
314
|
return this.appendSuffix ? [3] : [];
|
|
330
315
|
}
|
|
@@ -17,7 +17,7 @@ function _extends() {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
/* eslint-disable */
|
|
20
|
-
// sequence-guard v0.4.0
|
|
20
|
+
// sequence-guard v0.4.0 af5ad0623aec0b231a462052edaea1823f620a1e
|
|
21
21
|
// --
|
|
22
22
|
// Code generated by webrpc-gen@v0.12.x-dev with typescript@v0.10.0 generator. DO NOT EDIT.
|
|
23
23
|
//
|
|
@@ -30,7 +30,7 @@ const WebRPCVersion = 'v1';
|
|
|
30
30
|
const WebRPCSchemaVersion = 'v0.4.0';
|
|
31
31
|
|
|
32
32
|
// Schema hash generated from your RIDL schema
|
|
33
|
-
const WebRPCSchemaHash = '
|
|
33
|
+
const WebRPCSchemaHash = 'af5ad0623aec0b231a462052edaea1823f620a1e';
|
|
34
34
|
|
|
35
35
|
//
|
|
36
36
|
// Types
|
|
@@ -130,7 +130,9 @@ class Guard {
|
|
|
130
130
|
this.commitTOTP = (args, headers) => {
|
|
131
131
|
return this.fetch(this.url('CommitTOTP'), createHTTPRequest(args, headers)).then(res => {
|
|
132
132
|
return buildResponse(res).then(_data => {
|
|
133
|
-
return {
|
|
133
|
+
return {
|
|
134
|
+
codes: _data.codes
|
|
135
|
+
};
|
|
134
136
|
});
|
|
135
137
|
});
|
|
136
138
|
};
|
|
@@ -179,35 +181,59 @@ const buildResponse = res => {
|
|
|
179
181
|
|
|
180
182
|
const fetch = typeof global === 'object' ? global.fetch : window.fetch;
|
|
181
183
|
class GuardSigner {
|
|
182
|
-
constructor(address, url, appendSuffix = false
|
|
183
|
-
this.requests = new Map();
|
|
184
|
+
constructor(address, url, appendSuffix = false) {
|
|
184
185
|
this.address = address;
|
|
185
186
|
this.url = url;
|
|
186
187
|
this.appendSuffix = appendSuffix;
|
|
187
|
-
this.onError = onError;
|
|
188
188
|
this.guard = new Guard(url, fetch);
|
|
189
189
|
}
|
|
190
190
|
async getAddress() {
|
|
191
191
|
return this.address;
|
|
192
192
|
}
|
|
193
|
-
async requestSignature(
|
|
193
|
+
async requestSignature(_id, message, metadata, callbacks) {
|
|
194
|
+
const {
|
|
195
|
+
onSignature,
|
|
196
|
+
onRejection
|
|
197
|
+
} = callbacks;
|
|
194
198
|
if (!commons.isWalletSignRequestMetadata(metadata)) {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
// Queue the request first, this method only does that
|
|
198
|
-
// the requesting to the API is later handled on every status change
|
|
199
|
-
this.requests.set(id, callbacks);
|
|
199
|
+
onRejection('expected sequence signature request metadata');
|
|
200
|
+
return false;
|
|
200
201
|
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
202
|
+
try {
|
|
203
|
+
var _metadata$parts;
|
|
204
|
+
const guardTotpCode = metadata.guardTotpCode;
|
|
205
|
+
|
|
206
|
+
// Building auxData, notice: this uses the old v1 format
|
|
207
|
+
// TODO: We should update the guard API so we can pass the metadata directly
|
|
208
|
+
const coder = universal.genericCoderFor(metadata.config.version);
|
|
209
|
+
const {
|
|
210
|
+
encoded
|
|
211
|
+
} = coder.signature.encodeSigners(metadata.config, (_metadata$parts = metadata.parts) != null ? _metadata$parts : new Map(), [], metadata.chainId);
|
|
212
|
+
const {
|
|
213
|
+
sig: signature
|
|
214
|
+
} = await this.guard.signWith({
|
|
215
|
+
signer: this.address,
|
|
216
|
+
request: {
|
|
217
|
+
msg: ethers.utils.hexlify(message),
|
|
218
|
+
auxData: this.packMsgAndSig(metadata.address, metadata.digest, encoded, metadata.chainId),
|
|
219
|
+
chainId: ethers.BigNumber.from(metadata.chainId).toNumber()
|
|
220
|
+
},
|
|
221
|
+
token: guardTotpCode ? {
|
|
222
|
+
id: AuthMethod.TOTP,
|
|
223
|
+
token: guardTotpCode
|
|
224
|
+
} : undefined
|
|
225
|
+
});
|
|
226
|
+
if (ethers.utils.arrayify(signature).length === 0) {
|
|
227
|
+
throw new Error('guard response contained no signature data');
|
|
228
|
+
}
|
|
229
|
+
onSignature(signature);
|
|
230
|
+
return true;
|
|
231
|
+
} catch (error) {
|
|
232
|
+
onRejection(`unable to request guard signature: ${error}`);
|
|
233
|
+
return false;
|
|
208
234
|
}
|
|
209
|
-
this.evaluateRequest(id, status.message, status, metadata);
|
|
210
235
|
}
|
|
236
|
+
notifyStatusChange(_id, _status, _metadata) {}
|
|
211
237
|
async getAuthMethods(token) {
|
|
212
238
|
let response;
|
|
213
239
|
if ('jwt' in token) {
|
|
@@ -259,11 +285,14 @@ class GuardSigner {
|
|
|
259
285
|
return new URL(uri);
|
|
260
286
|
}
|
|
261
287
|
async commitTotp(token, jwt) {
|
|
262
|
-
|
|
288
|
+
const {
|
|
289
|
+
codes
|
|
290
|
+
} = await this.guard.commitTOTP({
|
|
263
291
|
token
|
|
264
292
|
}, {
|
|
265
293
|
Authorization: `BEARER ${jwt}`
|
|
266
294
|
});
|
|
295
|
+
return codes;
|
|
267
296
|
}
|
|
268
297
|
async resetTotp(token) {
|
|
269
298
|
const signedToken = await signUpdateAuthMethodToken(token);
|
|
@@ -277,50 +306,6 @@ class GuardSigner {
|
|
|
277
306
|
packMsgAndSig(address, msg, sig, chainId) {
|
|
278
307
|
return ethers.utils.defaultAbiCoder.encode(['address', 'uint256', 'bytes', 'bytes'], [address, chainId, msg, sig]);
|
|
279
308
|
}
|
|
280
|
-
keyOfRequest(signer, msg, auxData, chainId) {
|
|
281
|
-
return ethers.utils.solidityKeccak256(['address', 'uint256', 'bytes', 'bytes'], [signer, chainId, msg, auxData]);
|
|
282
|
-
}
|
|
283
|
-
async evaluateRequest(id, message, _, metadata) {
|
|
284
|
-
var _metadata$parts;
|
|
285
|
-
// Building auxData, notice: this uses the old v1 format
|
|
286
|
-
// TODO: We should update the guard API so we can pass the metadata directly
|
|
287
|
-
const coder = universal.genericCoderFor(metadata.config.version);
|
|
288
|
-
const {
|
|
289
|
-
encoded
|
|
290
|
-
} = coder.signature.encodeSigners(metadata.config, (_metadata$parts = metadata.parts) != null ? _metadata$parts : new Map(), [], metadata.chainId);
|
|
291
|
-
try {
|
|
292
|
-
var _this$requests$get;
|
|
293
|
-
const key = this.keyOfRequest(this.address, message, encoded, metadata.chainId);
|
|
294
|
-
const lastAttempt = (_this$requests$get = this.requests.get(id)) == null ? void 0 : _this$requests$get.lastAttempt;
|
|
295
|
-
if (lastAttempt === key) {
|
|
296
|
-
return;
|
|
297
|
-
}
|
|
298
|
-
this.requests.get(id).lastAttempt = key;
|
|
299
|
-
const result = await this.guard.signWith({
|
|
300
|
-
signer: this.address,
|
|
301
|
-
request: {
|
|
302
|
-
msg: ethers.utils.hexlify(message),
|
|
303
|
-
auxData: this.packMsgAndSig(metadata.address, metadata.digest, encoded, metadata.chainId),
|
|
304
|
-
chainId: ethers.BigNumber.from(metadata.chainId).toNumber() // TODO: This should be a string (in the API)
|
|
305
|
-
},
|
|
306
|
-
|
|
307
|
-
token: metadata.guardTotpCode ? {
|
|
308
|
-
id: AuthMethod.TOTP,
|
|
309
|
-
token: metadata.guardTotpCode
|
|
310
|
-
} : undefined
|
|
311
|
-
});
|
|
312
|
-
if (ethers.utils.arrayify(result.sig).length !== 0) {
|
|
313
|
-
this.requests.get(id).onSignature(result.sig);
|
|
314
|
-
this.requests.delete(id);
|
|
315
|
-
}
|
|
316
|
-
} catch (e) {
|
|
317
|
-
var _this$onError;
|
|
318
|
-
// The guard signer may reject the request for a number of reasons
|
|
319
|
-
// like for example, if it's being the first signer (it waits for other signers to sign first)
|
|
320
|
-
// We always forward the error here and filter on client side.
|
|
321
|
-
(_this$onError = this.onError) == null ? void 0 : _this$onError.call(this, e);
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
309
|
suffix() {
|
|
325
310
|
return this.appendSuffix ? [3] : [];
|
|
326
311
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export declare const WebRPCVersion = "v1";
|
|
2
2
|
export declare const WebRPCSchemaVersion = "v0.4.0";
|
|
3
|
-
export declare const WebRPCSchemaHash = "
|
|
3
|
+
export declare const WebRPCSchemaHash = "af5ad0623aec0b231a462052edaea1823f620a1e";
|
|
4
4
|
export interface Version {
|
|
5
5
|
webrpcVersion: string;
|
|
6
6
|
schemaVersion: string;
|
|
@@ -38,6 +38,10 @@ export interface AuthToken {
|
|
|
38
38
|
id: string;
|
|
39
39
|
token: string;
|
|
40
40
|
}
|
|
41
|
+
export interface RecoveryCode {
|
|
42
|
+
code: string;
|
|
43
|
+
used: boolean;
|
|
44
|
+
}
|
|
41
45
|
export interface Guard {
|
|
42
46
|
ping(headers?: object): Promise<PingReturn>;
|
|
43
47
|
version(headers?: object): Promise<VersionReturn>;
|
|
@@ -118,6 +122,7 @@ export interface CommitTOTPArgs {
|
|
|
118
122
|
token: string;
|
|
119
123
|
}
|
|
120
124
|
export interface CommitTOTPReturn {
|
|
125
|
+
codes: Array<RecoveryCode>;
|
|
121
126
|
}
|
|
122
127
|
export interface ResetTOTPArgs {
|
|
123
128
|
timestamp: number;
|
|
@@ -2,30 +2,27 @@ import { Account } from '@0xsequence/account';
|
|
|
2
2
|
import { signers, Status } from '@0xsequence/signhub';
|
|
3
3
|
import { TypedData } from '@0xsequence/utils';
|
|
4
4
|
import { BytesLike, ethers } from 'ethers';
|
|
5
|
+
import { RecoveryCode } from "./guard.gen.js";
|
|
5
6
|
export declare class GuardSigner implements signers.SapientSigner {
|
|
6
7
|
readonly address: string;
|
|
7
8
|
readonly url: string;
|
|
8
9
|
readonly appendSuffix: boolean;
|
|
9
|
-
private readonly onError?;
|
|
10
10
|
private guard;
|
|
11
|
-
|
|
12
|
-
constructor(address: string, url: string, appendSuffix?: boolean, onError?: ((err: Error) => void) | undefined);
|
|
11
|
+
constructor(address: string, url: string, appendSuffix?: boolean);
|
|
13
12
|
getAddress(): Promise<string>;
|
|
14
|
-
requestSignature(
|
|
13
|
+
requestSignature(_id: string, message: BytesLike, metadata: Object, callbacks: {
|
|
15
14
|
onSignature: (signature: BytesLike) => void;
|
|
16
15
|
onRejection: (error: string) => void;
|
|
17
16
|
onStatus: (situation: string) => void;
|
|
18
17
|
}): Promise<boolean>;
|
|
19
|
-
notifyStatusChange(
|
|
18
|
+
notifyStatusChange(_id: string, _status: Status, _metadata: Object): void;
|
|
20
19
|
getAuthMethods(token: GetAuthMethodsToken): Promise<AuthMethod[]>;
|
|
21
20
|
setPin(pin: string | undefined, token: UpdateAuthMethodToken): Promise<void>;
|
|
22
21
|
resetPin(token: UpdateAuthMethodToken): Promise<void>;
|
|
23
22
|
createTotp(token: UpdateAuthMethodToken): Promise<URL>;
|
|
24
|
-
commitTotp(token: string, jwt: string): Promise<
|
|
23
|
+
commitTotp(token: string, jwt: string): Promise<RecoveryCode[]>;
|
|
25
24
|
resetTotp(token: UpdateAuthMethodToken): Promise<void>;
|
|
26
25
|
private packMsgAndSig;
|
|
27
|
-
private keyOfRequest;
|
|
28
|
-
private evaluateRequest;
|
|
29
26
|
suffix(): BytesLike;
|
|
30
27
|
}
|
|
31
28
|
export declare enum AuthMethod {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@0xsequence/guard",
|
|
3
|
-
"version": "0.0.0-
|
|
3
|
+
"version": "0.0.0-20231102200515",
|
|
4
4
|
"description": "guard sub-package for Sequence",
|
|
5
5
|
"repository": "https://github.com/0xsequence/sequence.js/tree/master/packages/guard",
|
|
6
6
|
"source": "src/index.ts",
|
|
@@ -10,10 +10,10 @@
|
|
|
10
10
|
"license": "Apache-2.0",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"ethers": "^5.7.2",
|
|
13
|
-
"@0xsequence/account": "0.0.0-
|
|
14
|
-
"@0xsequence/
|
|
15
|
-
"@0xsequence/
|
|
16
|
-
"@0xsequence/
|
|
13
|
+
"@0xsequence/account": "0.0.0-20231102200515",
|
|
14
|
+
"@0xsequence/core": "0.0.0-20231102200515",
|
|
15
|
+
"@0xsequence/utils": "0.0.0-20231102200515",
|
|
16
|
+
"@0xsequence/signhub": "0.0.0-20231102200515"
|
|
17
17
|
},
|
|
18
18
|
"files": [
|
|
19
19
|
"src",
|
package/src/guard.gen.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* eslint-disable */
|
|
2
|
-
// sequence-guard v0.4.0
|
|
2
|
+
// sequence-guard v0.4.0 af5ad0623aec0b231a462052edaea1823f620a1e
|
|
3
3
|
// --
|
|
4
4
|
// Code generated by webrpc-gen@v0.12.x-dev with typescript@v0.10.0 generator. DO NOT EDIT.
|
|
5
5
|
//
|
|
@@ -12,7 +12,7 @@ export const WebRPCVersion = 'v1'
|
|
|
12
12
|
export const WebRPCSchemaVersion = 'v0.4.0'
|
|
13
13
|
|
|
14
14
|
// Schema hash generated from your RIDL schema
|
|
15
|
-
export const WebRPCSchemaHash = '
|
|
15
|
+
export const WebRPCSchemaHash = 'af5ad0623aec0b231a462052edaea1823f620a1e'
|
|
16
16
|
|
|
17
17
|
//
|
|
18
18
|
// Types
|
|
@@ -62,6 +62,11 @@ export interface AuthToken {
|
|
|
62
62
|
token: string
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
+
export interface RecoveryCode {
|
|
66
|
+
code: string
|
|
67
|
+
used: boolean
|
|
68
|
+
}
|
|
69
|
+
|
|
65
70
|
export interface Guard {
|
|
66
71
|
ping(headers?: object): Promise<PingReturn>
|
|
67
72
|
version(headers?: object): Promise<VersionReturn>
|
|
@@ -148,7 +153,9 @@ export interface CommitTOTPArgs {
|
|
|
148
153
|
token: string
|
|
149
154
|
}
|
|
150
155
|
|
|
151
|
-
export interface CommitTOTPReturn {
|
|
156
|
+
export interface CommitTOTPReturn {
|
|
157
|
+
codes: Array<RecoveryCode>
|
|
158
|
+
}
|
|
152
159
|
export interface ResetTOTPArgs {
|
|
153
160
|
timestamp: number
|
|
154
161
|
signature: string
|
|
@@ -272,7 +279,9 @@ export class Guard implements Guard {
|
|
|
272
279
|
commitTOTP = (args: CommitTOTPArgs, headers?: object): Promise<CommitTOTPReturn> => {
|
|
273
280
|
return this.fetch(this.url('CommitTOTP'), createHTTPRequest(args, headers)).then(res => {
|
|
274
281
|
return buildResponse(res).then(_data => {
|
|
275
|
-
return {
|
|
282
|
+
return {
|
|
283
|
+
codes: <Array<RecoveryCode>>_data.codes
|
|
284
|
+
}
|
|
276
285
|
})
|
|
277
286
|
})
|
|
278
287
|
}
|
package/src/signer.ts
CHANGED
|
@@ -3,27 +3,17 @@ import { commons, universal } from '@0xsequence/core'
|
|
|
3
3
|
import { signers, Status } from '@0xsequence/signhub'
|
|
4
4
|
import { TypedData } from '@0xsequence/utils'
|
|
5
5
|
import { BytesLike, ethers, TypedDataDomain } from 'ethers'
|
|
6
|
-
import { AuthMethodsReturn, Guard } from './guard.gen'
|
|
6
|
+
import { AuthMethodsReturn, Guard, RecoveryCode } from './guard.gen'
|
|
7
7
|
|
|
8
8
|
const fetch = typeof global === 'object' ? global.fetch : window.fetch
|
|
9
9
|
|
|
10
10
|
export class GuardSigner implements signers.SapientSigner {
|
|
11
11
|
private guard: Guard
|
|
12
|
-
private requests: Map<
|
|
13
|
-
string,
|
|
14
|
-
{
|
|
15
|
-
lastAttempt?: string
|
|
16
|
-
onSignature: (signature: BytesLike) => void
|
|
17
|
-
onRejection: (error: string) => void
|
|
18
|
-
onStatus: (situation: string) => void
|
|
19
|
-
}
|
|
20
|
-
> = new Map()
|
|
21
12
|
|
|
22
13
|
constructor(
|
|
23
14
|
public readonly address: string,
|
|
24
15
|
public readonly url: string,
|
|
25
16
|
public readonly appendSuffix: boolean = false,
|
|
26
|
-
private readonly onError?: (err: Error) => void
|
|
27
17
|
) {
|
|
28
18
|
this.guard = new Guard(url, fetch)
|
|
29
19
|
}
|
|
@@ -33,8 +23,8 @@ export class GuardSigner implements signers.SapientSigner {
|
|
|
33
23
|
}
|
|
34
24
|
|
|
35
25
|
async requestSignature(
|
|
36
|
-
|
|
37
|
-
|
|
26
|
+
_id: string,
|
|
27
|
+
message: BytesLike,
|
|
38
28
|
metadata: Object,
|
|
39
29
|
callbacks: {
|
|
40
30
|
onSignature: (signature: BytesLike) => void
|
|
@@ -42,26 +32,44 @@ export class GuardSigner implements signers.SapientSigner {
|
|
|
42
32
|
onStatus: (situation: string) => void
|
|
43
33
|
}
|
|
44
34
|
): Promise<boolean> {
|
|
35
|
+
const { onSignature, onRejection } = callbacks
|
|
36
|
+
|
|
45
37
|
if (!commons.isWalletSignRequestMetadata(metadata)) {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
// Queue the request first, this method only does that
|
|
49
|
-
// the requesting to the API is later handled on every status change
|
|
50
|
-
this.requests.set(id, callbacks)
|
|
38
|
+
onRejection('expected sequence signature request metadata')
|
|
39
|
+
return false
|
|
51
40
|
}
|
|
52
41
|
|
|
53
|
-
|
|
54
|
-
|
|
42
|
+
try {
|
|
43
|
+
const guardTotpCode = (metadata as { guardTotpCode?: string }).guardTotpCode
|
|
55
44
|
|
|
56
|
-
|
|
57
|
-
|
|
45
|
+
// Building auxData, notice: this uses the old v1 format
|
|
46
|
+
// TODO: We should update the guard API so we can pass the metadata directly
|
|
47
|
+
const coder = universal.genericCoderFor(metadata.config.version)
|
|
48
|
+
const { encoded } = coder.signature.encodeSigners(metadata.config, metadata.parts ?? new Map(), [], metadata.chainId)
|
|
58
49
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
50
|
+
const { sig: signature } = await this.guard.signWith({
|
|
51
|
+
signer: this.address,
|
|
52
|
+
request: {
|
|
53
|
+
msg: ethers.utils.hexlify(message),
|
|
54
|
+
auxData: this.packMsgAndSig(metadata.address, metadata.digest, encoded, metadata.chainId),
|
|
55
|
+
chainId: ethers.BigNumber.from(metadata.chainId).toNumber()
|
|
56
|
+
},
|
|
57
|
+
token: guardTotpCode ? { id: AuthMethod.TOTP, token: guardTotpCode } : undefined
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
if (ethers.utils.arrayify(signature).length === 0) {
|
|
61
|
+
throw new Error('guard response contained no signature data')
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
onSignature(signature)
|
|
65
|
+
return true
|
|
66
|
+
} catch (error) {
|
|
67
|
+
onRejection(`unable to request guard signature: ${error}`)
|
|
68
|
+
return false
|
|
62
69
|
}
|
|
70
|
+
}
|
|
63
71
|
|
|
64
|
-
|
|
72
|
+
notifyStatusChange(_id: string, _status: Status, _metadata: Object): void {
|
|
65
73
|
}
|
|
66
74
|
|
|
67
75
|
async getAuthMethods(token: GetAuthMethodsToken): Promise<AuthMethod[]> {
|
|
@@ -108,8 +116,9 @@ export class GuardSigner implements signers.SapientSigner {
|
|
|
108
116
|
return new URL(uri)
|
|
109
117
|
}
|
|
110
118
|
|
|
111
|
-
async commitTotp(token: string, jwt: string): Promise<
|
|
112
|
-
await this.guard.commitTOTP({ token }, { Authorization: `BEARER ${jwt}` })
|
|
119
|
+
async commitTotp(token: string, jwt: string): Promise<RecoveryCode[]> {
|
|
120
|
+
const { codes } = await this.guard.commitTOTP({ token }, { Authorization: `BEARER ${jwt}` })
|
|
121
|
+
return codes
|
|
113
122
|
}
|
|
114
123
|
|
|
115
124
|
async resetTotp(token: UpdateAuthMethodToken): Promise<void> {
|
|
@@ -125,57 +134,6 @@ export class GuardSigner implements signers.SapientSigner {
|
|
|
125
134
|
return ethers.utils.defaultAbiCoder.encode(['address', 'uint256', 'bytes', 'bytes'], [address, chainId, msg, sig])
|
|
126
135
|
}
|
|
127
136
|
|
|
128
|
-
private keyOfRequest(signer: string, msg: BytesLike, auxData: BytesLike, chainId: ethers.BigNumberish): string {
|
|
129
|
-
return ethers.utils.solidityKeccak256(['address', 'uint256', 'bytes', 'bytes'], [signer, chainId, msg, auxData])
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
private async evaluateRequest(
|
|
133
|
-
id: string,
|
|
134
|
-
message: BytesLike,
|
|
135
|
-
_: Status,
|
|
136
|
-
metadata: commons.WalletSignRequestMetadata & { guardTotpCode?: string }
|
|
137
|
-
): Promise<void> {
|
|
138
|
-
// Building auxData, notice: this uses the old v1 format
|
|
139
|
-
// TODO: We should update the guard API so we can pass the metadata directly
|
|
140
|
-
const coder = universal.genericCoderFor(metadata.config.version)
|
|
141
|
-
const { encoded } = coder.signature.encodeSigners(metadata.config, metadata.parts ?? new Map(), [], metadata.chainId)
|
|
142
|
-
|
|
143
|
-
try {
|
|
144
|
-
const key = this.keyOfRequest(this.address, message, encoded, metadata.chainId)
|
|
145
|
-
const lastAttempt = this.requests.get(id)?.lastAttempt
|
|
146
|
-
if (lastAttempt === key) {
|
|
147
|
-
return
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
this.requests.get(id)!.lastAttempt = key
|
|
151
|
-
|
|
152
|
-
const result = await this.guard.signWith({
|
|
153
|
-
signer: this.address,
|
|
154
|
-
request: {
|
|
155
|
-
msg: ethers.utils.hexlify(message),
|
|
156
|
-
auxData: this.packMsgAndSig(metadata.address, metadata.digest, encoded, metadata.chainId),
|
|
157
|
-
chainId: ethers.BigNumber.from(metadata.chainId).toNumber() // TODO: This should be a string (in the API)
|
|
158
|
-
},
|
|
159
|
-
token: metadata.guardTotpCode
|
|
160
|
-
? {
|
|
161
|
-
id: AuthMethod.TOTP,
|
|
162
|
-
token: metadata.guardTotpCode
|
|
163
|
-
}
|
|
164
|
-
: undefined
|
|
165
|
-
})
|
|
166
|
-
|
|
167
|
-
if (ethers.utils.arrayify(result.sig).length !== 0) {
|
|
168
|
-
this.requests.get(id)!.onSignature(result.sig)
|
|
169
|
-
this.requests.delete(id)
|
|
170
|
-
}
|
|
171
|
-
} catch (e) {
|
|
172
|
-
// The guard signer may reject the request for a number of reasons
|
|
173
|
-
// like for example, if it's being the first signer (it waits for other signers to sign first)
|
|
174
|
-
// We always forward the error here and filter on client side.
|
|
175
|
-
this.onError?.(e)
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
137
|
suffix(): BytesLike {
|
|
180
138
|
return this.appendSuffix ? [3] : []
|
|
181
139
|
}
|