@0xsequence/guard 1.4.0 → 1.4.1

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/src/guard.gen.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  /* eslint-disable */
2
- // sequence-guard v0.4.0 a29651d1d5f63268e8d03b51e46557e0632c144d
2
+ // sequence-guard v0.4.0 b1cf87e4fb4cc6bef4c479bd613bfb462d1f788e
3
3
  // --
4
- // Code generated by webrpc-gen@v0.10.x-dev with typescript generator. DO NOT EDIT.
4
+ // Code generated by webrpc-gen@v0.12.x-dev with typescript@v0.10.0 generator. DO NOT EDIT.
5
5
  //
6
- // webrpc-gen -schema=guard.ridl -target=typescript -client -out=./clients/guard.gen.ts
6
+ // webrpc-gen -schema=guard.ridl -target=typescript@v0.10.0 -client -out=./clients/guard.gen.ts
7
7
 
8
8
  // WebRPC description and code-gen version
9
9
  export const WebRPCVersion = 'v1'
@@ -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 = 'a29651d1d5f63268e8d03b51e46557e0632c144d'
15
+ export const WebRPCSchemaHash = 'b1cf87e4fb4cc6bef4c479bd613bfb462d1f788e'
16
16
 
17
17
  //
18
18
  // Types
@@ -50,6 +50,23 @@ export interface SignRequest {
50
50
  auxData: string
51
51
  }
52
52
 
53
+ export interface OwnershipProof {
54
+ wallet: string
55
+ timestamp: number
56
+ signer: string
57
+ signature: string
58
+ }
59
+
60
+ export interface AuthToken {
61
+ id: string
62
+ token: string
63
+ }
64
+
65
+ export interface RecoveryCode {
66
+ code: string
67
+ used: boolean
68
+ }
69
+
53
70
  export interface Guard {
54
71
  ping(headers?: object): Promise<PingReturn>
55
72
  version(headers?: object): Promise<VersionReturn>
@@ -57,6 +74,15 @@ export interface Guard {
57
74
  getSignerConfig(args: GetSignerConfigArgs, headers?: object): Promise<GetSignerConfigReturn>
58
75
  sign(args: SignArgs, headers?: object): Promise<SignReturn>
59
76
  signWith(args: SignWithArgs, headers?: object): Promise<SignWithReturn>
77
+ authMethods(args: AuthMethodsArgs, headers?: object): Promise<AuthMethodsReturn>
78
+ setPIN(args: SetPINArgs, headers?: object): Promise<SetPINReturn>
79
+ resetPIN(args: ResetPINArgs, headers?: object): Promise<ResetPINReturn>
80
+ createTOTP(args: CreateTOTPArgs, headers?: object): Promise<CreateTOTPReturn>
81
+ commitTOTP(args: CommitTOTPArgs, headers?: object): Promise<CommitTOTPReturn>
82
+ resetTOTP(args: ResetTOTPArgs, headers?: object): Promise<ResetTOTPReturn>
83
+ reset2FA(args: Reset2FAArgs, headers?: object): Promise<Reset2FAReturn>
84
+ recoveryCodes(args: RecoveryCodesArgs, headers?: object): Promise<RecoveryCodesReturn>
85
+ resetRecoveryCodes(args: ResetRecoveryCodesArgs, headers?: object): Promise<ResetRecoveryCodesReturn>
60
86
  }
61
87
 
62
88
  export interface PingArgs {}
@@ -83,6 +109,7 @@ export interface GetSignerConfigReturn {
83
109
  }
84
110
  export interface SignArgs {
85
111
  request: SignRequest
112
+ token?: AuthToken
86
113
  }
87
114
 
88
115
  export interface SignReturn {
@@ -91,11 +118,75 @@ export interface SignReturn {
91
118
  export interface SignWithArgs {
92
119
  signer: string
93
120
  request: SignRequest
121
+ token?: AuthToken
94
122
  }
95
123
 
96
124
  export interface SignWithReturn {
97
125
  sig: string
98
126
  }
127
+ export interface AuthMethodsArgs {
128
+ proof?: OwnershipProof
129
+ }
130
+
131
+ export interface AuthMethodsReturn {
132
+ methods: Array<string>
133
+ }
134
+ export interface SetPINArgs {
135
+ pin: string
136
+ timestamp: number
137
+ signature: string
138
+ }
139
+
140
+ export interface SetPINReturn {}
141
+ export interface ResetPINArgs {
142
+ timestamp: number
143
+ signature: string
144
+ }
145
+
146
+ export interface ResetPINReturn {}
147
+ export interface CreateTOTPArgs {
148
+ timestamp: number
149
+ signature: string
150
+ }
151
+
152
+ export interface CreateTOTPReturn {
153
+ uri: string
154
+ }
155
+ export interface CommitTOTPArgs {
156
+ token: string
157
+ }
158
+
159
+ export interface CommitTOTPReturn {
160
+ codes: Array<RecoveryCode>
161
+ }
162
+ export interface ResetTOTPArgs {
163
+ timestamp: number
164
+ signature: string
165
+ }
166
+
167
+ export interface ResetTOTPReturn {}
168
+ export interface Reset2FAArgs {
169
+ code: string
170
+ proof?: OwnershipProof
171
+ }
172
+
173
+ export interface Reset2FAReturn {}
174
+ export interface RecoveryCodesArgs {
175
+ timestamp: number
176
+ signature: string
177
+ }
178
+
179
+ export interface RecoveryCodesReturn {
180
+ codes: Array<RecoveryCode>
181
+ }
182
+ export interface ResetRecoveryCodesArgs {
183
+ timestamp: number
184
+ signature: string
185
+ }
186
+
187
+ export interface ResetRecoveryCodesReturn {
188
+ codes: Array<RecoveryCode>
189
+ }
99
190
 
100
191
  //
101
192
  // Client
@@ -173,6 +264,88 @@ export class Guard implements Guard {
173
264
  })
174
265
  })
