@silencelaboratories/walletprovider-sdk 0.3.0 → 1.3.0

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/README.md CHANGED
@@ -1,104 +1,103 @@
1
1
  # walletprovider-sdk
2
2
 
3
- The frontend library for Silent Network.
4
-
5
- # Demo
6
-
7
- Under the [demo](./demo) directory we provide the sample webpage that shows example usage of the library.
8
- In order to run it execute the following:
9
-
10
- 1. Build the library
11
-
12
- ```
13
- npm install
14
- npm run build
15
- ```
16
-
17
- 2. Run the demo
18
-
19
- ```
20
- cd demo
21
- npm install
22
- npm run dev
3
+ The client library for Silent Network Wallet Provider Service.
4
+
5
+ - [Installing](#installing)
6
+ - [Quick start](#quick-start)
7
+ - [Documentation](#documentation)
8
+ - [Features](#features)
9
+ - [Overview](#overview)
10
+ - [Authentication](#authentication)
11
+ - [Keygen](#keygen)
12
+ - [Signing](#signing)
13
+ - [Development](#development)
14
+ - [Build the library](#build-the-library)
15
+ - [End to end tests](#end-to-end-tests)
16
+ - [Generate the documentation](#generate-the-documentation)
17
+ - [Lint the code](#lint-the-code)
18
+
19
+ # Installing
20
+
21
+ ```sh
22
+ npm i @silencelaboratories/walletprovider-sdk
23
23
  ```
24
24
 
25
- The demo fetches configuration from the `.env` file. We provided example `.env` [here](./demo/.env).
25
+ # Quick start
26
26
 
27
- The demo communicates with [backend service](#the-backend). Run it before using the demo page.
27
+ Check the [demo](./demo/README.md) for a quick start guide.
28
28
 
29
- # Using the library
29
+ # Documentation
30
30
 
31
- The library is published on [npmjs](https://www.npmjs.com/package/@silencelaboratories/walletprovider-sdk) registry.
31
+ For description of classes, interfaces, types, please refer to [documentation](./docs/walletprovider-sdk.md).
32
32
 
33
- Install it in your project as usual:
33
+ # Features
34
34
 
35
- ```
36
- npm i @silencelaboratories/walletprovider-sdk
37
- ```
38
-
39
- ## The backend
35
+ - Authentication
36
+ - Keygen
37
+ - Signing
40
38
 
41
- The library communicates with backend service. The example implementation of such service is accessible [here](https://shipyard.rs/silencelaboratories/crates/wallet-provider-service). Please refer to backend documentation in order to run the service.
39
+ ## Overview
42
40
 
43
- Frontend uses [WalletProviderServiceClient](./docs/walletprovider-sdk.walletproviderserviceclient.md) object in order to connect to the backend and send requests.
41
+ The library provides API to authenticate, generate keys, and sign messages against the Silent Network. Before sending request for a distributed key or signature, users need to be authenticated to the Silent Network.
44
42
 
45
- # Documentation
46
-
47
- For description of classes, interfaces, types, please refer to [documentation](./docs/walletprovider-sdk.md).
43
+ Once authenticated, users register an ephemeral signing key pair and associate it with their identity. The ephemeral signing keys can later be used to authorize signing requests for duration of the session without the need for repeated user interaction, providing a seamless and secure authentication mechanism.
48
44
 
49
45
  ## Authentication
50
46
 
47
+ Users authenticate to Silent Network using 2 methods [Wallet-based](./docs/walletprovider-sdk.eoaauth.md) or [Passkey](./docs/walletprovider-sdk.passkeyauth.md).
51
48
 
52
- Users authenticate using **EOA wallet** or **Passkey** during **key generation** and register an ephemeral signing key pair and associates it with their identity.
53
-
54
- Frontend can later use the ephemeral signing key pair to authorize **signing requests** for duration of the session without the need for repeated user interaction, providing a seamless and secure authentication mechanism.
49
+ - [Wallet-based](./docs/walletprovider-sdk.eoaauth.md) authenticate users using their digital wallet, it runs at the same time users start doing **keygen**.
55
50
 
56
- Key generation:
57
- - [EOAAuth](./docs/walletprovider-sdk.eoaauth.md) to authenticate the user **during keygen**. The `EOAAuth` object is created with the user's wallet address.
51
+ - [Passkey](./docs/walletprovider-sdk.passkeyauth.md) has 2 steps: **register** and **login**. The user registers a passkey with the network, then logs in with the passkey while starting the **keygen** process.
58
52
 
59
- - [PasskeyAuth](./docs/walletprovider-sdk.passkeyauth.md) to authenticate the user **during keygen**. The `PasskeyAuth` object is created with the [PasskeyUser](./docs/walletprovider-sdk.passkeyuser.md), [RelyingPartyConfig](./docs/walletprovider-sdk.relyingpartyconfig.md).
60
53
 
61
- - The ephemeral public key and lifetime of the key in seconds will be associated with both `EOAAuth` and `PasskeyAuth` objects.
54
+ The [ephemeral public claim](./docs/walletprovider-sdk.eoaauth.ephclaim.md) will be associated with both [EOAAuth](./docs/walletprovider-sdk.eoaauth.md) and [PasskeyAuth](./docs/walletprovider-sdk.passkeyauth.md) objects.
62
55
 
63
- Signature generation:
64
- - [EphAuth](./docs/walletprovider-sdk.ephauth.md) to authenticate the user **during signing**. The `EphAuth` object is created with the ephemeral keypair.
56
+ - Users will use [EphAuth](./docs/walletprovider-sdk.ephauth.md) to do non-interactive authenticate **during signing**.
57
+ - The library supports 2 signing algorithms for ephemeral signing keys: `secp256k1, ed25519`
65
58
 
66
59
  ## Keygen
67
60
 
68
-
69
- The full working example is in the [demo](https://github.com/silence-laboratories/walletprovider-sdk/blob/a75d7a009fb4d3629d353d53f8c27c34190c9035/demo/src/routes/%2Bpage.svelte#L89).
61
+ The full working example is in the [demo](https://github.com/silence-laboratories/walletprovider-sdk/blob/main/demo/src/routes/%2Bpage.svelte#L172).
70
62
  The core object to use is the [NetworkSigner](./docs/walletprovider-sdk.networksigner.md). It allows to generate keys and do signatures.
71
63
 
72
- In order to create your keys, you need two other components. The [WalletProviderServiceClient](./docs/walletprovider-sdk.walletproviderserviceclient.md) that connects to the Backend part of the SDK, and the **authentication module**.
64
+ In order to create your keys, you need two other components. The [WalletProviderServiceClient](./docs/walletprovider-sdk.walletproviderserviceclient.md) that connects to the Backend part of the SDK, and the **authenticator module**.
73
65
 
74
66
  ### Authenticate with EOA wallet
75
67
  We provide EOA authentication via [EOAAuth](./docs/walletprovider-sdk.eoaauth.md) module. Let's create the `NetworkSigner` with associated `EOAAuth` object.
76
68
 
77
69
  ```ts
70
+ const algSign = 'secp256k1'; // Signing algorithms of ephemeral key
78
71
  // Generate ephemeral secret key esk
79
- const sk = generateEphPrivateKey();
72
+ const sk = generateEphPrivateKey(algSign);
80
73
  // Derive public part epk from esk
81
- const ephPK = getEphPublicKey(sk);
74
+ const ephPK = getEphPublicKey(sk, algSign);
82
75
  // Arbitrary ID to identify the ephemeral key
83
76
  const ephId = uuidv4();
84
- // Create a client that connects to the backend service
85
- const wpClient = await createWalletProviderService(clusterConfig);
77
+ // Create ephemeral key claim instance based on the ephemeral key
78
+ const ephClaim = new EphKeyClaim(
79
+ ephId,
80
+ ephPK,
81
+ algSign,
82
+ // Lifetime of one hour
83
+ 60 * 60,
84
+ );
86
85
 
87
86
  // Create EOA authenticator, signature will include epk
88
87
  const eoaAuth = new EOAAuth(
89
- ephId,
90
88
  accountsFromBrowserWallet[0],
91
89
  new BrowserWallet(),
92
- ephPK,
93
- // Lifetime of one hour
94
- 60 * 60,
90
+ ephClaim
95
91
  );
96
92
 
