@0xsequence/guard 2.3.35 → 3.0.0-beta.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.
@@ -1,2 +0,0 @@
1
- export { Guard } from "./guard.gen.js";
2
- export * from "./signer.js";
@@ -1,66 +0,0 @@
1
- import { Account } from '@0xsequence/account';
2
- import { commons } from '@0xsequence/core';
3
- import { signers, Status } from '@0xsequence/signhub';
4
- import { TypedData } from '@0xsequence/utils';
5
- import { ethers } from 'ethers';
6
- import { RecoveryCode as GuardRecoveryCode } from "./guard.gen.js";
7
- export declare class GuardSigner implements signers.SapientSigner {
8
- readonly address: string;
9
- readonly url: string;
10
- readonly appendSuffix: boolean;
11
- readonly projectAccessKey?: string | undefined;
12
- private guard;
13
- constructor(address: string, url: string, appendSuffix?: boolean, projectAccessKey?: string | undefined);
14
- _fetch: (input: RequestInfo, init?: RequestInit) => Promise<Response>;
15
- getAddress(): Promise<string>;
16
- buildDeployTransaction(_metadata: object): Promise<commons.transaction.TransactionBundle | undefined>;
17
- predecorateSignedTransactions(_metadata: object): Promise<commons.transaction.SignedTransactionBundle[]>;
18
- decorateTransactions(bundle: commons.transaction.IntendedTransactionBundle, _metadata: object): Promise<commons.transaction.IntendedTransactionBundle>;
19
- sign(message: ethers.BytesLike, metadata: object): Promise<ethers.BytesLike>;
20
- notifyStatusChange(_id: string, _status: Status, _metadata: object): void;
21
- getAuthMethods(proof: OwnershipProof): Promise<{
22
- methods: AuthMethod[];
23
- active: boolean;
24
- }>;
25
- setPin(pin: string | undefined, proof: AuthUpdateProof): Promise<void>;
26
- resetPin(proof: AuthUpdateProof): Promise<void>;
27
- createTotp(proof: AuthUpdateProof): Promise<URL>;
28
- commitTotp(token: string, jwt: string): Promise<RecoveryCode[]>;
29
- resetTotp(proof: AuthUpdateProof): Promise<void>;
30
- reset2fa(recoveryCode: string, proof: OwnershipProof): Promise<void>;
31
- getRecoveryCodes(proof: AuthUpdateProof): Promise<RecoveryCode[]>;
32
- resetRecoveryCodes(proof: AuthUpdateProof): Promise<RecoveryCode[]>;
33
- private packMsgAndSig;
34
- suffix(): ethers.BytesLike;
35
- }
36
- export type RecoveryCode = GuardRecoveryCode;
37
- export declare enum AuthMethod {
38
- PIN = "PIN",
39
- TOTP = "TOTP"
40
- }
41
- export type SignedOwnershipProof = {
42
- walletAddress: string;
43
- timestamp: Date;
44
- signerAddress: string;
45
- signature: string;
46
- };
47
- export type OwnershipProof = SignedOwnershipProof | {
48
- jwt: string;
49
- } | {
50
- walletAddress: string;
51
- signer: ethers.Signer | signers.SapientSigner;
52
- };
53
- export declare function isSignedOwnershipProof(proof: OwnershipProof): proof is SignedOwnershipProof;
54
- export declare function signOwnershipProof(proof: Exclude<OwnershipProof, {
55
- jwt: string;
56
- }>): Promise<SignedOwnershipProof>;
57
- export type AuthUpdateProof = {
58
- jwt: string;
59
- } & ({
60
- timestamp: Date;
61
- signature: string;
62
- } | {
63
- wallet: Account;
64
- });
65
- export declare function getOwnershipProofTypedData(wallet: string, timestamp: Date): TypedData;
66
- export declare function getAuthUpdateProofTypedData(timestamp: Date): TypedData;
package/src/signer.ts DELETED
@@ -1,308 +0,0 @@
1
- import { Account } from '@0xsequence/account'
2
- import { commons, universal } from '@0xsequence/core'
3
- import { signers, Status } from '@0xsequence/signhub'
4
- import { encodeTypedDataDigest, TypedData } from '@0xsequence/utils'
5
- import { ethers } from 'ethers'
6
- import { AuthMethodsReturn, Guard, RecoveryCode as GuardRecoveryCode } from './guard.gen'
7
-
8
- export class GuardSigner implements signers.SapientSigner {
9
- private guard: Guard
10
-
11
- constructor(
12
- public readonly address: string,
13
- public readonly url: string,
14
- public readonly appendSuffix: boolean = false,
15
- public readonly projectAccessKey?: string
16
- ) {
17
- this.guard = new Guard(url, this._fetch)
18
- }
19
-
20
- _fetch = (input: RequestInfo, init?: RequestInit): Promise<Response> => {
21
- const headers: { [key: string]: any } = {}
22
-
23
- const projectAccessKey = this.projectAccessKey
24
-
25
- if (projectAccessKey && projectAccessKey.length > 0) {
26
- headers['X-Access-Key'] = projectAccessKey
27
- }
28
-
29
- // before the request is made
30
- init!.headers = { ...init!.headers, ...headers }
31
-
32
- return fetch(input, init)
33
- }
34
-
35
- async getAddress(): Promise<string> {
36
- return this.address
37
- }
38
-
39
- async buildDeployTransaction(_metadata: object): Promise<commons.transaction.TransactionBundle | undefined> {
40
- return undefined
41
- }
42
-
43
- async predecorateSignedTransactions(_metadata: object): Promise<commons.transaction.SignedTransactionBundle[]> {
44
- return []
45
- }
46
-
47
- async decorateTransactions(
48
- bundle: commons.transaction.IntendedTransactionBundle,
49
- _metadata: object
50
- ): Promise<commons.transaction.IntendedTransactionBundle> {
51
- return bundle
52
- }
53
-
54
- async sign(message: ethers.BytesLike, metadata: object): Promise<ethers.BytesLike> {
55
- if (!commons.isWalletSignRequestMetadata(metadata)) {
56
- throw new Error('expected sequence signature request metadata')
57
- }
58
-
59
- const guardTotpCode = (metadata as { guardTotpCode?: string }).guardTotpCode
60
-
61
- // Building auxData, notice: this uses the old v1 format
62
- // TODO: We should update the guard API so we can pass the metadata directly
63
- const coder = universal.genericCoderFor(metadata.config.version)
64
- const { encoded } = coder.signature.encodeSigners(metadata.config, metadata.parts ?? new Map(), [], metadata.chainId)
65
-
66
- return (
67
- await this.guard.signWith({
68
- signer: this.address,
69
- request: {
70
- msg: ethers.hexlify(message),
71
- auxData: this.packMsgAndSig(metadata.address, metadata.digest, encoded, metadata.chainId),
72
- chainId: Number(metadata.chainId)
73
- },
74
- token: guardTotpCode ? { id: AuthMethod.TOTP, token: guardTotpCode } : undefined
75
- })
76
- ).sig
77
- }
78
-
79
- notifyStatusChange(_id: string, _status: Status, _metadata: object): void {}
80
-
81
- async getAuthMethods(proof: OwnershipProof): Promise<{ methods: AuthMethod[]; active: boolean }> {
82
- let response: AuthMethodsReturn
83
-
84
- if ('jwt' in proof) {
85
- response = await this.guard.authMethods({}, { Authorization: `BEARER ${proof.jwt}` })
86
- } else {
87
- const signedProof = await signOwnershipProof(proof)
88
-
89
- response = await this.guard.authMethods({
90
- proof: {
91
- wallet: signedProof.walletAddress,
92
- timestamp: signedProof.timestamp.getTime(),
93
- signer: signedProof.signerAddress,
94
- signature: signedProof.signature
95
- }
96
- })
97
- }
98
-
99
- return { ...response, methods: response.methods.map(parseAuthMethod) }
100
- }
101
-
102
- async setPin(pin: string | undefined, proof: AuthUpdateProof): Promise<void> {
103
- const signedProof = await signAuthUpdateProof(proof)
104
-
105
- if (pin === undefined) {
106
- await this.guard.resetPIN(
107
- { timestamp: signedProof.timestamp.getTime(), signature: signedProof.signature },
108
- { Authorization: `BEARER ${proof.jwt}` }
109
- )
110
- } else {
111
- await this.guard.setPIN(
112
- { pin, timestamp: signedProof.timestamp.getTime(), signature: signedProof.signature },
113
- { Authorization: `BEARER ${proof.jwt}` }
114
- )
115
- }
116
- }
117
-
118
- resetPin(proof: AuthUpdateProof): Promise<void> {
119
- return this.setPin(undefined, proof)
120
- }
121
-
122
- async createTotp(proof: AuthUpdateProof): Promise<URL> {
123
- const signedProof = await signAuthUpdateProof(proof)
124
-
125
- const { uri } = await this.guard.createTOTP(
126
- { timestamp: signedProof.timestamp.getTime(), signature: signedProof.signature },
127
- { Authorization: `BEARER ${proof.jwt}` }
128
- )
129
-
130
- return new URL(uri)
131
- }
132
-
133
- async commitTotp(token: string, jwt: string): Promise<RecoveryCode[]> {
134
- const { codes } = await this.guard.commitTOTP({ token }, { Authorization: `BEARER ${jwt}` })
135
- return codes
136
- }
137
-
138
- async resetTotp(proof: AuthUpdateProof): Promise<void> {
139
- const signedProof = await signAuthUpdateProof(proof)
140
-
141
- await this.guard.resetTOTP(
142
- { timestamp: signedProof.timestamp.getTime(), signature: signedProof.signature },
143
- { Authorization: `BEARER ${proof.jwt}` }
144
- )
145
- }
146
-
147
- async reset2fa(recoveryCode: string, proof: OwnershipProof): Promise<void> {
148
- if ('jwt' in proof) {
149
- await this.guard.reset2FA({ code: recoveryCode }, { Authorization: `BEARER ${proof.jwt}` })
150
- } else {
151
- const signedProof = await signOwnershipProof(proof)
152
-
153
- await this.guard.reset2FA({
154
- code: recoveryCode,
155
- proof: {
156
- wallet: signedProof.walletAddress,
157
- timestamp: signedProof.timestamp.getTime(),
158
- signer: signedProof.signerAddress,
159
- signature: signedProof.signature
160
- }
161
- })
162
- }
163
- }
164
-
165
- async getRecoveryCodes(proof: AuthUpdateProof): Promise<RecoveryCode[]> {
166
- const signedProof = await signAuthUpdateProof(proof)
167
-
168
- const { codes } = await this.guard.recoveryCodes(
169
- { timestamp: signedProof.timestamp.getTime(), signature: signedProof.signature },
170
- { Authorization: `BEARER ${proof.jwt}` }
171
- )
172
-
173
- return codes
174
- }
175
-
176
- async resetRecoveryCodes(proof: AuthUpdateProof): Promise<RecoveryCode[]> {
177
- const signedProof = await signAuthUpdateProof(proof)
178
-
179
- const { codes } = await this.guard.resetRecoveryCodes(
180
- { timestamp: signedProof.timestamp.getTime(), signature: signedProof.signature },
181
- { Authorization: `BEARER ${proof.jwt}` }
182
- )
183
-
184
- return codes
185
- }
186
-
187
- private packMsgAndSig(address: string, msg: ethers.BytesLike, sig: ethers.BytesLike, chainId: ethers.BigNumberish): string {
188
- return ethers.AbiCoder.defaultAbiCoder().encode(['address', 'uint256', 'bytes', 'bytes'], [address, chainId, msg, sig])
189
- }
190
-
191
- suffix(): ethers.BytesLike {
192
- return new Uint8Array(this.appendSuffix ? [3] : [])
193
- }
194
- }
195
-
196
- export type RecoveryCode = GuardRecoveryCode
197
-
198
- export enum AuthMethod {
199
- PIN = 'PIN',
200
- TOTP = 'TOTP'
201
- }
202
-
203
- function parseAuthMethod(method: string): AuthMethod {
204
- switch (method) {
205
- case AuthMethod.PIN:
206
- case AuthMethod.TOTP:
207
- return method
208
- default:
209
- throw new Error(`unknown auth method '${method}'`)
210
- }
211
- }
212
-
213
- export type SignedOwnershipProof = {
214
- walletAddress: string
215
- timestamp: Date
216
- signerAddress: string
217
- signature: string
218
- }
219
-
220
- export type OwnershipProof =
221
- | SignedOwnershipProof
222
- | { jwt: string }
223
- | {
224
- walletAddress: string
225
- signer: ethers.Signer | signers.SapientSigner
226
- }
227
-
228
- export function isSignedOwnershipProof(proof: OwnershipProof): proof is SignedOwnershipProof {
229
- return 'signerAddress' in proof && typeof proof.signerAddress === 'string'
230
- }
231
-
232
- export async function signOwnershipProof(proof: Exclude<OwnershipProof, { jwt: string }>): Promise<SignedOwnershipProof> {
233
- if (isSignedOwnershipProof(proof)) {
234
- return proof
235
- } else {
236
- const signer = signers.isSapientSigner(proof.signer) ? proof.signer : new signers.SignerWrapper(proof.signer)
237
- const signerAddress = await signer.getAddress()
238
- const timestamp = new Date()
239
- const typedData = getOwnershipProofTypedData(proof.walletAddress, timestamp)
240
- const digest = encodeTypedDataDigest(typedData)
241
-
242
- return {
243
- walletAddress: proof.walletAddress,
244
- timestamp,
245
- signerAddress,
246
- signature: ethers.hexlify(await signer.sign(digest, {}))
247
- }
248
- }
249
- }
250
-
251
- export type AuthUpdateProof = { jwt: string } & ({ timestamp: Date; signature: string } | { wallet: Account })
252
-
253
- async function signAuthUpdateProof(proof: AuthUpdateProof): Promise<{ jwt: string; timestamp: Date; signature: string }> {
254
- if ('wallet' in proof) {
255
- const timestamp = new Date()
256
- const typedData = getAuthUpdateProofTypedData(timestamp)
257
-
258
- const signature = await proof.wallet.signTypedData(
259
- typedData.domain,
260
- typedData.types,
261
- typedData.message,
262
- typedData.domain.chainId ?? 1,
263
- 'eip6492'
264
- )
265
-
266
- return { jwt: proof.jwt, timestamp, signature }
267
- } else {
268
- return proof
269
- }
270
- }
271
-
272
- export function getOwnershipProofTypedData(wallet: string, timestamp: Date): TypedData {
273
- return {
274
- domain,
275
- types: {
276
- AuthMethods: [
277
- { name: 'wallet', type: 'address' },
278
- { name: 'timestamp', type: 'string' }
279
- ]
280
- },
281
- message: {
282
- wallet: ethers.getAddress(wallet),
283
- timestamp: toUTCString(timestamp)
284
- }
285
- }
286
- }
287
-
288
- export function getAuthUpdateProofTypedData(timestamp: Date): TypedData {
289
- return {
290
- domain,
291
- types: {
292
- AuthUpdate: [{ name: 'timestamp', type: 'string' }]
293
- },
294
- message: {
295
- timestamp: toUTCString(timestamp)
296
- }
297
- }
298
- }
299
-
300
- const domain: ethers.TypedDataDomain = {
301
- name: 'Sequence Guard',
302
- version: '1',
303
- chainId: 1
304
- }
305
-
306
- function toUTCString(date: Date): string {
307
- return date.toUTCString().replace('GMT', 'UTC')
308
- }