175
266
  }
267
+
268
+ authMethods = (args: AuthMethodsArgs, headers?: object): Promise<AuthMethodsReturn> => {
269
+ return this.fetch(this.url('AuthMethods'), createHTTPRequest(args, headers)).then(res => {
270
+ return buildResponse(res).then(_data => {
271
+ return {
272
+ methods: <Array<string>>_data.methods
273
+ }
274
+ })
275
+ })
276
+ }
277
+
278
+ setPIN = (args: SetPINArgs, headers?: object): Promise<SetPINReturn> => {
279
+ return this.fetch(this.url('SetPIN'), createHTTPRequest(args, headers)).then(res => {
280
+ return buildResponse(res).then(_data => {
281
+ return {}
282
+ })
283
+ })
284
+ }
285
+
286
+ resetPIN = (args: ResetPINArgs, headers?: object): Promise<ResetPINReturn> => {
287
+ return this.fetch(this.url('ResetPIN'), createHTTPRequest(args, headers)).then(res => {
288
+ return buildResponse(res).then(_data => {
289
+ return {}
290
+ })
291
+ })
292
+ }
293
+
294
+ createTOTP = (args: CreateTOTPArgs, headers?: object): Promise<CreateTOTPReturn> => {
295
+ return this.fetch(this.url('CreateTOTP'), createHTTPRequest(args, headers)).then(res => {
296
+ return buildResponse(res).then(_data => {
297
+ return {
298
+ uri: <string>_data.uri
299
+ }
300
+ })
301
+ })
302
+ }
303
+
304
+ commitTOTP = (args: CommitTOTPArgs, headers?: object): Promise<CommitTOTPReturn> => {
305
+ return this.fetch(this.url('CommitTOTP'), createHTTPRequest(args, headers)).then(res => {
306
+ return buildResponse(res).then(_data => {
307
+ return {
308
+ codes: <Array<RecoveryCode>>_data.codes
309
+ }
310
+ })
311
+ })
312
+ }
313
+
314
+ resetTOTP = (args: ResetTOTPArgs, headers?: object): Promise<ResetTOTPReturn> => {
315
+ return this.fetch(this.url('ResetTOTP'), createHTTPRequest(args, headers)).then(res => {
316
+ return buildResponse(res).then(_data => {
317
+ return {}
318
+ })
319
+ })
320
+ }
321
+
322
+ reset2FA = (args: Reset2FAArgs, headers?: object): Promise<Reset2FAReturn> => {
323
+ return this.fetch(this.url('Reset2FA'), createHTTPRequest(args, headers)).then(res => {
324
+ return buildResponse(res).then(_data => {
325
+ return {}
326
+ })
327
+ })
328
+ }
329
+
330
+ recoveryCodes = (args: RecoveryCodesArgs, headers?: object): Promise<RecoveryCodesReturn> => {
331
+ return this.fetch(this.url('RecoveryCodes'), createHTTPRequest(args, headers)).then(res => {
332
+ return buildResponse(res).then(_data => {
333
+ return {
334
+ codes: <Array<RecoveryCode>>_data.codes
335
+ }
336
+ })
337
+ })
338
+ }
339
+
340
+ resetRecoveryCodes = (args: ResetRecoveryCodesArgs, headers?: object): Promise<ResetRecoveryCodesReturn> => {
341
+ return this.fetch(this.url('ResetRecoveryCodes'), createHTTPRequest(args, headers)).then(res => {
342
+ return buildResponse(res).then(_data => {
343
+ return {
344
+ codes: <Array<RecoveryCode>>_data.codes
345
+ }
346
+ })
347
+ })
348
+ }
176
349
  }