93
+ // Create a client that connects to the backend service
94
+ const wpClient = await createWalletProviderService(clusterConfig);
95
+
97
96
  // Create a new signer instance
98
97
  const sdk = new NetworkSigner(wpClient, threshold, partiesNumber, eoaAuth);
99
98
  ```
100
99
 
101
- Now you can generate a key, using the [generateKey](./docs/walletprovider-sdk.networksigner.authenticateandcreatekey.md) method. The method accepts optional permissions. No permissions means _allow all operations_.
100
+ Now you can generate a key, using the [generateKey](./docs/walletprovider-sdk.networksigner.generatekey.md) method. The method accepts optional permissions. No permissions means _allow all operations_.
102
101
 
103
102
  ```ts
104
103
  const permissions = {
@@ -120,22 +119,52 @@ const permissions = {
120
119
  let resp: KeygenResponse = await sdk.generateKey(JSON.stringify(permissions));
121
120
  ```
122
121
 
123
- Calling this method will cause to the Browser Wallet window to pop up, requesting the User to sign the request.
122
+ Calling this method will cause to the Digital Wallet window to pop up, requesting the User to sign the request.
124
123
 
125
124
  The returned [KeygenResponse](./docs/walletprovider-sdk.keygenresponse.md) contains `keyId` and `publicKey`. The `publicKey` is the public part of the key generated by Silent Network. Use the `keyId` in subsequent calls to sign.
126
125
 
127
- The `esk` key can be later used by the frontend in subsequent signgen requests for authenticating.
126
+ The ephemeral `sk` key can be later used in subsequent signgen requests for authenticating.
128
127
 
129
128
  ### Authenticate with Passkey
130
- We provide Passkey authentication via [PasskeyAuth](./docs/walletprovider-sdk.passkeyauth.md) module. Let's create the `NetworkSigner` with associated `PasskeyAuth` object.
129
+ First, we need to register user passkey to the network. We provide Passkey register via [PasskeyRegister](./docs/walletprovider-sdk.passkeyregister.md) module.
130
+ ```ts
131
+ const wpClient = await createWalletProviderService(clusterConfig);
132
+ const rpConfig: RelyingPartyConfig = {
133
+ rpId: 'localhost',
134
+ rpName: 'http://localhost:5173',
135
+ };
136
+ const userId = uuidv4();
137
+ const passkeyUser = {
138
+ id: userId,
139
+ displayName: 'Alice',
140
+ name: 'alice@gmail.com ' + userId, // For development purposes
141
+ };
142
+
143
+ const passkeyAuth = new PasskeyRegister(rpConfig, passkeyUser);
144
+ // Create a new signer instance
145
+ const sdk = new NetworkSigner(wpClient, +threshold, +partiesNumber, passkeyAuth);
146
+
147
+ // Register a new passkey
148
+ let resp: RegisterPasskeyResponse = await sdk.registerPasskey();
149
+ ```
150
+
151
+ We provide Passkey login authentication via [PasskeyAuth](./docs/walletprovider-sdk.passkeyauth.md) module. Let's create the `NetworkSigner` with associated `PasskeyAuth` object.
131
152
 
132
153
  ```ts
154
+ const algSign = 'secp256k1'; // Signing algorithms of ephemeral key
133
155
  // Generate ephemeral secret key esk
134
- const sk = generateEphPrivateKey();
156
+ const sk = generateEphPrivateKey(algSign);
135
157
  // Derive public part epk from esk
136
- const ephPK = getEphPublicKey(sk);
158
+ const ephPK = getEphPublicKey(sk, algSign);
137
159
  // Arbitrary ID to identify the ephemeral key
138
160
  const ephId = uuidv4();
161
+ // Create ephemeral key claim instance based on the ephemeral key
162
+ const ephClaim = new EphKeyClaim(
163
+ ephId,
164
+ ephPK,
165
+ // Lifetime of one hour
166
+ 60 * 60,
167
+ );
139
168
  // Create a client that connects to the backend service
140
169
  const wpClient = await createWalletProviderService(clusterConfig);
141
170
  // Here we configure the relying party for local development
@@ -143,50 +172,40 @@ const rpConfig: RelyingPartyConfig = {
143
172
  rpId: 'localhost',
144
173
  rpName: 'http://localhost:5173',
145
174
  };
146
- // Information about the owner of the passkey
147
- const passkeyUser: PasskeyUser = {
148
- id: userId,
149
- displayName: 'Alice',
150
- name: 'alice@gmail.com ' + userId, // For development purposes
151
- };
152
175
 
153
176
  // Get passkey credential id from your storage
154
177
  const credentialId = getPasskeyCredentialId();
155
- // Create EOA authenticator, signature will include epk
178
+ // Create Passkey authenticator, signature will include epk
156
179
  const passkeyAuth = new PasskeyAuth(
157
180
  rpConfig,
158
- passkeyUser,
159
- ephId,
160
- ephPK,
161
- // Lifetime of one hour
162
- 60 * 60,
163
- // If credentialId is null, we will do passkey register, otherwise, we will do passkey auth/login
181
+ // We will do passkey auth/login with the provided credentialId
164
182
  credentialId,
183
+ ephClaim,
165
184
  );
166
185
 
167
186
  // Create a new signer instance
168
187
  const sdk = new NetworkSigner(wpClient, threshold, partiesNumber, passkeyAuth);
169
188
  ```
170
189
 
171
- Now you can generate a key like in the EOA example by calling the [generateKey](./docs/walletprovider-sdk.networksigner.authenticateandcreatekey.md) method.
190
+ Now you can generate a key like in the EOA example by calling the [generateKey](./docs/walletprovider-sdk.networksigner.generatekey.md) method.
172
191
 
173
- Calling this method will prompt the browser to request Passkey User Verification. Once user verification is done, the [KeygenResponse](./docs/walletprovider-sdk.keygenresponse.md) is returned.
192
+ Calling this method will prompt the device to request [Passkey User Verification](https://web.dev/articles/webauthn-user-verification). Once user verification is done, the [KeygenResponse](./docs/walletprovider-sdk.keygenresponse.md) is returned.
174
193
 
175
- The `esk` key can be later used by the frontend in subsequent signgen requests for authenticating.
194
+ The `sk` key can be later used in subsequent signgen requests.
176
195
 
177
196
  ## Signing
178
197
 
179
- The full signing example is [here](https://github.com/silence-laboratories/walletprovider-sdk/blob/a75d7a009fb4d3629d353d53f8c27c34190c9035/demo/src/routes/%2Bpage.svelte#L170).
198
+ The full signing example is [here](https://github.com/silence-laboratories/walletprovider-sdk/blob/main/demo/src/routes/%2Bpage.svelte#L228).
180
199
 
181
- Let's create NetworkSigner for signing. Note the `EphAuth` is used to avoid user interaction when generating the signatures.
200
+ The workflow is similar to the keygen process. The core objects to use are the [NetworkSigner](./docs/walletprovider-sdk.networksigner.md), WalletProviderServiceClient, and the [ephemeral authenticator module](./docs/walletprovider-sdk.ephauth.md).
182
201
  ```ts
183
- const authModule = new EphAuth(ephId, ephSK);
202
+ const authModule = new EphAuth(selectedEphId, ephSK, selectedEphSignAlg);
184
203
  // Create a new signer instance
185
204
  const sdk = new NetworkSigner(wpClient, threshold, partiesNumber, authModule);
186
205
  ```
187
206
 
188
207
 
189
- Use the [NetworkSigner.signMessage](./docs/walletprovider-sdk.networksigner.authenticateandsign.md) method in order to generate a signature.
208
+ Use the [NetworkSigner.signMessage](./docs/walletprovider-sdk.networksigner.signMessage.md) method in order to generate a signature.
190
209
 
191
210
  ```ts
192
211
  let signMessage = JSON.stringify({
@@ -215,16 +234,12 @@ let resp = await sdk.signMessage(selectedKeyId, signMessage);
215
234
 
216
235
  The [SignResponse](./docs/walletprovider-sdk.signresponse.md) contains the signature `sign` and the recovery ID `recid`.
217
236
 
237
+ # Development
218
238
 
219
- ## Install dependencies
220
-
221
- ```bash
222
- npm install
223
- ```
224
-
225
- ## Build
239
+ ## Build the library
226
240
 
227
241
  ```bash
242
+ npm i
228
243
  npm run build
229
244
  ```
230
245
 
@@ -233,14 +248,14 @@ The output will be in the `dist` folder.
233
248
  ## End to end tests
234
249
  Please refer to [README.md](./e2e-tests/README.md) for instructions how to execute them.
235
250
 
236
- ## Format the code
251
+ ## Generate the documentation
237
252
 
238
253
  ```bash
239
- npm run format
254
+ npm run docs
240
255
  ```
241
256
 
242
- ## Generate the documentation
257
+ ## Lint the code
243
258
 
244
259
  ```bash
245
- npm run docs
260
+ ./local_ci.sh
246
261
  ```
@@ -1,10 +1,10 @@
1
1
  /** Externally Owned Account (EOA) atuhentication. Uses secret key stored on a wallet to sign requests.
2
2
  * The requests are presented to the user in a readable form by using TypedData (EIP712).
3
3
  */
4
- import { KeygenSetupOpts } from './networkSigner';
4
+ import { MetadataSetupOpts, KeygenSetupOpts } from './setupMessage';
5
5
  import { type UserAuthentication } from './authentication';
6
6
  import { type TypedDataDomain } from 'viem';
7
- import { EphClaim } from './ephemeralAuthentication';
7
+ import { EphKeyClaim } from './ephemeralAuthentication';
8
8
  export type FieldDefinition = {
9
9
  name: string;
10
10
  type: string;
@@ -45,13 +45,23 @@ export interface IBrowserWallet {
45
45
  */
46
46
  signTypedData<T>(from: string, request: TypedData<T>): Promise<unknown>;
47
47
  }
48
+ type RequestToSign<T> = {
49
+ setup: T;
50
+ challenge: string;
51
+ };
52
+ export declare const EIP712SilentShardAuthenticationDomain: {
53
+ name: string;
54
+ version: string;
55
+ };
56
+ export declare function createTypedRequest(setup: KeygenSetupOpts | MetadataSetupOpts, aggregated_challenge: string, ephClaim: EphKeyClaim): TypedData<RequestToSign<KeygenSetupOpts | MetadataSetupOpts>>;
48
57
  /** Present the request to the User using wallet UI, and ask for sign.
49
58
  * The signature is the authorization for keygen operation
50
59
  */
51
60
  export declare function authenticateUsingEOA({ setup, eoa, challenge, browserWallet, ephClaim, }: {
52
- setup: KeygenSetupOpts;
61
+ setup: KeygenSetupOpts | MetadataSetupOpts;
53
62
  eoa: string;
54
63
  challenge: string;
55
64
  browserWallet: IBrowserWallet;
56
- ephClaim: EphClaim;
65
+ ephClaim: EphKeyClaim;
57
66
  }): Promise<UserAuthentication>;
67
+ export {};
@@ -1,7 +1,7 @@
1
- import { AddEphemeralKeyOpts, KeygenSetupOpts, SignSetupOpts } from './networkSigner';
1
+ import { MetadataSetupOpts, KeygenSetupOpts, SignSetupOpts } from './setupMessage';
2
2
  import { IBrowserWallet } from './EOAauthentication';
3
3
  import { PasskeyUser, RelyingPartyConfig } from './passkeyAuthentication';
4
- import { EphClaim } from './ephemeralAuthentication';
4
+ import { EphKeyClaim, SignAlgorithm } from './ephemeralAuthentication';
5
5
  /** Type of the request authentication
6
6
  * @alpha
7
7
  */
@@ -16,12 +16,12 @@ export type UserAuthentication = {
16
16
  };
17
17
  export interface AuthModule {
18
18
  authenticate({ setup, challenge, }: {
19
- setup: KeygenSetupOpts | SignSetupOpts | AddEphemeralKeyOpts;
19
+ setup: KeygenSetupOpts | SignSetupOpts | MetadataSetupOpts;
20
20
  challenge: string;
21
21
  }): Promise<UserAuthentication>;
22
22
  }
23
23
  export interface DkgAuthModule extends AuthModule {
24
- get ephClaim(): EphClaim;
24
+ get ephClaim(): EphKeyClaim;
25
25
  }
26
26
  /** The `EOAAuth` implementing Externally Owned Account authentication.
27
27
  * @alpha
@@ -32,16 +32,14 @@ export declare class EOAAuth implements DkgAuthModule {
32
32
  /** the ETH address that is used to do EOA authentication */
33
33
  private eoa;
34
34
  /** Ephemeral key claim */
35
- ephClaim: EphClaim;
35
+ ephClaim: EphKeyClaim;
36
36
  /**
37
37
  *
38
- * @param ephId - Ephemeral key ID
39
38
  * @param eoa - Ethereum address
40
39
  * @param browserWallet - Interface to the wallet provider, like MetaMask, that is used to sign the requests
41
- * @param ephPK - Ephemeral public key
42
- * @param lifetime - Lifetime of the ephemeral key. Default is 1 hour
40
+ * @param ephClaim - EphKeyClaim instance
43
41
  */
44
- constructor(ephId: string, eoa: string, browserWallet: IBrowserWallet, ephPK: Uint8Array, lifetime: number);
42
+ constructor(eoa: string, browserWallet: IBrowserWallet, ephClaim: EphKeyClaim);
45
43
  private validateInputs;
46
44
  /**
47
45
  * Prepares a message to present on the Browser Wallet window and requests to sign it.
@@ -50,8 +48,8 @@ export declare class EOAAuth implements DkgAuthModule {
50
48
  *
51
49
  * @public
52
50
  */
53
- authenticate({ setup, challenge }: {
54
- setup: KeygenSetupOpts;
51
+ authenticate({ setup, challenge, }: {
52
+ setup: KeygenSetupOpts | MetadataSetupOpts;
55
53
  challenge: string;
56
54
  }): Promise<UserAuthentication>;
57
55
  }
@@ -70,8 +68,9 @@ export declare class EphAuth implements AuthModule {
70
68
  *
71
69
  * @param ephId - Ephemeral key ID
72
70
  * @param ephSK - Ephemeral secret key
71
+ * @param signAlg - Signature algorithm
73
72
  */
74
- constructor(ephId: string, ephSK: Uint8Array);
73
+ constructor(ephId: string, ephSK: Uint8Array, signAlg: SignAlgorithm);
75
74
  /**
76
75
  * Prepares a message to present on the Browser Wallet window and requests to sign it.
77
76
  * @param setup - Signgen setup options
@@ -79,8 +78,8 @@ export declare class EphAuth implements AuthModule {
79
78
  *
80
79
  * @public
81
80
  */
82
- authenticate({ setup, challenge }: {
83
- setup: SignSetupOpts;
81
+ authenticate({ setup, challenge, }: {
82
+ setup: SignSetupOpts | MetadataSetupOpts;
84
83
  challenge: string;
85
84
  }): Promise<UserAuthentication>;
86
85
  }
@@ -92,22 +91,36 @@ export declare class PasskeyAuth implements DkgAuthModule {
92
91
  private rpConfig;
93
92
  /** ID of the acceptable credential by user. App proves that user has passkey credential by passing the value of this field */
94
93
  private allowCredentialId;
94
+ /** Ephemeral key claim */
95
+ ephClaim: EphKeyClaim;
96
+ /**
97
+ *
98
+ * @param rpConfig - Passkey relying party configuration. Read more: https://developer.mozilla.org/en-US/docs/Web/API/PublicKeyCredentialCreationOptions#rp
99
+ * @param allowCredentialId - ID of the acceptable credential by user. App proves that user has passkey credential by passing the value of this field
100
+ * @param ephClaim - EphKeyClaim instance
101
+ */
102
+ constructor(rpConfig: RelyingPartyConfig, allowCredentialId: string, ephClaim: EphKeyClaim);
103
+ authenticate({ setup, challenge, }: {
104
+ setup: KeygenSetupOpts | MetadataSetupOpts;
105
+ challenge: string;
106
+ }): Promise<UserAuthentication>;
107
+ }
108
+ /** The `AuthModule` implementing Passkey register.
109
+ * @alpha
110
+ */
111
+ export declare class PasskeyRegister implements AuthModule {
112
+ /** Replying party object. Read more: https://developer.mozilla.org/en-US/docs/Web/API/PublicKeyCredentialCreationOptions#rp */
113
+ private rpConfig;
95
114
  /** Passkey user information, only requires while registering. Read more: https://developer.mozilla.org/en-US/docs/Web/API/PublicKeyCredentialCreationOptions#user */
96
115
  private user;
97
- /** Ephemeral key claim */
98
- ephClaim: EphClaim;
99
116
  /**
100
117
  *
101
118
  * @param rpConfig - Passkey relying party configuration. Read more: https://developer.mozilla.org/en-US/docs/Web/API/PublicKeyCredentialCreationOptions#rp
102
119
  * @param user - Passkey user information, only requires while registering. Read more: https://developer.mozilla.org/en-US/docs/Web/API/PublicKeyCredentialCreationOptions#user
103
- * @param allowCredentialId - ID of the acceptable credential by user. App proves that user has passkey credential by passing the value of this field
104
- * @param ephId - Ephemeral key ID
105
- * @param ephPK - Ephemeral public key
106
- * @param lifetime - Lifetime of the ephemeral key. Default is 1 hour
107
120
  */
108
- constructor(rpConfig: RelyingPartyConfig, user: PasskeyUser | null, allowCredentialId: string | null, ephId: string, ephPK: Uint8Array, lifetime: number);
121
+ constructor(rpConfig: RelyingPartyConfig, user: PasskeyUser);
109
122
  authenticate({ setup, challenge, }: {
110
- setup: KeygenSetupOpts | AddEphemeralKeyOpts;
123
+ setup: MetadataSetupOpts;
111
124
  challenge: string;
112
125
  }): Promise<UserAuthentication>;
113
126
  }
@@ -1,3 +1,4 @@
1
1
  export declare const decodeBase64: (b64: string) => Uint8Array;
2
2
  export declare const encodeBase64: (b: Uint8Array) => string;
3
3
  export declare const arrayBufferToBase64Url: (a: ArrayBuffer) => string;
4
+ export declare const calculateFinalChallenge: (setupOpts: string) => string;
@@ -1,10 +1,26 @@
1
1
  import { UserAuthentication } from './authentication';
2
- import { SignSetupOpts } from './networkSigner';
3
- export declare class EphClaim {
2
+ import { SignSetupOpts } from './setupMessage';
3
+ /**
4
+ * Supported signature algorithms for ephemeral key
5
+ * @alpha
6
+ */
7
+ export type SignAlgorithm = 'ed25519' | 'secp256k1';
8
+ /** The `EphKeyClaim` object represents the public claim of the ephemeral key.
9
+ * @alpha
10
+ */
11
+ export declare class EphKeyClaim {
4
12
  ephId: string;
5
13
  ephPK: string;
14
+ signAlg: SignAlgorithm;
6
15
  expiry: number;
7
- constructor(ephId: string, ephPK: Uint8Array, lifetime?: number);
16
+ /**
17
+ *
18
+ * @param ephId - Ephemeral key ID
19
+ * @param ephPK - Ephemeral public key
20
+ * @param signAlg - Signature algorithm.
21
+ * @param lifetime - Lifetime of the ephemeral key. Default is 1 hour
22
+ */
23
+ constructor(ephId: string, ephPK: Uint8Array, signAlg: SignAlgorithm, lifetime?: number);
8
24
  private validateInputs;
9
25
  toJSON(): string;
10
26
  }
@@ -15,7 +31,14 @@ export declare function authenticateUsingEphKey({ setup, challenge, ephSK, ephCl
15
31
  setup: SignSetupOpts;
16
32
  challenge: string;
17
33
  ephSK: Uint8Array;
18
- ephClaim: EphClaim;
34
+ ephClaim: EphKeyClaim;
19
35
  }): Promise<UserAuthentication>;
20
- export declare function generateEphPrivateKey(): Uint8Array;
21
- export declare function getEphPublicKey(ephSK: Uint8Array): Uint8Array;
36
+ export declare function genHexSignature(msg: Uint8Array, ephSK: Uint8Array, signAlg: SignAlgorithm): Promise<string>;
37
+ /** Generate Ephemeral `privateKey`
38
+ * @public
39
+ */
40
+ export declare function generateEphPrivateKey(algSign: SignAlgorithm): Uint8Array;
41
+ /** Derive Ephemeral `publicKey` from `privateKey` returned from `generateEphPrivateKey`
42
+ * @public
43
+ */
44
+ export declare function getEphPublicKey(ephSK: Uint8Array, algSign: SignAlgorithm): Uint8Array;
package/dist/index.cjs.js CHANGED
@@ -1 +1,6 @@
1
- "use strict";var S=Object.defineProperty;var Q=Object.getOwnPropertyDescriptor;var G=Object.getOwnPropertyNames;var z=Object.prototype.hasOwnProperty;var Y=(n,e,t)=>e in n?S(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t;var X=(n,e)=>{for(var t in e)S(n,t,{get:e[t],enumerable:!0})},Z=(n,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of G(e))!z.call(n,i)&&i!==t&&S(n,i,{get:()=>e[i],enumerable:!(r=Q(e,i))||r.enumerable});return n};var j=n=>Z(S({},"__esModule",{value:!0}),n);var s=(n,e,t)=>Y(n,typeof e!="symbol"?e+"":e,t);var se={};X(se,{EOAAuth:()=>I,EphAuth:()=>E,NetworkSigner:()=>C,PasskeyAuth:()=>K,WalletProviderServiceClient:()=>A,computeAddress:()=>V,generateEphPrivateKey:()=>q,getEphPublicKey:()=>B});module.exports=j(se);var U=require("js-base64");var R=n=>btoa(String.fromCodePoint.apply(null,Array.from(n))),c=n=>U.Base64.fromUint8Array(new Uint8Array(n),!0);var h=(n,e)=>{u(typeof e!="string",`${n} must be string`),u((e==null?void 0:e.trim().length)===0,`${n} cannot be empty`)},w=n=>{u(!(n instanceof Uint8Array),"key must be an Uint8Array"),u(n.length!==32,"ed25519: key length must be 32 bytes")},u=(n,e)=>{if(n)throw new Error(e)};var A=class{constructor(e){s(this,"walletProviderId");s(this,"walletProviderUrl");s(this,"passkeyCredentialId");this.walletProviderId=e.walletProviderId,this.walletProviderUrl=e.walletProviderUrl}getWalletId(){return this.walletProviderId}async startKeygen({setup:e,authModule:t}){return this.connect(e,t).then(r=>{var p,l;let i=r.split(":");u(i.length!==2,"Invalid keygen response from network");let a=(p=i[0])==null?void 0:p.split("=")[1];return{publicKey:(l=i[1])==null?void 0:l.split("=")[1],keyId:a,passkeyCredentialId:this.passkeyCredentialId}})}async startSigngen({setup:e,authModule:t}){return this.connect(e,t).then(r=>{var p,l;let i=r.split(":");u(i.length!==2,"Invalid signgen response from network");let a=(p=i[0])==null?void 0:p.split("=")[1],o=(l=i[1])==null?void 0:l.split("=")[1];if(a===void 0||o===void 0)throw new Error("Invalid signgen response from network");return{sign:a,recid:parseInt(o)}})}async addEphemeralKey({setup:e,authModule:t}){return this.connect(e,t).then(r=>({status:r}))}connect(e,t){return new Promise((r,i)=>{let a=0,o=e.queryPath;o==="signgen"&&(e.message=R(new TextEncoder().encode(e.message)));let p=new WebSocket(`${this.walletProviderUrl}/${o}`);p.addEventListener("open",l=>{switch(console.debug(`Connection opened in state ${a} with event ${JSON.stringify(l,void 0," ")}`),a){case 0:a=1,p.send(JSON.stringify(e));break;case 1:case 2:a=3,i("Incorrect protocol state");break;case 3:break}}),p.addEventListener("message",async l=>{switch(console.debug(`Connection message in state ${a} with event ${JSON.stringify(l,void 0," ")}`),a){case 0:a=3,i("Incorrect protocol state");break;case 1:{a=2;try{let d=await t.authenticate({setup:e,challenge:l.data});d.credentials.method==="passkey"&&(this.passkeyCredentialId=d.credentials.id),p.send(JSON.stringify(d))}catch(d){i(d)}break}case 2:a=3,p.close(),r(l.data);break;case 3:break}}),p.addEventListener("error",l=>{console.debug(`Connection error in state ${a} with event ${JSON.stringify(l,void 0," ")}`),a!=3&&(a=3,i("Incorrect protocol state"))}),p.addEventListener("close",l=>{console.debug(`Connection closed in state ${a} with event ${JSON.stringify(l,void 0," ")}`),a!=3&&(a=3,i("Incorrect protocol state"))})})}};var ee=1,T=2,te=3,M=[{name:"tag",type:"uint16"},{name:"value",type:"string"}],g=class{constructor({t:e,n:t,key_label:r,permissions:i}){s(this,"t");s(this,"n");s(this,"key_label");s(this,"metadata");this.t=e,this.n=t,r&&(this.key_label=r),this.metadata=[],i&&this.metadata.push({tag:ee,value:i})}set ephClaim(e){this.metadata.push({tag:T,value:e.toJSON()})}get queryPath(){return"keygen"}get requestSchema(){return{Request:[{name:"setup",type:"KeygenSetupOpts"},{name:"challenge",type:"string"}],KeygenSetupOpts:[{name:"t",type:"uint32"},{name:"n",type:"uint32"},{name:"metadata",type:"TaggedValue[]"}],TaggedValue:M}}},b=class{constructor({t:e,key_id:t,message:r}){s(this,"t");s(this,"key_id");s(this,"message");this.t=e,this.key_id=t,this.message=r}get queryPath(){return"signgen"}},f=class{constructor({n:e,key_id:t}){s(this,"n");s(this,"key_id");s(this,"metadata");this.n=e,this.key_id=t,this.metadata=[],this.metadata.push({tag:te,value:t})}set ephClaim(e){this.metadata.push({tag:T,value:e.toJSON()})}get queryPath(){return"addEphemeralKey"}get requestSchema(){return{Request:[{name:"setup",type:"AddEphemeralKeyOpts"},{name:"challenge",type:"string"}],AddEphemeralKeyOpts:[{name:"n",type:"uint32"},{name:"metadata",type:"TaggedValue[]"}],TaggedValue:M}}},C=class{constructor(e,t,r,i){s(this,"authModule");s(this,"threshold");s(this,"totalNodes");s(this,"wp_client");u(t<2,`Threshold = ${t} must be at least 2`),u(r<t,`Total nodes = ${r} must be greater or equal to threshold = ${t}`),this.threshold=t,this.totalNodes=r,this.authModule=i,this.wp_client=e}async generateKey(e){let t=new g({t:this.threshold,n:this.totalNodes,permissions:e,key_label:void 0});return this.setEphClaimOf(t),await this.wp_client.startKeygen({setup:t,authModule:this.authModule})}async signMessage(e,t){h("keyId",e),h("message",t);let r=new b({t:this.threshold,key_id:e,message:t});return await this.wp_client.startSigngen({setup:r,authModule:this.authModule})}async addEphemeralKey(e){h("keyId",e);let t=new f({n:this.totalNodes,key_id:e});return this.setEphClaimOf(t),await this.wp_client.addEphemeralKey({setup:t,authModule:this.authModule})}setEphClaimOf(e){e.ephClaim=this.authModule.ephClaim}};var ne={name:"SilentShard authentication",version:"0.1.0"},re=[{name:"name",type:"string"},{name:"version",type:"string"}];function ie(n,e,t){let r;return n instanceof g?r=new g({t:n.t,n:n.n,key_label:n.key_label,permissions:void 0}):r=new f({n:n.n,key_id:n.key_id}),r.ephClaim=t,{types:{EIP712Domain:re,...n.requestSchema},domain:ne,primaryType:"Request",message:{setup:r,challenge:e}}}async function N({setup:n,eoa:e,challenge:t,browserWallet:r,ephClaim:i}){let a=ie(n,t,i),o=await r.signTypedData(e,a);return{credentials:{credentials:i.toJSON(),method:"eoa",id:e},signature:o}}var W=require("@noble/curves/ed25519");var O=require("js-base64"),k=require("viem");async function D({user:n,challenge:e,rpConfig:t,ephClaim:r}){let i=(0,k.hexToBytes)(`0x${e}`,{size:32}),a={publicKey:{authenticatorSelection:{residentKey:"preferred",userVerification:"required"},challenge:i,excludeCredentials:[],pubKeyCredParams:[{type:"public-key",alg:-7},{type:"public-key",alg:-257}],rp:{name:t.rpName,id:t.rpId},user:{...n,id:O.Base64.toUint8Array(n.id)}}},o=await navigator.credentials.create(a);if(o===null)throw new Error("No credential returned");let p=c(o.response.attestationObject),d={rawCredential:JSON.stringify({authenticatorAttachment:o.authenticatorAttachment,id:o.id,rawId:c(o.rawId),response:{attestationObject:p,clientDataJSON:c(o.response.clientDataJSON)},type:o.type}),origin:t.rpName,rpId:t.rpId};return{credentials:{credentials:r.toJSON(),method:"passkey",id:o.id},signature:JSON.stringify(d)}}async function J({challenge:n,allowCredentialId:e,rpConfig:t,ephClaim:r}){let i=(0,k.hexToBytes)(`0x${n}`,{size:32}),a=e?[{type:"public-key",id:O.Base64.toUint8Array(e)}]:[],o={publicKey:{userVerification:"required",challenge:i,allowCredentials:a}},p=await navigator.credentials.get(o);if(p===null)throw new Error("Failed to get navigator credentials");let l=p.response,d=l.userHandle;if(d===null)throw new Error("User handle cannot be null");let H=c(l.signature),L={rawCredential:JSON.stringify({authenticatorAttachment:p.authenticatorAttachment,id:p.id,rawId:c(p.rawId),response:{authenticatorData:c(l.authenticatorData),clientDataJSON:c(l.clientDataJSON),signature:H,userHandle:c(d)},type:p.type}),origin:t.rpName,rpId:t.rpId};return{credentials:{credentials:r.toJSON(),method:"passkey",id:p.id},signature:JSON.stringify(L)}}var x=require("viem"),P=require("@noble/curves/ed25519");var m=class{constructor(e,t,r=3600){s(this,"ephId");s(this,"ephPK");s(this,"expiry");this.validateInputs(e,t,r),this.ephId=e,this.ephPK=(0,x.toHex)(t),this.expiry=Math.floor(Date.now()/1e3)+r}validateInputs(e,t,r){h("ephId",e),w(t),u(Number.isInteger(r)===!1,"lifetime must be an integer");let i=r>0&&r<=365*24*60*60;u(!i,"lifetime must be greater than 0 and less than or equal to 365 days")}toJSON(){return JSON.stringify({ephId:this.ephId,ephPK:this.ephPK,expiry:this.expiry})}};async function _({setup:n,challenge:e,ephSK:t,ephClaim:r}){let i={setup:n,challenge:e},a=new TextEncoder,o=(0,x.toHex)(P.ed25519.sign(a.encode(JSON.stringify(i)),t));return{credentials:{credentials:r.toJSON(),method:"ephemeral",id:r.ephId},signature:o}}function q(){return P.ed25519.utils.randomPrivateKey()}function B(n){return P.ed25519.getPublicKey(n)}var $=require("viem");var I=class{constructor(e,t,r,i,a){s(this,"browserWallet");s(this,"eoa");s(this,"ephClaim");this.validateInputs(t,r),this.ephClaim=new m(e,i,a),this.browserWallet=r,this.eoa=t}validateInputs(e,t){u(!(0,$.isAddress)(e),"invalid Ethereum address format"),u(!((t==null?void 0:t.signTypedData)instanceof Function),"invalid browserWallet")}async authenticate({setup:e,challenge:t}){return await N({setup:e,eoa:this.eoa,challenge:t,browserWallet:this.browserWallet,ephClaim:this.ephClaim})}},E=class{constructor(e,t){s(this,"ephSK");s(this,"ephClaim");w(t),this.ephSK=t;let r=W.ed25519.getPublicKey(this.ephSK);this.ephClaim=new m(e,r)}async authenticate({setup:e,challenge:t}){return await _({setup:e,challenge:t,ephSK:this.ephSK,ephClaim:this.ephClaim})}},K=class{constructor(e,t,r,i,a,o){s(this,"rpConfig");s(this,"allowCredentialId");s(this,"user");s(this,"ephClaim");this.ephClaim=new m(i,a,o),this.rpConfig=e,this.user=t,this.allowCredentialId=r}async authenticate({setup:e,challenge:t}){let r=e.queryPath==="addEphemeralKey";if(this.allowCredentialId||r)return await J({allowCredentialId:this.allowCredentialId,challenge:t,rpConfig:this.rpConfig,ephClaim:this.ephClaim});if(this.user)return await D({user:this.user,challenge:t,rpConfig:this.rpConfig,ephClaim:this.ephClaim});throw new Error("Invalid arguments for passkey authentication")}};var v=require("viem/accounts"),F=require("@noble/curves/secp256k1");var y=require("viem");function V(n){if(n.startsWith("0x")&&(n=n.slice(2)),n.startsWith("04"))return(0,v.publicKeyToAddress)(`0x${n} `);if(n.startsWith("02")||n.startsWith("03")){let e=F.secp256k1.ProjectivePoint.fromHex(n).toHex(!1);return(0,v.publicKeyToAddress)(`0x${e}`)}else throw new Error("Invalid public key")}0&&(module.exports={EOAAuth,EphAuth,NetworkSigner,PasskeyAuth,WalletProviderServiceClient,computeAddress,generateEphPrivateKey,getEphPublicKey});
1
+ "use strict";var R=Object.defineProperty;var St=Object.getOwnPropertyDescriptor;var xt=Object.getOwnPropertyNames;var wt=Object.prototype.hasOwnProperty;var bt=(n,t,e)=>t in n?R(n,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):n[t]=e;var At=(n,t)=>{for(var e in t)R(n,e,{get:t[e],enumerable:!0})},Pt=(n,t,e,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of xt(t))!wt.call(n,r)&&r!==e&&R(n,r,{get:()=>t[r],enumerable:!(i=St(t,r))||i.enumerable});return n};var Ct=n=>Pt(R({},"__esModule",{value:!0}),n);var p=(n,t,e)=>bt(n,typeof t!="symbol"?t+"":t,e);var Bt={};At(Bt,{EOAAuth:()=>b,EphAuth:()=>I,EphKeyClaim:()=>w,NetworkSigner:()=>U,PasskeyAuth:()=>A,PasskeyRegister:()=>E,WalletProviderServiceClient:()=>M,computeAddress:()=>_,default:()=>Tt,generateEphPrivateKey:()=>J,getEphPublicKey:()=>v});module.exports=Ct(Bt);var Ot=1,et=2,F=3,nt=[{name:"tag",type:"uint16"},{name:"value",type:"string"}],m=class{constructor({t,n:e,key_label:i,permissions:r}){p(this,"t");p(this,"n");p(this,"key_label");p(this,"metadata");this.t=t,this.n=e,i&&(this.key_label=i),this.metadata=[],r&&this.metadata.push({tag:Ot,value:r})}set ephClaim(t){this.metadata.push({tag:et,value:t.toJSON()})}get requestSchema(){return{Request:[{name:"setup",type:"KeygenSetupOpts"},{name:"challenge",type:"string"}],KeygenSetupOpts:[{name:"t",type:"uint32"},{name:"n",type:"uint32"},{name:"metadata",type:"TaggedValue[]"}],TaggedValue:nt}}},k=class{constructor({t,key_id:e,message:i}){p(this,"t");p(this,"key_id");p(this,"message");this.t=t,this.key_id=e,this.message=i}},d=class{constructor(){p(this,"metadata");this.metadata=[]}set ephClaim(t){this.metadata.push({tag:et,value:t.toJSON()})}set keyId(t){this.metadata.push({tag:F,value:t})}extractMetadataByTag(t){let e=this.metadata.find(i=>i.tag===t);if(e)return e.value;throw new Error(`Tag ${t} not found in metadata`)}get requestSchema(){return{Request:[{name:"setup",type:"MetadataSetupOpts"},{name:"challenge",type:"string"}],MetadataSetupOpts:[{name:"metadata",type:"TaggedValue[]"}],TaggedValue:nt}}};var kt={name:"SilentShard authentication",version:"0.1.0"},vt=[{name:"name",type:"string"},{name:"version",type:"string"}];function It(n,t,e){let i;return n instanceof m?i=new m({t:n.t,n:n.n,key_label:n.key_label,permissions:void 0}):(i=new d,i.keyId=n.extractMetadataByTag(F)),i.ephClaim=e,{types:{EIP712Domain:vt,...n.requestSchema},domain:kt,primaryType:"Request",message:{setup:i,challenge:t}}}async function it({setup:n,eoa:t,challenge:e,browserWallet:i,ephClaim:r}){let o=It(n,e,r),s=await i.signTypedData(t,o);return{credentials:{credentials:r.toJSON(),method:"eoa",id:t},signature:s}}var ct=require("js-base64");function Et(n){return n instanceof Uint8Array||ArrayBuffer.isView(n)&&n.constructor.name==="Uint8Array"}function q(n,...t){if(!Et(n))throw new Error("Uint8Array expected");if(t.length>0&&!t.includes(n.length))throw new Error("Uint8Array expected of length "+t+", got length="+n.length)}function H(n,t=!0){if(n.destroyed)throw new Error("Hash instance has been destroyed");if(t&&n.finished)throw new Error("Hash#digest() has already been called")}function st(n,t){q(n);let e=t.outputLen;if(n.length<e)throw new Error("digestInto() expects output buffer of length at least "+e)}var B=n=>new DataView(n.buffer,n.byteOffset,n.byteLength),f=(n,t)=>n<<32-t|n>>>t;function Ut(n){if(typeof n!="string")throw new Error("utf8ToBytes expected string, got "+typeof n);return new Uint8Array(new TextEncoder().encode(n))}function G(n){return typeof n=="string"&&(n=Ut(n)),q(n),n}var T=class{clone(){return this._cloneInto()}};function rt(n){let t=i=>n().update(G(i)).digest(),e=n();return t.outputLen=e.outputLen,t.blockLen=e.blockLen,t.create=()=>n(),t}function Mt(n,t,e,i){if(typeof n.setBigUint64=="function")return n.setBigUint64(t,e,i);let r=BigInt(32),o=BigInt(4294967295),s=Number(e>>r&o),a=Number(e&o),c=i?4:0,u=i?0:4;n.setUint32(t+c,s,i),n.setUint32(t+u,a,i)}var ot=(n,t,e)=>n&t^~n&e,at=(n,t,e)=>n&t^n&e^t&e,N=class extends T{constructor(t,e,i,r){super(),this.blockLen=t,this.outputLen=e,this.padOffset=i,this.isLE=r,this.finished=!1,this.length=0,this.pos=0,this.destroyed=!1,this.buffer=new Uint8Array(t),this.view=B(this.buffer)}update(t){H(this);let{view:e,buffer:i,blockLen:r}=this;t=G(t);let o=t.length;for(let s=0;s<o;){let a=Math.min(r-this.pos,o-s);if(a===r){let c=B(t);for(;r<=o-s;s+=r)this.process(c,s);continue}i.set(t.subarray(s,s+a),this.pos),this.pos+=a,s+=a,this.pos===r&&(this.process(e,0),this.pos=0)}return this.length+=t.length,this.roundClean(),this}digestInto(t){H(this),st(t,this),this.finished=!0;let{buffer:e,view:i,blockLen:r,isLE:o}=this,{pos:s}=this;e[s++]=128,this.buffer.subarray(s).fill(0),this.padOffset>r-s&&(this.process(i,0),s=0);for(let l=s;l<r;l++)e[l]=0;Mt(i,r-8,BigInt(this.length*8),o),this.process(i,0);let a=B(t),c=this.outputLen;if(c%4)throw new Error("_sha2: outputLen should be aligned to 32bit");let u=c/4,g=this.get();if(u>g.length)throw new Error("_sha2: outputLen bigger than state");for(let l=0;l<u;l++)a.setUint32(4*l,g[l],o)}digest(){let{buffer:t,outputLen:e}=this;this.digestInto(t);let i=t.slice(0,e);return this.destroy(),i}_cloneInto(t){t||(t=new this.constructor),t.set(...this.get());let{blockLen:e,buffer:i,length:r,finished:o,destroyed:s,pos:a}=this;return t.length=r,t.pos=a,t.finished=o,t.destroyed=s,r%e&&t.buffer.set(i),t}};var Kt=new Uint32Array([1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298]),S=new Uint32Array([1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225]),x=new Uint32Array(64),z=class extends N{constructor(){super(64,32,8,!1),this.A=S[0]|0,this.B=S[1]|0,this.C=S[2]|0,this.D=S[3]|0,this.E=S[4]|0,this.F=S[5]|0,this.G=S[6]|0,this.H=S[7]|0}get(){let{A:t,B:e,C:i,D:r,E:o,F:s,G:a,H:c}=this;return[t,e,i,r,o,s,a,c]}set(t,e,i,r,o,s,a,c){this.A=t|0,this.B=e|0,this.C=i|0,this.D=r|0,this.E=o|0,this.F=s|0,this.G=a|0,this.H=c|0}process(t,e){for(let l=0;l<16;l++,e+=4)x[l]=t.getUint32(e,!1);for(let l=16;l<64;l++){let P=x[l-15],O=x[l-2],tt=f(P,7)^f(P,18)^P>>>3,W=f(O,17)^f(O,19)^O>>>10;x[l]=W+x[l-7]+tt+x[l-16]|0}let{A:i,B:r,C:o,D:s,E:a,F:c,G:u,H:g}=this;for(let l=0;l<64;l++){let P=f(a,6)^f(a,11)^f(a,25),O=g+P+ot(a,c,u)+Kt[l]+x[l]|0,W=(f(i,2)^f(i,13)^f(i,22))+at(i,r,o)|0;g=u,u=c,c=a,a=s+O|0,s=o,o=r,r=i,i=O+W|0}i=i+this.A|0,r=r+this.B|0,o=o+this.C|0,s=s+this.D|0,a=a+this.E|0,c=c+this.F|0,u=u+this.G|0,g=g+this.H|0,this.set(i,r,o,s,a,c,u,g)}roundClean(){x.fill(0)}destroy(){this.set(0,0,0,0,0,0,0,0),this.buffer.fill(0)}};var Q=rt(()=>new z);var D=require("viem");var Y=n=>btoa(String.fromCodePoint.apply(null,Array.from(n))),y=n=>ct.Base64.fromUint8Array(new Uint8Array(n),!0),pt=n=>{let t=(0,D.stringToBytes)(n),e=Q(Q(t));return(0,D.toHex)(e,{size:32}).slice(2)};var j=require("js-base64"),X=require("viem");async function ut({user:n,challenge:t,rpConfig:e}){let i=(0,X.hexToBytes)(`0x${t}`,{size:32}),r={publicKey:{authenticatorSelection:{residentKey:"preferred",userVerification:"required"},challenge:i,excludeCredentials:[],pubKeyCredParams:[{type:"public-key",alg:-7},{type:"public-key",alg:-257}],rp:{name:e.rpName,id:e.rpId},user:{...n,id:j.Base64.toUint8Array(n.id)}}},o=await navigator.credentials.create(r);if(o===null)throw new Error("No credential returned");let s=y(o.response.attestationObject),c={rawCredential:JSON.stringify({authenticatorAttachment:o.authenticatorAttachment,id:o.id,rawId:y(o.rawId),response:{attestationObject:s,clientDataJSON:y(o.response.clientDataJSON)},type:o.type}),origin:e.rpName,rpId:e.rpId};return{credentials:{credentials:"",method:"passkey",id:o.id},signature:JSON.stringify(c)}}async function lt({challenge:n,allowCredentialId:t,rpConfig:e,ephClaim:i}){let r=(0,X.hexToBytes)(`0x${n}`,{size:32}),o=t?[{type:"public-key",id:j.Base64.toUint8Array(t)}]:[],s={publicKey:{userVerification:"required",challenge:r,allowCredentials:o}},a=await navigator.credentials.get(s);if(a===null)throw new Error("Failed to get navigator credentials");let c=a.response,u=c.userHandle;if(u===null)throw new Error("User handle cannot be null");let g=y(c.signature),P={rawCredential:JSON.stringify({authenticatorAttachment:a.authenticatorAttachment,id:a.id,rawId:y(a.rawId),response:{authenticatorData:y(c.authenticatorData),clientDataJSON:y(c.clientDataJSON),signature:g,userHandle:y(u)},type:a.type}),origin:e.rpName,rpId:e.rpId};return{credentials:{credentials:i.toJSON(),method:"passkey",id:a.id},signature:JSON.stringify(P)}}var V=require("viem"),L=require("@noble/curves/ed25519"),Z=require("@noble/curves/secp256k1");var C=(n,t)=>{h(typeof t!="string",`${n} must be string`),h((t==null?void 0:t.trim().length)===0,`${n} cannot be empty`)},ht=(n,t)=>{h(!(n instanceof Uint8Array),"key must be an Uint8Array"),t==="secp256k1"&&h(n.length!==65,"secp256k1: key length must be 65 bytes, got "+n.length),t==="ed25519"&&h(n.length!==32,"ed25519: key length must be 32 bytes, got "+n.length)},dt=(n,t)=>{h(!(n instanceof Uint8Array),"key must be an Uint8Array"),t==="secp256k1"&&h(n.length!==32,"secp256k1: key length must be 32 bytes, got "+n.length),t==="ed25519"&&h(n.length!==32,"ed25519: key length must be 32 bytes, got "+n.length)};var h=(n,t)=>{if(n)throw new Error(t)};var gt=require("viem/accounts");var w=class{constructor(t,e,i,r=3600){p(this,"ephId");p(this,"ephPK");p(this,"signAlg");p(this,"expiry");this.validateInputs(t,e,i,r),this.ephId=t,this.ephPK=(0,V.toHex)(e),this.signAlg=i,this.expiry=Math.floor(Date.now()/1e3)+r}validateInputs(t,e,i,r){C("ephId",t),ht(e,i),h(Number.isInteger(r)===!1,"lifetime must be an integer");let o=r>0&&r<=365*24*60*60;h(!o,"lifetime must be greater than 0 and less than or equal to 365 days")}toJSON(){return JSON.stringify({ephId:this.ephId,ephPK:this.ephPK,expiry:this.expiry,signAlg:this.signAlg})}};async function ft({setup:n,challenge:t,ephSK:e,ephClaim:i}){let r={setup:n,challenge:t},s=new TextEncoder().encode(JSON.stringify(r)),a=await Rt(s,e,i.signAlg);return{credentials:{credentials:i.toJSON(),method:"ephemeral",id:i.ephId},signature:a}}async function Rt(n,t,e){switch(e){case"ed25519":return(0,V.toHex)(L.ed25519.sign(n,t));case"secp256k1":return await(0,gt.signMessage)({message:{raw:n},privateKey:(0,V.toHex)(t)});default:throw new Error("Invalid signature algorithm")}}function J(n){switch(n){case"ed25519":return L.ed25519.utils.randomPrivateKey();case"secp256k1":return Z.secp256k1.utils.randomPrivateKey();default:throw new Error("Invalid signature algorithm")}}function v(n,t){switch(t){case"ed25519":return L.ed25519.getPublicKey(n);case"secp256k1":return Z.secp256k1.getPublicKey(n,!1);default:throw new Error("Invalid signature algorithm")}}var mt=require("viem");var b=class{constructor(t,e,i){p(this,"browserWallet");p(this,"eoa");p(this,"ephClaim");this.validateInputs(t,e),this.ephClaim=i,this.browserWallet=e,this.eoa=t}validateInputs(t,e){h(!(0,mt.isAddress)(t),"invalid Ethereum address format"),h(!((e==null?void 0:e.signTypedData)instanceof Function),"invalid browserWallet")}async authenticate({setup:t,challenge:e}){return h(!(t instanceof m||t instanceof d),`invalid setup for EOA authenticate. Requires KeygenSetupOpts or MetadataSetupOpts but found ${JSON.stringify(t)}`),await it({setup:t,eoa:this.eoa,challenge:e,browserWallet:this.browserWallet,ephClaim:this.ephClaim})}},I=class{constructor(t,e,i){p(this,"ephSK");p(this,"ephClaim");dt(e,i),this.ephSK=e;let r=v(this.ephSK,i);this.ephClaim=new w(t,r,i)}async authenticate({setup:t,challenge:e}){return h(!(t instanceof k||t instanceof d),`invalid setup for Eph authenticate. Requires SignSetupOpts or MetadataSetupOpts but found ${JSON.stringify(t)}`),await ft({setup:t,challenge:e,ephSK:this.ephSK,ephClaim:this.ephClaim})}},A=class{constructor(t,e,i){p(this,"rpConfig");p(this,"allowCredentialId");p(this,"ephClaim");this.ephClaim=i,this.rpConfig=t,this.allowCredentialId=e}async authenticate({setup:t,challenge:e}){return h(!(t instanceof m||t instanceof d),`invalid setup for Passkey authenticate. Requires KeygenSetupOpts or MetadataSetupOpts but found ${JSON.stringify(t)}`),await lt({allowCredentialId:this.allowCredentialId,challenge:e,rpConfig:this.rpConfig,ephClaim:this.ephClaim})}},E=class{constructor(t,e){p(this,"rpConfig");p(this,"user");this.rpConfig=t,this.user=e}async authenticate({setup:t,challenge:e}){return h(!(t instanceof d),`invalid setup for Passkey register. Requires MetadataSetupOpts but found ${JSON.stringify(t)}`),await ut({user:this.user,challenge:e,rpConfig:this.rpConfig})}};var U=class{constructor(t,e,i,r){p(this,"authModule");p(this,"threshold");p(this,"totalNodes");p(this,"wpClient");h(e<2,`Threshold = ${e} must be at least 2`),h(i<e,`Total nodes = ${i} must be greater or equal to threshold = ${e}`),this.threshold=e,this.totalNodes=i,this.authModule=r,this.wpClient=t}async generateKey(t){let e=new m({t:this.threshold,n:this.totalNodes,permissions:t,key_label:void 0});return this.setEphClaimOf(e),await this.wpClient.startKeygen({setup:e,authModule:this.authModule})}async signMessage(t,e){C("keyId",t),C("message",e);let i=new k({t:this.threshold,key_id:t,message:e});return await this.wpClient.startSigngen({setup:i,authModule:this.authModule})}async addEphemeralKey(t){C("keyId",t);let e=new d;return e.keyId=t,this.setEphClaimOf(e),await this.wpClient.addEphemeralKey({setup:e,authModule:this.authModule})}async revokeEphemeralKey(t){C("keyId",t);let e=new d;return e.keyId=t,this.setEphClaimOf(e),await this.wpClient.revokeEphemeralKey({setup:e,authModule:this.authModule})}async registerPasskey(){let t=new d;return await this.wpClient.registerPasskey({setup:t,authModule:this.authModule})}setEphClaimOf(t){(this.authModule instanceof b||this.authModule instanceof A)&&(t.ephClaim=this.authModule.ephClaim)}};var M=class{constructor(t){p(this,"walletProviderId");p(this,"walletProviderUrl");p(this,"apiVersion","v1");this.walletProviderId=t.walletProviderId,this.walletProviderUrl=`${t.walletProviderUrl}/${t.apiVersion}`,this.apiVersion=t.apiVersion}getVersion(){return this.apiVersion}getWalletId(){return this.walletProviderId}async startKeygen({setup:t,authModule:e}){return(this.apiVersion==="v1"?this.connect.bind(this):this.connectV2.bind(this))("keygen",t,e).then(r=>{var c,u;let o=r.split(":");h(o.length!==2,"Invalid keygen response from network");let s=(c=o[0])==null?void 0:c.split("=")[1];return{publicKey:(u=o[1])==null?void 0:u.split("=")[1],keyId:s}})}async startSigngen({setup:t,authModule:e}){return(this.apiVersion==="v1"?this.connect.bind(this):this.connectV2.bind(this))("signgen",t,e).then(r=>{var c,u;let o=r.split(":");h(o.length!==2,"Invalid signgen response from network");let s=(c=o[0])==null?void 0:c.split("=")[1],a=(u=o[1])==null?void 0:u.split("=")[1];if(s===void 0||a===void 0)throw new Error("Invalid signgen response from network");return{sign:s,recid:parseInt(a)}})}async addEphemeralKey({setup:t,authModule:e}){return(this.apiVersion==="v1"?this.connect.bind(this):this.connectV2.bind(this))("addEphemeralKey",t,e).then(r=>({status:r}))}async revokeEphemeralKey({setup:t,authModule:e}){return(this.apiVersion==="v1"?this.connect.bind(this):this.connectV2.bind(this))("revokeEphemeralKey",t,e).then(r=>({status:r}))}async registerPasskey({setup:t,authModule:e}){return(this.apiVersion==="v1"?this.connect.bind(this):this.connectV2.bind(this))("registerPasskey",t,e).then(r=>({passkeyCredentialId:r}))}connect(t,e,i){return new Promise((r,o)=>{let s=0;t==="signgen"&&(e.message=Y(new TextEncoder().encode(e.message)));let a=new WebSocket(`${this.walletProviderUrl}/${t}`);a.addEventListener("open",c=>{switch(console.debug(`Connection opened in state ${s} with event ${JSON.stringify(c,void 0," ")}`),s){case 0:s=1,a.send(JSON.stringify(e));break;case 1:case 2:s=3,o("Incorrect protocol state");break;case 3:break}}),a.addEventListener("message",async c=>{switch(console.debug(`Connection message in state ${s} with event ${JSON.stringify(c,void 0," ")}`),s){case 0:s=3,o("Incorrect protocol state");break;case 1:{s=2;try{let u=await i.authenticate({setup:e,challenge:c.data});a.send(JSON.stringify(u))}catch(u){o(u)}break}case 2:s=3,a.close(),r(c.data);break;case 3:break}}),a.addEventListener("error",c=>{console.debug(`Connection error in state ${s} with event ${JSON.stringify(c,void 0," ")}`),s!=3&&(s=3,o("Incorrect protocol state"))}),a.addEventListener("close",c=>{console.debug(`Connection closed in state ${s} with event ${JSON.stringify(c,void 0," ")}`),s!=3&&(s=3,o("Incorrect protocol state"))})})}connectV2(t,e,i){return new Promise((r,o)=>{let s=0;t==="signgen"&&(e.message=Y(new TextEncoder().encode(e.message)));let a=new WebSocket(`${this.walletProviderUrl}/${t}`);a.addEventListener("open",async c=>{switch(console.debug(`Connection opened in state ${s} with event ${JSON.stringify(c,void 0," ")}`),s){case 0:s=2;try{let u=JSON.stringify(e),g=await i.authenticate({setup:e,challenge:pt(u)});a.send(JSON.stringify({setupOpts:u,userAuth:JSON.stringify(g)}))}catch(u){o(u)}break;case 2:s=3,o("Incorrect protocol state");break;case 3:break}}),a.addEventListener("message",async c=>{switch(console.debug(`Connection message in state ${s} with event ${JSON.stringify(c,void 0," ")}`),s){case 0:s=3,o("Incorrect protocol state");break;case 2:s=3,a.close(),r(c.data);break;case 3:break}}),a.addEventListener("error",c=>{console.debug(`Connection error in state ${s} with event ${JSON.stringify(c,void 0," ")}`),s!=3&&(s=3,o("Incorrect protocol state"))}),a.addEventListener("close",c=>{console.debug(`Connection closed in state ${s} with event ${JSON.stringify(c,void 0," ")}`),s!=3&&(s=3,o("Incorrect protocol state"))})})}};var $=require("viem/accounts"),yt=require("@noble/curves/secp256k1");var K=require("viem");function _(n){if(n.startsWith("0x")&&(n=n.slice(2)),n.startsWith("04"))return(0,$.publicKeyToAddress)(`0x${n} `);if(n.startsWith("02")||n.startsWith("03")){let t=yt.secp256k1.ProjectivePoint.fromHex(n).toHex(!1);return(0,$.publicKeyToAddress)(`0x${t}`)}else throw new Error("Invalid public key")}var Tt={NetworkSigner:U,WalletProviderServiceClient:M,EOAAuth:b,EphAuth:I,PasskeyAuth:A,PasskeyRegister:E,generateEphPrivateKey:J,getEphPublicKey:v,EphKeyClaim:w,computeAddress:_};0&&(module.exports={EOAAuth,EphAuth,EphKeyClaim,NetworkSigner,PasskeyAuth,PasskeyRegister,WalletProviderServiceClient,computeAddress,generateEphPrivateKey,getEphPublicKey});
2
+ /*! Bundled license information:
3
+
4
+ @noble/hashes/esm/utils.js:
5
+ (*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) *)
6
+ */