177
350
 
178
351
  export interface WebRPCError extends Error {
package/src/index.ts CHANGED
@@ -1,2 +1 @@
1
- export * from './guard.gen'
2
1
  export * from './signer'
package/src/signer.ts CHANGED
@@ -1,27 +1,19 @@
1
- import { signers, Status } from '@0xsequence/signhub'
2
- import { BytesLike, ethers } from 'ethers'
3
- import { Guard } from './guard.gen'
1
+ import { Account } from '@0xsequence/account'
4
2
  import { commons, universal } from '@0xsequence/core'
3
+ import { signers, Status } from '@0xsequence/signhub'
4
+ import { encodeTypedDataDigest, TypedData } from '@0xsequence/utils'
5
+ import { BytesLike, ethers, TypedDataDomain } from 'ethers'
6
+ import { AuthMethodsReturn, Guard, RecoveryCode as GuardRecoveryCode } from './guard.gen'
5
7
 
6
8
  const fetch = typeof global === 'object' ? global.fetch : window.fetch
7
9
 
8
10
  export class GuardSigner implements signers.SapientSigner {
9
11
  private guard: Guard
10
- private requests: Map<
11
- string,
12
- {
13
- lastAttempt?: string
14
- onSignature: (signature: BytesLike) => void
15
- onRejection: (error: string) => void
16
- onStatus: (situation: string) => void
17
- }
18
- > = new Map()
19
12
 
20
13
  constructor(
21
14
  public readonly address: string,
22
15
  public readonly url: string,
23
- public readonly appendSuffix: boolean = false,
24
- private readonly onError?: (err: Error) => void
16
+ public readonly appendSuffix: boolean = false
25
17
  ) {
26
18
  this.guard = new Guard(url, fetch)
27
19
  }
@@ -46,8 +38,8 @@ export class GuardSigner implements signers.SapientSigner {
46
38
  }
47
39
 
48
40
  async requestSignature(
49
- id: string,
50
- _message: BytesLike,
41
+ _id: string,
42
+ message: BytesLike,
51
43
  metadata: object,
52
44
  callbacks: {
53
45
  onSignature: (signature: BytesLike) => void
@@ -55,78 +47,286 @@ export class GuardSigner implements signers.SapientSigner {
55
47
  onStatus: (situation: string) => void
56
48
  }
57
49
  ): Promise<boolean> {
50
+ const { onSignature, onRejection } = callbacks
51
+
58
52
  if (!commons.isWalletSignRequestMetadata(metadata)) {
59
- callbacks.onRejection('Expected Sequence-like metadata')
53
+ onRejection('expected sequence signature request metadata')
54
+ return false
55
+ }
56
+
57
+ const guardTotpCode = (metadata as { guardTotpCode?: string }).guardTotpCode
58
+
59
+ // Building auxData, notice: this uses the old v1 format
60
+ // TODO: We should update the guard API so we can pass the metadata directly
61
+ const coder = universal.genericCoderFor(metadata.config.version)
62
+ const { encoded } = coder.signature.encodeSigners(metadata.config, metadata.parts ?? new Map(), [], metadata.chainId)
63
+
64
+ try {
65
+ const { sig: signature } = await this.guard.signWith({
66
+ signer: this.address,
67
+ request: {
68
+ msg: ethers.utils.hexlify(message),
69
+ auxData: this.packMsgAndSig(metadata.address, metadata.digest, encoded, metadata.chainId),
70
+ chainId: ethers.BigNumber.from(metadata.chainId).toNumber()
71
+ },
72
+ token: guardTotpCode ? { id: AuthMethod.TOTP, token: guardTotpCode } : undefined
73
+ })
74
+
75
+ if (ethers.utils.arrayify(signature).length === 0) {
76
+ throw new Error('guard response contained no signature data')
77
+ }
78
+
79
+ onSignature(signature)
80
+ return true
81
+ } catch (error) {
82
+ onRejection(`unable to request guard signature: ${error.message ?? error.msg ?? error}`)
83
+ return false
84
+ }
85
+ }
86
+
87
+ notifyStatusChange(_id: string, _status: Status, _metadata: object): void {}
88
+
89
+ async getAuthMethods(proof: OwnershipProof): Promise<AuthMethod[]> {
90
+ let response: AuthMethodsReturn
91
+
92
+ if ('jwt' in proof) {
93
+ response = await this.guard.authMethods({}, { Authorization: `BEARER ${proof.jwt}` })
60
94
  } else {
61
- // Queue the request first, this method only does that
62
- // the requesting to the API is later handled on every status change
63
- this.requests.set(id, callbacks)
95
+ const signedProof = await signOwnershipProof(proof)
96
+
97
+ response = await this.guard.authMethods({
98
+ proof: {
99
+ wallet: signedProof.walletAddress,
100
+ timestamp: signedProof.timestamp.getTime(),
101
+ signer: signedProof.signerAddress,
102
+ signature: signedProof.signature
103
+ }
104
+ })
64
105
  }
65
106
 
66
- return true
107
+ return response.methods.map(parseAuthMethod)
67
108
  }
68
109
 
69
- notifyStatusChange(id: string, status: Status, metadata: object): void {
70
- if (!this.requests.has(id)) return
110
+ async setPin(pin: string | undefined, proof: AuthUpdateProof): Promise<void> {
111
+ const signedProof = await signAuthUpdateProof(proof)
71
112
 
72
- if (!commons.isWalletSignRequestMetadata(metadata)) {
73
- this.requests.get(id)!.onRejection('Expected Sequence-like metadata (status update)')
74
- return
113
+ if (pin === undefined) {
114
+ await this.guard.resetPIN(
115
+ { timestamp: signedProof.timestamp.getTime(), signature: signedProof.signature },
116
+ { Authorization: `BEARER ${proof.jwt}` }
117
+ )
118
+ } else {
119
+ await this.guard.setPIN(
120
+ { pin, timestamp: signedProof.timestamp.getTime(), signature: signedProof.signature },
121
+ { Authorization: `BEARER ${proof.jwt}` }
122
+ )
75
123
  }
124
+ }
76
125
 
77
- this.evaluateRequest(id, status.message, status, metadata)
126
+ resetPin(proof: AuthUpdateProof): Promise<void> {
127
+ return this.setPin(undefined, proof)
78
128
  }
79
129
 
80
- private packMsgAndSig(address: string, msg: BytesLike, sig: BytesLike, chainId: ethers.BigNumberish): string {
81
- return ethers.utils.defaultAbiCoder.encode(['address', 'uint256', 'bytes', 'bytes'], [address, chainId, msg, sig])
130
+ async createTotp(proof: AuthUpdateProof): Promise<URL> {
131
+ const signedProof = await signAuthUpdateProof(proof)
132
+
133
+ const { uri } = await this.guard.createTOTP(
134
+ { timestamp: signedProof.timestamp.getTime(), signature: signedProof.signature },
135
+ { Authorization: `BEARER ${proof.jwt}` }
136
+ )
137
+
138
+ return new URL(uri)
82
139
  }
83
140
 
84
- private keyOfRequest(signer: string, msg: BytesLike, auxData: BytesLike, chainId: ethers.BigNumberish): string {
85
- return ethers.utils.solidityKeccak256(['address', 'uint256', 'bytes', 'bytes'], [signer, chainId, msg, auxData])
141
+ async commitTotp(token: string, jwt: string): Promise<RecoveryCode[]> {
142
+ const { codes } = await this.guard.commitTOTP({ token }, { Authorization: `BEARER ${jwt}` })
143
+ return codes
86
144
  }
87
145
 
88
- private async evaluateRequest(
89
- id: string,
90
- message: BytesLike,
91
- _: Status,
92
- metadata: commons.WalletSignRequestMetadata
93
- ): Promise<void> {
94
- // Building auxData, notice: this uses the old v1 format
95
- // TODO: We should update the guard API so we can pass the metadata directly
96
- const coder = universal.genericCoderFor(metadata.config.version)
97
- const { encoded } = coder.signature.encodeSigners(metadata.config, metadata.parts ?? new Map(), [], metadata.chainId)
146
+ async resetTotp(proof: AuthUpdateProof): Promise<void> {
147
+ const signedProof = await signAuthUpdateProof(proof)
98
148
 
99
- try {
100
- const key = this.keyOfRequest(this.address, message, encoded, metadata.chainId)
101
- const lastAttempt = this.requests.get(id)?.lastAttempt
102
- if (lastAttempt === key) {
103
- return
104
- }
149
+ await this.guard.resetTOTP(
150
+ { timestamp: signedProof.timestamp.getTime(), signature: signedProof.signature },
151
+ { Authorization: `BEARER ${proof.jwt}` }
152
+ )
153
+ }
105
154
 
106
- this.requests.get(id)!.lastAttempt = key
155
+ async reset2fa(recoveryCode: string, proof: OwnershipProof): Promise<void> {
156
+ if ('jwt' in proof) {
157
+ await this.guard.reset2FA({ code: recoveryCode }, { Authorization: `BEARER ${proof.jwt}` })
158
+ } else {
159
+ const signedProof = await signOwnershipProof(proof)
107
160
 
108
- const result = await this.guard.signWith({
109
- signer: this.address,
110
- request: {
111
- msg: ethers.utils.hexlify(message),
112
- auxData: this.packMsgAndSig(metadata.address, metadata.digest, encoded, metadata.chainId),
113
- chainId: ethers.BigNumber.from(metadata.chainId).toNumber() // TODO: This should be a string (in the API)
161
+ await this.guard.reset2FA({
162
+ code: recoveryCode,
163
+ proof: {
164
+ wallet: signedProof.walletAddress,
165
+ timestamp: signedProof.timestamp.getTime(),
166
+ signer: signedProof.signerAddress,
167
+ signature: signedProof.signature
114
168
  }
115
169
  })
116
-
117
- if (ethers.utils.arrayify(result.sig).length !== 0) {
118
- this.requests.get(id)!.onSignature(result.sig)
119
- this.requests.delete(id)
120
- }
121
- } catch (e) {
122
- // The guard signer may reject the request for a number of reasons
123
- // like for example, if it's being the first signer (it waits for other signers to sign first)
124
- // We always forward the error here and filter on client side.
125
- this.onError?.(e)
126
170
  }
127
171
  }
128
172
 
173
+ async getRecoveryCodes(proof: AuthUpdateProof): Promise<RecoveryCode[]> {
174
+ const signedProof = await signAuthUpdateProof(proof)
175
+
176
+ const { codes } = await this.guard.recoveryCodes(
177
+ { timestamp: signedProof.timestamp.getTime(), signature: signedProof.signature },
178
+ { Authorization: `BEARER ${proof.jwt}` }
179
+ )
180
+
181
+ return codes
182
+ }
183
+
184
+ async resetRecoveryCodes(proof: AuthUpdateProof): Promise<RecoveryCode[]> {
185
+ const signedProof = await signAuthUpdateProof(proof)
186
+
187
+ const { codes } = await this.guard.resetRecoveryCodes(
188
+ { timestamp: signedProof.timestamp.getTime(), signature: signedProof.signature },
189
+ { Authorization: `BEARER ${proof.jwt}` }
190
+ )
191
+
192
+ return codes
193
+ }
194
+
195
+ private packMsgAndSig(address: string, msg: BytesLike, sig: BytesLike, chainId: ethers.BigNumberish): string {
196
+ return ethers.utils.defaultAbiCoder.encode(['address', 'uint256', 'bytes', 'bytes'], [address, chainId, msg, sig])
197
+ }
198
+
129
199
  suffix(): BytesLike {
130
200
  return this.appendSuffix ? [3] : []
131
201
  }
132
202
  }
203
+
204
+ export type RecoveryCode = GuardRecoveryCode
205
+
206
+ export enum AuthMethod {
207
+ PIN = 'PIN',
208
+ TOTP = 'TOTP'
209
+ }
210
+
211
+ function parseAuthMethod(method: string): AuthMethod {
212
+ switch (method) {
213
+ case AuthMethod.PIN:
214
+ case AuthMethod.TOTP:
215
+ return method
216
+ default:
217
+ throw new Error(`unknown auth method '${method}'`)
218
+ }
219
+ }
220
+
221
+ export type OwnershipProof =
222
+ | { jwt: string }
223
+ | {
224
+ walletAddress: string
225
+ timestamp: Date
226
+ signerAddress: string
227
+ signature: string
228
+ }
229
+ | {
230
+ walletAddress: string
231
+ signer: ethers.Signer | signers.SapientSigner
232
+ }
233
+
234
+ function isSignedOwnershipProof(
235
+ proof: OwnershipProof
236
+ ): proof is { walletAddress: string; timestamp: Date; signerAddress: string; signature: string } {
237
+ return 'signerAddress' in proof && typeof proof.signerAddress === 'string'
238
+ }
239
+
240
+ async function signOwnershipProof(
241
+ proof: Exclude<OwnershipProof, { jwt: string }>
242
+ ): Promise<{ walletAddress: string; timestamp: Date; signerAddress: string; signature: string }> {
243
+ if (isSignedOwnershipProof(proof)) {
244
+ return proof
245
+ } else {
246
+ const signer = signers.isSapientSigner(proof.signer) ? proof.signer : new signers.SignerWrapper(proof.signer)
247
+ const signerAddress = await signer.getAddress()
248
+ const timestamp = new Date()
249
+ const typedData = getOwnershipProofTypedData(proof.walletAddress, timestamp)
250
+ const digest = encodeTypedDataDigest(typedData)
251
+ const randomId = ethers.utils.hexlify(ethers.utils.randomBytes(32))
252
+
253
+ return new Promise((resolve, reject) =>
254
+ signer.requestSignature(
255
+ randomId,
256
+ digest,
257
+ {},
258
+ {
259
+ onSignature(signature) {
260
+ resolve({
261
+ walletAddress: proof.walletAddress,
262
+ timestamp,
263
+ signerAddress,
264
+ signature: ethers.utils.hexlify(signature)
265
+ })
266
+ },
267
+ onRejection: reject,
268
+ onStatus(_situation) {}
269
+ }
270
+ )
271
+ )
272
+ }
273
+ }
274
+
275
+ export type AuthUpdateProof = { jwt: string } & ({ timestamp: Date; signature: string } | { wallet: Account })
276
+
277
+ async function signAuthUpdateProof(proof: AuthUpdateProof): Promise<{ jwt: string; timestamp: Date; signature: string }> {
278
+ if ('wallet' in proof) {
279
+ const timestamp = new Date()
280
+ const typedData = getAuthUpdateProofTypedData(timestamp)
281
+
282
+ const signature = await proof.wallet.signTypedData(
283
+ typedData.domain,
284
+ typedData.types,
285
+ typedData.message,
286
+ typedData.domain.chainId ?? 1,
287
+ 'eip6492'
288
+ )
289
+
290
+ return { jwt: proof.jwt, timestamp, signature }
291
+ } else {
292
+ return proof
293
+ }
294
+ }
295
+
296
+ export function getOwnershipProofTypedData(wallet: string, timestamp: Date): TypedData {
297
+ return {
298
+ domain,
299
+ types: {
300
+ AuthMethods: [
301
+ { name: 'wallet', type: 'address' },
302
+ { name: 'timestamp', type: 'string' }
303
+ ]
304
+ },
305
+ message: {
306
+ wallet: ethers.utils.getAddress(wallet),
307
+ timestamp: toUTCString(timestamp)
308
+ }
309
+ }
310
+ }
311
+
312
+ export function getAuthUpdateProofTypedData(timestamp: Date): TypedData {
313
+ return {
314
+ domain,
315
+ types: {
316
+ AuthUpdate: [{ name: 'timestamp', type: 'string' }]
317
+ },
318
+ message: {
319
+ timestamp: toUTCString(timestamp)
320
+ }
321
+ }
322
+ }
323
+
324
+ const domain: TypedDataDomain = {
325
+ name: 'Sequence Guard',
326
+ version: '1',
327
+ chainId: 1
328
+ }
329
+
330
+ function toUTCString(date: Date): string {
331
+ return date.toUTCString().replace('GMT', 'UTC')
332
+ }