@silencelaboratories/walletprovider-sdk 0.0.10 → 0.2.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
@@ -10,8 +10,8 @@ In order to run it execute the following:
10
10
  1. Build the library
11
11
 
12
12
  ```
13
- bun install
14
- bun run build
13
+ npm install
14
+ npm run build
15
15
  ```
16
16
 
17
17
  2. Run the demo
@@ -49,24 +49,30 @@ For description of classes, interfaces, types, please refer to [documentation](.
49
49
  ## Authentication
50
50
 
51
51
 
52
- Users authenticate using an EOA wallet during **key generation** and register an ephemeral signing key pair and associates it with their identity.
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
53
 
54
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.
55
55
 
56
- We use [EOAAuth](./docs/walletprovider-sdk.eoaauth.md) to authenticate the user **during keygen**. The `EOAAuth` object is created with the user's wallet address, ephemeral public key, and lifetime of the key in seconds.
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.
58
+
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
+
61
+ - The ephemeral public key and lifetime of the key in seconds will be associated with both `EOAAuth` and `PasskeyAuth` objects.
57
62
 
58
- We then use [EphAuth](./docs/walletprovider-sdk.ephauth.md) to authenticate the user **during signing**. The `EphAuth` object is created with the user's wallet address and ephemeral keypair.
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.
59
65
 
60
66
  ## Keygen
61
67
 
62
68
 
63
69
  The full working example is in the [demo](https://github.com/silence-laboratories/walletprovider-sdk/blob/a75d7a009fb4d3629d353d53f8c27c34190c9035/demo/src/routes/%2Bpage.svelte#L89).
64
- The core object to use is the [NetworkSigner](./docs/walletprovider-sdk.networksigner.md).
70
+ The core object to use is the [NetworkSigner](./docs/walletprovider-sdk.networksigner.md). It allows to generate keys and do signatures.
65
71
 
66
- It allows to generate keys and do signatures. In order to create, 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. Currently we provide EOA authentication via [EOAAuth](./docs/walletprovider-sdk.eoaauth.md).
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**.
67
73
 
68
-
69
- Let's create the `NetworkSigner`
74
+ ### Authenticate with EOA wallet
75
+ We provide EOA authentication via [EOAAuth](./docs/walletprovider-sdk.eoaauth.md) module. Let's create the `NetworkSigner` with associated `EOAAuth` object.
70
76
 
71
77
  ```ts
72
78
  // Generate ephemeral secret key esk
@@ -74,12 +80,14 @@ const sk = ed.utils.randomPrivateKey();
74
80
  ephSK = sk;
75
81
  // Derive public part epk from esk
76
82
  ephPK = await ed.getPublicKeyAsync(sk);
77
-
83
+ // Arbitrary ID to identify the ephemeral key
84
+ const ephId = uuidv4();
78
85
  // Create a client that connects to the backend service
79
86
  const wpClient = await createWalletProviderService(clusterConfig);
80
87
 
81
88
  // Create EOA authenticator, signature will include epk
82
89
  const eoaAuth = new EOAAuth(
90
+ ephId,
83
91
  accountsFromBrowserWallet[0],
84
92
  new BrowserWallet(),
85
93
  ephPK,
@@ -113,9 +121,58 @@ const permissions = {
113
121
  let resp: KeygenResponse = await sdk.authenticateAndCreateKey(JSON.stringify(permissions));
114
122
  ```
115
123
 
116
- Calling this method will cause to the Browser Wallet window to pop up, requesting the User to sign the request. After execution [KeygenResponse](./docs/walletprovider-sdk.keygenresponse.md) is returned.
124
+ Calling this method will cause to the Browser Wallet window to pop up, requesting the User to sign the request.
117
125
 
118
- The [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
+ 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.
127
+
128
+ The `esk` key can be later used by the frontend in subsequent signgen requests for authenticating.
129
+
130
+ ### Authenticate with Passkey
131
+ We provide Passkey authentication via [PasskeyAuth](./docs/walletprovider-sdk.passkeyauth.md) module. Let's create the `NetworkSigner` with associated `PasskeyAuth` object.
132
+
133
+ ```ts
134
+ // Generate ephemeral secret key esk
135
+ const sk = ed.utils.randomPrivateKey();
136
+ ephSK = sk;
137
+ // Derive public part epk from esk
138
+ ephPK = await ed.getPublicKeyAsync(sk);
139
+ // Arbitrary ID to identify the ephemeral key
140
+ const ephId = uuidv4();
141
+ // Create a client that connects to the backend service
142
+ const wpClient = await createWalletProviderService(clusterConfig);
143
+ // Here we configure the relying party for local development
144
+ const rpConfig: RelyingPartyConfig = {
145
+ rpId: 'localhost',
146
+ rpName: 'http://localhost:5173',
147
+ };
148
+ // Information about the owner of the passkey
149
+ const passkeyUser: PasskeyUser = {
150
+ id: userId,
151
+ displayName: 'Alice',
152
+ name: 'alice@gmail.com ' + userId, // For development purposes
153
+ };
154
+
155
+ // Get passkey credential id from your storage
156
+ const credentialId = getPasskeyCredentialId();
157
+ // Create EOA authenticator, signature will include epk
158
+ const passkeyAuth = new PasskeyAuth(
159
+ rpConfig,
160
+ passkeyUser,
161
+ ephId,
162
+ ephPK,
163
+ // Lifetime of one hour
164
+ 60 * 60,
165
+ // If credentialId is null, we will do passkey register, otherwise, we will do passkey auth/login
166
+ credentialId,
167
+ );
168
+
169
+ // Create a new signer instance
170
+ const sdk = new NetworkSigner(wpClient, threshold, partiesNumber, passkeyAuth);
171
+ ```
172
+
173
+ Now you can generate a key like in the EOA example by calling the [authenticateAndCreateKey](./docs/walletprovider-sdk.networksigner.authenticateandcreatekey.md) method.
174
+
175
+ 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.
119
176
 
120
177
  The `esk` key can be later used by the frontend in subsequent signgen requests for authenticating.
121
178
 
@@ -125,7 +182,7 @@ The full signing example is [here](https://github.com/silence-laboratories/walle
125
182
 
126
183
  Let's create NetworkSigner for signing. Note the `EphAuth` is used to avoid user interaction when generating the signatures.
127
184
  ```ts
128
- const authModule = new EphAuth(accountsFromBrowserWallet[0], ephSK!);
185
+ const authModule = new EphAuth(ephId, ephSK);
129
186
  // Create a new signer instance
130
187
  const sdk = new NetworkSigner(wpClient, threshold, partiesNumber, authModule);
131
188
  ```
@@ -135,71 +192,57 @@ Use the [NetworkSigner.authenticateAndSign](./docs/walletprovider-sdk.networksig
135
192
 
136
193
  ```ts
137
194
  let signMessage = JSON.stringify({
138
- userOperation: {
139
- sender: '0x8d4cb2540d993fe34c646299f1ab4af3012ff34c',
140
- nonce: '0x7',
141
- initCode: '',
142
- callData: '0000189a...',
143
- callGasLimit: '123130',
144
- verificationGasLimit: '153427',
145
- preVerificationGas: '66768',
146
- maxFeePerGas: '',
147
- maxPriorityFeePerGas: '',
148
- paymasterAndData: '',
149
- },
150
- entryPointVersion: 'v0.6.0',
151
- entryPointAddress: '0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789',
152
- chainId: 80002,
153
- });
195
+ message: JSON.stringify({
196
+ userOperation: {
197
+ sender: '0x8d4cb2540d993fe34c646299f1ab4af3012ff34c',
198
+ nonce: '0x7',
199
+ initCode: '0x',
200
+ callData: '0000189...',
201
+ callGasLimit: '0x18473',
202
+ verificationGasLimit: '0x18473',
203
+ preVerificationGas: '66768',
204
+ maxFeePerGas: '',
205
+ maxPriorityFeePerGas: '',
206
+ paymasterAndData: '0x',
207
+ },
208
+ entryPointVersion: 'v0.6.0',
209
+ entryPointAddress: '0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789',
210
+ chainId: 80002,
211
+ }),
212
+ requestType: 'accountAbstractionTx',
213
+ });
154
214
 
155
215
  let resp = await sdk.authenticateAndSign(selectedKeyId, signMessage);
156
216
  ```
157
217
 
158
218
  The [SignResponse](./docs/walletprovider-sdk.signresponse.md) contains the signature `sign` and the recovery ID `recid`.
159
219
 
160
- # Developing the library
161
-
162
- Audience of this section are library developers.
163
-
164
- ## Bun runtime is required
165
-
166
- Install bun from https://bun.sh
167
220
 
168
221
  ## Install dependencies
169
222
 
170
223
  ```bash
171
- bun install
224
+ npm install
172
225
  ```
173
226
 
174
227
  ## Build
175
228
 
176
229
  ```bash
177
- bun run build
230
+ npm run build
178
231
  ```
179
232
 
180
233
  The output will be in the `dist` folder.
181
234
 
182
- ## Test
183
-
184
- Create `*.test.ts` files and run tests with:
185
-
186
- ```bash
187
- bun run test
188
- # or watch test
189
- bun run test:watch
190
- ```
191
-
192
235
  ## End to end tests
193
236
  Please refer to [README.md](./e2e-tests/README.md) for instructions how to execute them.
194
237
 
195
238
  ## Format the code
196
239
 
197
240
  ```bash
198
- bun run format
241
+ npm run format
199
242
  ```
200
243
 
201
244
  ## Generate the documentation
202
245
 
203
246
  ```bash
204
- bun run docs
205
- ```
247
+ npm run docs
248
+ ```
@@ -1,14 +1,9 @@
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, SignSetupOpts } from './networkSigner.ts';
5
- import { type UserAuthentication } from './authentication.ts';
4
+ import { KeygenSetupOpts } from './networkSigner';
5
+ import { type UserAuthentication } from './authentication';
6
6
  import { type TypedDataDomain } from 'viem';
7
- export type EphClaim = {
8
- eoa: string;
9
- ephPK: string;
10
- expiry: number;
11
- };
12
7
  export type FieldDefinition = {
13
8
  name: string;
14
9
  type: string;
@@ -50,23 +45,14 @@ export interface IBrowserWallet {
50
45
  signTypedData<T>(from: string, request: TypedData<T>): Promise<unknown>;
51
46
  }
52
47
  /** Present the request to the User using wallet UI, and ask for sign.
53
- * The signature is the authorization for the operation
48
+ * The signature is the authorization for keygen operation
54
49
  */
55
- export declare function authenticateUsingEOA({ setup, user_id, challenge, browserWallet, ephPK, lifetime, }: {
50
+ export declare function authenticateUsingEOA({ setup, ephId, eoa, challenge, browserWallet, ephPK, lifetime, }: {
56
51
  setup: KeygenSetupOpts;
57
- user_id: string;
52
+ ephId: string;
53
+ eoa: string;
58
54
  challenge: string;
59
55
  browserWallet: IBrowserWallet;
60
56
  ephPK: Uint8Array;
61
57
  lifetime: number;
62
58
  }): Promise<UserAuthentication>;
63
- /** Present the request to the User using wallet UI, and ask for sign.
64
- * The signature is the authorization for the operation
65
- */
66
- export declare function authenticateUsingEphKey({ setup, user_id, challenge, ephSK, ephPK, }: {
67
- setup: SignSetupOpts;
68
- user_id: string;
69
- challenge: string;
70
- ephSK: Uint8Array;
71
- ephPK: Uint8Array;
72
- }): Promise<UserAuthentication>;
@@ -1,22 +1,19 @@
1
1
  import { KeygenSetupOpts, SignSetupOpts } from './networkSigner';
2
2
  import { IBrowserWallet } from './EOAauthentication';
3
+ import { PasskeyUser, RelyingPartyConfig } from './passkeyAuthentication';
3
4
  /** Type of the request authentication
4
5
  * @alpha
5
6
  */
6
- export declare enum AuthMethod {
7
- /** Authentication using Externally Owned Account */
8
- EOA = 0,
9
- /** No authentication */
10
- NONE = 1
11
- }
12
7
  export type UserCredentials = {
13
8
  id: string;
14
9
  method: string;
15
10
  credentials: string;
11
+ ephId?: string;
16
12
  };
17
13
  export type UserAuthentication = {
18
14
  credentials: UserCredentials;
19
15
  signature: string;
16
+ passkeyCredentialId?: string;
20
17
  };
21
18
  export interface AuthModule {
22
19
  authenticate({ setup, challenge, }: {
@@ -24,46 +21,78 @@ export interface AuthModule {
24
21
  challenge: string;
25
22
  }): Promise<UserAuthentication>;
26
23
  }
27
- /** The `AuthModule` implementing Externally Owned Account authentication.
24
+ /** The `EOAAuth` implementing Externally Owned Account authentication.
28
25
  * @alpha
29
26
  */
30
27
  export declare class EOAAuth implements AuthModule {
31
- /** User ID, typically the ETH address that is used to do authentication */
32
- userId: string;
28
+ /** Ephemeral id identify ephemeral key */
29
+ ephId: string;
33
30
  /** An interface to the wallet, like MetaMask, that is used to sign the requests */
34
31
  browserWallet: IBrowserWallet;
35
32
  /** Public key of the ephemeral key */
36
33
  ephPK: Uint8Array;
37
34
  /** Lifetime of the ephemeral key */
38
35
  lifetime: number;
39
- constructor(userId: string, browserWallet: IBrowserWallet, ephPK: Uint8Array, lifetime?: number);
36
+ /** the ETH address that is used to do EOA authentication */
37
+ eoa: string;
38
+ constructor(ephId: string, eoa: string, browserWallet: IBrowserWallet, ephPK: Uint8Array, lifetime?: number);
40
39
  /**
41
40
  * Prepares a message to present on the Browser Wallet window and requests to sign it.
42
- * @param setup - either Keygen or Sign setup options
41
+ * @param setup - Keygen setup options
43
42
  * @param challenge - the challenge received from the backend
44
43
  *
45
44
  * @public
46
45
  */
47
- authenticate({ setup, challenge, }: {
48
- setup: KeygenSetupOpts | SignSetupOpts;
46
+ authenticate({ setup, challenge }: {
47
+ setup: KeygenSetupOpts;
49
48
  challenge: string;
50
49
  }): Promise<UserAuthentication>;
51
50
  }
52
- /** An Ephmeral key used to locally sign the signature requests to network.
51
+ /** The `EphAuth` module is only used for signing requests to the network.
52
+ * @alpha
53
+ * An Ephmeral key used to locally sign the signature requests to network.
53
54
  * This eph key is registered during keygen. The key is used to sign the requests without
54
55
  * asking the user to sign the request each time.
55
- * The auth module is only used for signing requests to the network.
56
56
  * */
57
57
  export declare class EphAuth implements AuthModule {
58
- /** User ID, typically the ETH address that is used to do authentication */
59
- userId: string;
58
+ /** Ephemeral id identify ephemeral key */
59
+ ephId: string;
60
60
  /** Secret key of the ephemeral keypair */
61
61
  ephSK: Uint8Array;
62
62
  /** Public key of the ephemeral keypair */
63
63
  ephPK: Uint8Array;
64
- constructor(userId: string, ephSK: Uint8Array);
65
- authenticate({ setup, challenge, }: {
66
- setup: KeygenSetupOpts | SignSetupOpts;
64
+ constructor(ephId: string, ephSK: Uint8Array);
65
+ /**
66
+ * Prepares a message to present on the Browser Wallet window and requests to sign it.
67
+ * @param setup - Signgen setup options
68
+ * @param challenge - the challenge received from the backend
69
+ *
70
+ * @public
71
+ */
72
+ authenticate({ setup, challenge }: {
73
+ setup: SignSetupOpts;
74
+ challenge: string;
75
+ }): Promise<UserAuthentication>;
76
+ }
77
+ /** The `AuthModule` implementing Passkey authentication.
78
+ * @alpha
79
+ */
80
+ export declare class PasskeyAuth implements AuthModule {
81
+ /** Replying party object. Read more: https://developer.mozilla.org/en-US/docs/Web/API/PublicKeyCredentialCreationOptions#rp */
82
+ rpConfig: RelyingPartyConfig;
83
+ /** Passkey user information. Read more: https://developer.mozilla.org/en-US/docs/Web/API/PublicKeyCredentialCreationOptions#user */
84
+ user: PasskeyUser;
85
+ /** Public key of the ephemeral key */
86
+ ephPK: Uint8Array;
87
+ /** Lifetime of the ephemeral key */
88
+ lifetime: number;
89
+ /** Ephemeral id identify ephemeral key */
90
+ ephId: string;
91
+ /** Credential id that user and authenticator acknowledges about */
92
+ credentialId: string | null;
93
+ constructor(rpConfig: RelyingPartyConfig, user: PasskeyUser, ephId: string, ephPK: Uint8Array, lifetime: number | undefined, credentialId: string | null);
94
+ authenticate({ setup, challenge }: {
95
+ setup: KeygenSetupOpts;
67
96
  challenge: string;
68
97
  }): Promise<UserAuthentication>;
69
98
  }
@@ -1,4 +1,3 @@
1
- export declare const decodeHex: (s: string) => Uint8Array;
2
- export declare const encodeHex: (a: Uint8Array) => string;
3
1
  export declare const decodeBase64: (b64: string) => Uint8Array;
4
2
  export declare const encodeBase64: (b: Uint8Array) => string;
3
+ export declare const arrayBufferToBase64Url: (a: ArrayBuffer) => string;
@@ -0,0 +1,16 @@
1
+ import { UserAuthentication } from './authentication';
2
+ import { SignSetupOpts } from './networkSigner';
3
+ export type EphClaim = {
4
+ ephPK: string;
5
+ expiry: number;
6
+ };
7
+ /** Locally sign the signature requests to network without asking the user, the ephSK is registered during keygen.
8
+ * The signature is the authorization for signgen operation
9
+ */
10
+ export declare function authenticateUsingEphKey({ setup, ephId, challenge, ephSK, ephPK, }: {
11
+ setup: SignSetupOpts;
12
+ ephId: string;
13
+ challenge: string;
14
+ ephSK: Uint8Array;
15
+ ephPK: Uint8Array;
16
+ }): Promise<UserAuthentication>;
@@ -0,0 +1 @@
1
+ "use strict";var H=Object.create;var y=Object.defineProperty;var F=Object.getOwnPropertyDescriptor;var z=Object.getOwnPropertyNames;var L=Object.getPrototypeOf,V=Object.prototype.hasOwnProperty;var G=(t,e,n)=>e in t?y(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n;var Y=(t,e)=>{for(var n in e)y(t,n,{get:e[n],enumerable:!0})},v=(t,e,n,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of z(e))!V.call(t,s)&&s!==n&&y(t,s,{get:()=>e[s],enumerable:!(r=F(e,s))||r.enumerable});return t};var j=(t,e,n)=>(n=t!=null?H(L(t)):{},v(e||!t||!t.__esModule?y(n,"default",{value:t,enumerable:!0}):n,t)),Q=t=>v(y({},"__esModule",{value:!0}),t);var a=(t,e,n)=>G(t,typeof e!="symbol"?e+"":e,n);var se={};Y(se,{EOAAuth:()=>w,EphAuth:()=>A,NetworkSigner:()=>P,PasskeyAuth:()=>I,WalletProviderServiceClient:()=>K,computeAddress:()=>M});module.exports=Q(se);var k=require("viem");var X=1,Z=2,f=class{constructor({t:e,n,ephPK:r,key_label:s,permissions:i}){a(this,"t");a(this,"n");a(this,"key_label");a(this,"metadata");this.t=e,this.n=n,this.key_label=s,this.metadata=[],this.metadata.push({tag:Z,value:r}),i&&this.metadata.push({tag:X,value:i})}};function u(t){return t.message!==void 0}var P=class{constructor(e,n,r,s){a(this,"authModule");a(this,"threshold");a(this,"totalNodes");a(this,"wp_client");if(n===0)throw new Error("Threshold cannot be 0");this.threshold=n,this.totalNodes=r,this.authModule=s,this.wp_client=e}async authenticateAndCreateKey(e,n){try{let r=new f({t:this.threshold,n:this.totalNodes,permissions:n,ephPK:(0,k.toHex)(e)}),s=p=>this.authModule.authenticate({setup:r,challenge:p}),i=await this.wp_client.startKeygen({setup:r,signer:s});return console.log("Keygen response:",i),i}catch(r){throw console.error(r),r}}async authenticateAndSign(e,n){let r={t:this.threshold,key_id:e,message:n},s=p=>this.authModule.authenticate({setup:r,challenge:p}),i=await this.wp_client.startSigngen({setup:r,signer:s});return console.log("Sign response:",i),i}};var b=require("viem"),ee=[{name:"tag",type:"uint16"},{name:"value",type:"string"}],te={Request:[{name:"setup",type:"KeygenSetupOpts"},{name:"challenge",type:"string"}],KeygenSetupOpts:[{name:"t",type:"uint32"},{name:"n",type:"uint32"},{name:"metadata",type:"TaggedValue[]"}],TaggedValue:ee},ne={name:"SilentShard authentication",version:"0.1.0"},ie=[{name:"name",type:"string"},{name:"version",type:"string"}];function re(t,e,n){console.log("EPHKEY",n);let r=new f({t:t.t,n:t.n,key_label:t.key_label,permissions:void 0,ephPK:(0,b.toHex)(n)});return{types:{EIP712Domain:ie,...te},domain:ne,primaryType:"Request",message:{setup:r,challenge:e}}}async function R({setup:t,ephId:e,eoa:n,challenge:r,browserWallet:s,ephPK:i,lifetime:p}){if(u(t))throw new Error("EOA auth cannot be used for Sign requests, please use EphAuth instead");let c=re(t,r,i),o=await s.signTypedData(n,c);console.log("User signed a request",o);let l={ephPK:(0,b.toHex)(i),expiry:Math.floor(Date.now()/1e3)+p};return{credentials:{credentials:JSON.stringify(l),method:"eoa",id:n,ephId:e},signature:o}}var B=require("@noble/curves/ed25519");var T=require("js-base64");var E=t=>btoa(String.fromCodePoint.apply(null,Array.from(t))),g=t=>T.Base64.fromUint8Array(new Uint8Array(t),!0);var O=require("js-base64"),d=require("viem");async function N({user:t,ephId:e,challenge:n,rpConfig:r,ephPK:s,lifetime:i}){let p=(0,d.hexToBytes)(`0x${n}`,{size:32}),c={publicKey:{authenticatorSelection:{authenticatorAttachment:void 0,residentKey:"preferred",requireResidentKey:!1,userVerification:"required"},challenge:p,excludeCredentials:[],pubKeyCredParams:[{type:"public-key",alg:-7},{type:"public-key",alg:-257}],rp:{name:r.rpName,id:r.rpId},user:{...t,id:O.Base64.toUint8Array(t.id)}}},o=await navigator.credentials.create(c);if(o===null)throw new Error("No credential returned");let l=g(o.response.attestationObject),S={rawCredential:JSON.stringify({authenticatorAttachment:o.authenticatorAttachment,id:o.id,rawId:g(o.rawId),response:{attestationObject:l,clientDataJSON:g(o.response.clientDataJSON)},type:o.type}),origin:r.rpName,rpId:r.rpId},x={ephPK:(0,d.toHex)(s),expiry:Math.floor(Date.now()/1e3)+i};return{credentials:{credentials:JSON.stringify(x),method:"passkey",id:o.id,ephId:e},signature:JSON.stringify(S),passkeyCredentialId:o.id}}async function D({ephId:t,challenge:e,credentialId:n,rpConfig:r,ephPK:s,lifetime:i}){let p=(0,d.hexToBytes)(`0x${e}`,{size:32}),c=[{type:"public-key",id:O.Base64.toUint8Array(n)}],o={publicKey:{userVerification:"required",challenge:p,allowCredentials:c}},l=await navigator.credentials.get(o);if(l===null)throw new Error("Failed to get navigator credentials");let m=l.response,S=m.userHandle;if(S===null)throw new Error("User handle cannot be null");let x=g(m.signature),_={rawCredential:JSON.stringify({authenticatorAttachment:l.authenticatorAttachment,id:l.id,rawId:g(l.rawId),response:{authenticatorData:g(m.authenticatorData),clientDataJSON:g(m.clientDataJSON),signature:x,userHandle:g(S)},type:l.type}),origin:r.rpName,rpId:r.rpId,credentialId:n},$={ephPK:(0,d.toHex)(s),expiry:Math.floor(Date.now()/1e3)+i};return{credentials:{credentials:JSON.stringify($),method:"passkey",id:l.id,ephId:t},signature:JSON.stringify(_),passkeyCredentialId:l.id}}var U=require("viem"),J=require("@noble/curves/ed25519");async function W({setup:t,ephId:e,challenge:n,ephSK:r,ephPK:s}){let i={setup:t,challenge:n},p=new TextEncoder,c=(0,U.toHex)(J.ed25519.sign(p.encode(JSON.stringify(i)),r));console.log("AUTH SIGNATURE by eph key",c);let o={ephPK:(0,U.toHex)(s),expiry:0};return{credentials:{credentials:JSON.stringify(o),method:"ephemeral",id:e},signature:c}}var w=class{constructor(e,n,r,s,i=3600){a(this,"ephId");a(this,"browserWallet");a(this,"ephPK");a(this,"lifetime");a(this,"eoa");this.ephId=e,this.browserWallet=r,this.ephPK=s,this.lifetime=i,this.eoa=n}async authenticate({setup:e,challenge:n}){return await R({setup:e,ephId:this.ephId,eoa:this.eoa,challenge:n,browserWallet:this.browserWallet,ephPK:this.ephPK,lifetime:this.lifetime})}},A=class{constructor(e,n){a(this,"ephId");a(this,"ephSK");a(this,"ephPK");this.ephId=e,this.ephSK=n,this.ephPK=B.ed25519.getPublicKey(this.ephSK)}async authenticate({setup:e,challenge:n}){return await W({setup:e,ephId:this.ephId,challenge:n,ephSK:this.ephSK,ephPK:this.ephPK})}},I=class{constructor(e,n,r,s,i=3600,p){a(this,"rpConfig");a(this,"user");a(this,"ephPK");a(this,"lifetime");a(this,"ephId");a(this,"credentialId");this.rpConfig=e,this.user=n,this.ephPK=s,this.lifetime=i,this.ephId=r,this.credentialId=p}async authenticate({setup:e,challenge:n}){if(u(e))throw new Error("Passkey auth cannot be used for Sign requests, please use EphAuth instead");return this.credentialId?await D({ephId:this.ephId,credentialId:this.credentialId,challenge:n,rpConfig:this.rpConfig,ephPK:this.ephPK,lifetime:this.lifetime}):await N({user:this.user,ephId:this.ephId,challenge:n,rpConfig:this.rpConfig,ephPK:this.ephPK,lifetime:this.lifetime})}};var K=class{constructor(e){a(this,"walletProviderId");a(this,"walletProviderUrl");a(this,"passkeyCredentialId");this.walletProviderId=e.walletProviderId,this.walletProviderUrl=e.walletProviderUrl}getWalletId(){return this.walletProviderId}async startKeygen({setup:e,signer:n}){return this.connect(e,n).then(r=>{let s=r.split(":"),i=s[0].split("=")[1];return{publicKey:s[1].split("=")[1],keyId:i,passkeyCredentialId:this.passkeyCredentialId}})}async startSigngen({setup:e,signer:n}){return this.connect(e,n).then(r=>{let s=r.split(":"),i=s[0].split("=")[1],p=s[1].split("=")[1];return{sign:i,recid:parseInt(p)}})}connect(e,n){return new Promise((r,s)=>{let i=0,p;u(e)?(p="signgen",e.message=E(new TextEncoder().encode(e.message))):p="keygen";let c=new WebSocket(`${this.walletProviderUrl}/${p}`);c.addEventListener("open",o=>{switch(console.log(`Connection opened in state ${i} with event ${JSON.stringify(o,void 0," ")}`),i){case 0:i=1,console.log(`Sending setup: ${JSON.stringify(e)}`),c.send(JSON.stringify(e));break;case 1:case 2:i=3,s("Incorrect protocol state");break;case 3:break}}),c.addEventListener("message",async o=>{switch(console.log(`Connection message in state ${i} with event ${JSON.stringify(o,void 0," ")}`),i){case 0:i=3,s("Incorrect protocol state");break;case 1:{i=2;let l=await n(o.data);l.credentials.method==="passkey"&&(this.passkeyCredentialId=l.passkeyCredentialId),console.log(`Sending signature: ${JSON.stringify(l)}`),c.send(JSON.stringify(l));break}case 2:i=3,c.close(),r(o.data);break;case 3:break}}),c.addEventListener("error",o=>{console.log(`Connection error in state ${i} with event ${JSON.stringify(o,void 0," ")}`),i!=3&&(i=3,s("Incorrect protocol state"))}),c.addEventListener("close",o=>{console.log(`Connection closed in state ${i} with event ${JSON.stringify(o,void 0," ")}`),i!=3&&(i=3,s("Incorrect protocol state"))})})}};var h=j(require("viem")),C=require("viem/accounts"),q=require("@noble/curves/secp256k1");function M(t){if(t.startsWith("0x")&&(t=t.slice(2)),t.startsWith("04"))return(0,C.publicKeyToAddress)(`0x${t} `);if(t.startsWith("02")||t.startsWith("03")){let e=q.secp256k1.ProjectivePoint.fromHex(t).toHex(!1);return(0,C.publicKeyToAddress)(`0x${e}`)}else throw new Error("Invalid public key")}0&&(module.exports={EOAAuth,EphAuth,NetworkSigner,PasskeyAuth,WalletProviderServiceClient,computeAddress});
package/dist/index.d.ts CHANGED
@@ -1,6 +1,8 @@
1
- export { NetworkSigner, SignResponse, KeygenResponse } from './networkSigner.ts';
2
- export { AuthMethod, EOAAuth, EphAuth } from './authentication.ts';
3
- export type { IBrowserWallet, TypedData } from './EOAauthentication.ts';
4
- export type { ClientConfig, IWalletProviderServiceClient } from './walletProviderServiceClientInterface.ts';
5
- export { WalletProviderServiceClient } from './walletProviderServiceClient.ts';
6
- export { computeAddress } from './viemSigner.ts';
1
+ export type { SignResponse, KeygenResponse } from './networkSigner';
2
+ export type { IBrowserWallet, TypedData } from './EOAauthentication';
3
+ export type { ClientConfig, IWalletProviderServiceClient } from './walletProviderServiceClientInterface';
4
+ export type { PasskeyUser, RelyingPartyConfig } from './passkeyAuthentication';
5
+ export { NetworkSigner } from './networkSigner';
6
+ export { EOAAuth, EphAuth, PasskeyAuth } from './authentication';
7
+ export { WalletProviderServiceClient } from './walletProviderServiceClient';
8
+ export { computeAddress } from './viemSigner';
@@ -0,0 +1 @@
1
+ var M=Object.defineProperty,_=Object.defineProperties;var $=Object.getOwnPropertyDescriptors;var b=Object.getOwnPropertySymbols;var H=Object.prototype.hasOwnProperty,F=Object.prototype.propertyIsEnumerable;var P=(n,e,t)=>e in n?M(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t,m=(n,e)=>{for(var t in e||(e={}))H.call(e,t)&&P(n,t,e[t]);if(b)for(var t of b(e))F.call(e,t)&&P(n,t,e[t]);return n},w=(n,e)=>_(n,$(e));var a=(n,e,t)=>P(n,typeof e!="symbol"?e+"":e,t);import{toHex as z}from"viem";var L=1,V=2,y=class{constructor({t:e,n:t,ephPK:r,key_label:s,permissions:i}){a(this,"t");a(this,"n");a(this,"key_label");a(this,"metadata");this.t=e,this.n=t,this.key_label=s,this.metadata=[],this.metadata.push({tag:V,value:r}),i&&this.metadata.push({tag:L,value:i})}};function u(n){return n.message!==void 0}var A=class{constructor(e,t,r,s){a(this,"authModule");a(this,"threshold");a(this,"totalNodes");a(this,"wp_client");if(t===0)throw new Error("Threshold cannot be 0");this.threshold=t,this.totalNodes=r,this.authModule=s,this.wp_client=e}async authenticateAndCreateKey(e,t){try{let r=new y({t:this.threshold,n:this.totalNodes,permissions:t,ephPK:z(e)}),s=p=>this.authModule.authenticate({setup:r,challenge:p}),i=await this.wp_client.startKeygen({setup:r,signer:s});return console.log("Keygen response:",i),i}catch(r){throw console.error(r),r}}async authenticateAndSign(e,t){let r={t:this.threshold,key_id:e,message:t},s=p=>this.authModule.authenticate({setup:r,challenge:p}),i=await this.wp_client.startSigngen({setup:r,signer:s});return console.log("Sign response:",i),i}};import{toHex as O}from"viem";var G=[{name:"tag",type:"uint16"},{name:"value",type:"string"}],Y={Request:[{name:"setup",type:"KeygenSetupOpts"},{name:"challenge",type:"string"}],KeygenSetupOpts:[{name:"t",type:"uint32"},{name:"n",type:"uint32"},{name:"metadata",type:"TaggedValue[]"}],TaggedValue:G},j={name:"SilentShard authentication",version:"0.1.0"},Q=[{name:"name",type:"string"},{name:"version",type:"string"}];function X(n,e,t){console.log("EPHKEY",t);let r=new y({t:n.t,n:n.n,key_label:n.key_label,permissions:void 0,ephPK:O(t)});return{types:m({EIP712Domain:Q},Y),domain:j,primaryType:"Request",message:{setup:r,challenge:e}}}async function U({setup:n,ephId:e,eoa:t,challenge:r,browserWallet:s,ephPK:i,lifetime:p}){if(u(n))throw new Error("EOA auth cannot be used for Sign requests, please use EphAuth instead");let c=X(n,r,i),o=await s.signTypedData(t,c);console.log("User signed a request",o);let l={ephPK:O(i),expiry:Math.floor(Date.now()/1e3)+p};return{credentials:{credentials:JSON.stringify(l),method:"eoa",id:t,ephId:e},signature:o}}import{ed25519 as te}from"@noble/curves/ed25519";import{Base64 as Z}from"js-base64";var v=n=>btoa(String.fromCodePoint.apply(null,Array.from(n))),g=n=>Z.fromUint8Array(new Uint8Array(n),!0);import{Base64 as k}from"js-base64";import{toHex as R,hexToBytes as T}from"viem";async function E({user:n,ephId:e,challenge:t,rpConfig:r,ephPK:s,lifetime:i}){let p=T("0x".concat(t),{size:32}),c={publicKey:{authenticatorSelection:{authenticatorAttachment:void 0,residentKey:"preferred",requireResidentKey:!1,userVerification:"required"},challenge:p,excludeCredentials:[],pubKeyCredParams:[{type:"public-key",alg:-7},{type:"public-key",alg:-257}],rp:{name:r.rpName,id:r.rpId},user:w(m({},n),{id:k.toUint8Array(n.id)})}},o=await navigator.credentials.create(c);if(o===null)throw new Error("No credential returned");let l=g(o.response.attestationObject),f={rawCredential:JSON.stringify({authenticatorAttachment:o.authenticatorAttachment,id:o.id,rawId:g(o.rawId),response:{attestationObject:l,clientDataJSON:g(o.response.clientDataJSON)},type:o.type}),origin:r.rpName,rpId:r.rpId},S={ephPK:R(s),expiry:Math.floor(Date.now()/1e3)+i};return{credentials:{credentials:JSON.stringify(S),method:"passkey",id:o.id,ephId:e},signature:JSON.stringify(f),passkeyCredentialId:o.id}}async function N({ephId:n,challenge:e,credentialId:t,rpConfig:r,ephPK:s,lifetime:i}){let p=T("0x".concat(e),{size:32}),c=[{type:"public-key",id:k.toUint8Array(t)}],o={publicKey:{userVerification:"required",challenge:p,allowCredentials:c}},l=await navigator.credentials.get(o);if(l===null)throw new Error("Failed to get navigator credentials");let h=l.response,f=h.userHandle;if(f===null)throw new Error("User handle cannot be null");let S=g(h.signature),B={rawCredential:JSON.stringify({authenticatorAttachment:l.authenticatorAttachment,id:l.id,rawId:g(l.rawId),response:{authenticatorData:g(h.authenticatorData),clientDataJSON:g(h.clientDataJSON),signature:S,userHandle:g(f)},type:l.type}),origin:r.rpName,rpId:r.rpId,credentialId:t},q={ephPK:R(s),expiry:Math.floor(Date.now()/1e3)+i};return{credentials:{credentials:JSON.stringify(q),method:"passkey",id:l.id,ephId:n},signature:JSON.stringify(B),passkeyCredentialId:l.id}}import{toHex as D}from"viem";import{ed25519 as ee}from"@noble/curves/ed25519";async function J({setup:n,ephId:e,challenge:t,ephSK:r,ephPK:s}){let i={setup:n,challenge:t},p=new TextEncoder,c=D(ee.sign(p.encode(JSON.stringify(i)),r));console.log("AUTH SIGNATURE by eph key",c);let o={ephPK:D(s),expiry:0};return{credentials:{credentials:JSON.stringify(o),method:"ephemeral",id:e},signature:c}}var I=class{constructor(e,t,r,s,i=3600){a(this,"ephId");a(this,"browserWallet");a(this,"ephPK");a(this,"lifetime");a(this,"eoa");this.ephId=e,this.browserWallet=r,this.ephPK=s,this.lifetime=i,this.eoa=t}async authenticate({setup:e,challenge:t}){return await U({setup:e,ephId:this.ephId,eoa:this.eoa,challenge:t,browserWallet:this.browserWallet,ephPK:this.ephPK,lifetime:this.lifetime})}},K=class{constructor(e,t){a(this,"ephId");a(this,"ephSK");a(this,"ephPK");this.ephId=e,this.ephSK=t,this.ephPK=te.getPublicKey(this.ephSK)}async authenticate({setup:e,challenge:t}){return await J({setup:e,ephId:this.ephId,challenge:t,ephSK:this.ephSK,ephPK:this.ephPK})}},C=class{constructor(e,t,r,s,i=3600,p){a(this,"rpConfig");a(this,"user");a(this,"ephPK");a(this,"lifetime");a(this,"ephId");a(this,"credentialId");this.rpConfig=e,this.user=t,this.ephPK=s,this.lifetime=i,this.ephId=r,this.credentialId=p}async authenticate({setup:e,challenge:t}){if(u(e))throw new Error("Passkey auth cannot be used for Sign requests, please use EphAuth instead");return this.credentialId?await N({ephId:this.ephId,credentialId:this.credentialId,challenge:t,rpConfig:this.rpConfig,ephPK:this.ephPK,lifetime:this.lifetime}):await E({user:this.user,ephId:this.ephId,challenge:t,rpConfig:this.rpConfig,ephPK:this.ephPK,lifetime:this.lifetime})}};var x=class{constructor(e){a(this,"walletProviderId");a(this,"walletProviderUrl");a(this,"passkeyCredentialId");this.walletProviderId=e.walletProviderId,this.walletProviderUrl=e.walletProviderUrl}getWalletId(){return this.walletProviderId}async startKeygen({setup:e,signer:t}){return this.connect(e,t).then(r=>{let s=r.split(":"),i=s[0].split("=")[1];return{publicKey:s[1].split("=")[1],keyId:i,passkeyCredentialId:this.passkeyCredentialId}})}async startSigngen({setup:e,signer:t}){return this.connect(e,t).then(r=>{let s=r.split(":"),i=s[0].split("=")[1],p=s[1].split("=")[1];return{sign:i,recid:parseInt(p)}})}connect(e,t){return new Promise((r,s)=>{let i=0,p;u(e)?(p="signgen",e.message=v(new TextEncoder().encode(e.message))):p="keygen";let c=new WebSocket("".concat(this.walletProviderUrl,"/").concat(p));c.addEventListener("open",o=>{switch(console.log("Connection opened in state ".concat(i," with event ").concat(JSON.stringify(o,void 0," "))),i){case 0:i=1,console.log("Sending setup: ".concat(JSON.stringify(e))),c.send(JSON.stringify(e));break;case 1:case 2:i=3,s("Incorrect protocol state");break;case 3:break}}),c.addEventListener("message",async o=>{switch(console.log("Connection message in state ".concat(i," with event ").concat(JSON.stringify(o,void 0," "))),i){case 0:i=3,s("Incorrect protocol state");break;case 1:{i=2;let l=await t(o.data);l.credentials.method==="passkey"&&(this.passkeyCredentialId=l.passkeyCredentialId),console.log("Sending signature: ".concat(JSON.stringify(l))),c.send(JSON.stringify(l));break}case 2:i=3,c.close(),r(o.data);break;case 3:break}}),c.addEventListener("error",o=>{console.log("Connection error in state ".concat(i," with event ").concat(JSON.stringify(o,void 0," "))),i!=3&&(i=3,s("Incorrect protocol state"))}),c.addEventListener("close",o=>{console.log("Connection closed in state ".concat(i," with event ").concat(JSON.stringify(o,void 0," "))),i!=3&&(i=3,s("Incorrect protocol state"))})})}};import*as d from"viem";import{publicKeyToAddress as W,toAccount as _e}from"viem/accounts";import{secp256k1 as ne}from"@noble/curves/secp256k1";function ie(n){if(n.startsWith("0x")&&(n=n.slice(2)),n.startsWith("04"))return W("0x".concat(n," "));if(n.startsWith("02")||n.startsWith("03")){let e=ne.ProjectivePoint.fromHex(n).toHex(!1);return W("0x".concat(e))}else throw new Error("Invalid public key")}export{I as EOAAuth,K as EphAuth,A as NetworkSigner,C as PasskeyAuth,x as WalletProviderServiceClient,ie as computeAddress};
@@ -1,5 +1,5 @@
1
- import { AuthModule, UserAuthentication } from './authentication.ts';
2
- import { type IWalletProviderServiceClient } from './walletProviderServiceClientInterface.ts';
1
+ import { AuthModule, UserAuthentication } from './authentication';
2
+ import { type IWalletProviderServiceClient } from './walletProviderServiceClientInterface';
3
3
  /**
4
4
  * Response from the network for keygen requests
5
5
  * @alpha
@@ -19,6 +19,10 @@ export interface KeygenResponse {
19
19
  * where Y is set to 0x02 if Y-coord is even, or 0x03 if Y-coord is odd
20
20
  */
21
21
  publicKey: string;
22
+ /**
23
+ * Optional credential id used for passkey authentication
24
+ */
25
+ passkeyCredentialId?: string;
22
26
  }
23
27
  /**
24
28
  * Response from the network for sign request
@@ -49,12 +53,12 @@ export declare class KeygenSetupOpts {
49
53
  tag: number;
50
54
  value: string;
51
55
  }[];
52
- constructor({ t, n, key_label, permissions, ephPK, }: {
56
+ constructor({ t, n, ephPK, key_label, permissions, }: {
53
57
  t: number;
54
58
  n: number;
59
+ ephPK: string;
55
60
  key_label?: string;
56
61
  permissions?: string;
57
- ephPK?: string;
58
62
  });
59
63
  }
60
64
  /** Parameters used in Signature execution */
@@ -101,7 +105,6 @@ export declare class NetworkSigner {
101
105
  * The permissions are validated during sign requests.
102
106
  * @returns {@link KeygenResponse} containing `keyId` and the `pubKey` public part of the key
103
107
  * @public
104
- * @alpha
105
108
  */
106
109
  authenticateAndCreateKey(ephKey: Uint8Array, permissions?: string): Promise<KeygenResponse>;
107
110
  /** Generate a signature. Uses `authModule` to authenticate the sign request by the User.
@@ -110,7 +113,6 @@ export declare class NetworkSigner {
110
113
  * @param message - the message to sign by the MPC network
111
114
  * @returns {@link SignResponse}
112
115
  * @public
113
- * @alpha
114
116
  */
115
117
  authenticateAndSign(keyId: string, message: string): Promise<SignResponse>;
116
118
  }
@@ -0,0 +1,32 @@
1
+ import { UserAuthentication } from './authentication';
2
+ /** Information about the user currently registering. Read more: https://w3c.github.io/webauthn/#dom-publickeycredentialcreationoptions-user
3
+ * @alpha
4
+ * */
5
+ export type PasskeyUser = {
6
+ id: string;
7
+ name: string;
8
+ displayName: string;
9
+ };
10
+ /** The RP responsible for registering and authenticating the user. Read more: https://w3c.github.io/webauthn/#dom-publickeycredentialcreationoptions-rp
11
+ * @alpha
12
+ * */
13
+ export type RelyingPartyConfig = {
14
+ rpName: string;
15
+ rpId: string;
16
+ };
17
+ export declare function passkeyRegister({ user, ephId, challenge, rpConfig, ephPK, lifetime, }: {
18
+ user: PasskeyUser;
19
+ ephId: string;
20
+ challenge: string;
21
+ rpConfig: RelyingPartyConfig;
22
+ ephPK: Uint8Array;
23
+ lifetime: number;
24
+ }): Promise<UserAuthentication>;
25
+ export declare function passkeyLogin({ ephId, challenge, credentialId, rpConfig, ephPK, lifetime, }: {
26
+ ephId: string;
27
+ challenge: string;
28
+ credentialId: string;
29
+ rpConfig: RelyingPartyConfig;
30
+ ephPK: Uint8Array;
31
+ lifetime: number;
32
+ }): Promise<UserAuthentication>;
@@ -9,5 +9,7 @@ import { NetworkSigner } from './networkSigner';
9
9
  * @param threshold The threshold.
10
10
  */
11
11
  export declare function createViemAccount(networkSigner: NetworkSigner, keyId: string, publicKey: string): viem.LocalAccount;
12
- /** Computes ETH address from ECDSA `publicKey` returned by Silent Network */
12
+ /** Computes ETH address from ECDSA `publicKey` returned by Silent Network
13
+ * @public
14
+ */
13
15
  export declare function computeAddress(publicKey: string): viem.Address;
@@ -8,6 +8,7 @@ import { type ClientConfig, IWalletProviderServiceClient, type Signer } from './
8
8
  export declare class WalletProviderServiceClient implements IWalletProviderServiceClient {
9
9
  walletProviderId: string;
10
10
  walletProviderUrl: string;
11
+ passkeyCredentialId?: string;
11
12
  /**
12
13
  * Create new client that connects to the backend service
13
14
  * @param config - config containing information about backend service
@@ -22,5 +23,5 @@ export declare class WalletProviderServiceClient implements IWalletProviderServi
22
23
  setup: SignSetupOpts;
23
24
  signer: Signer;
24
25
  }): Promise<SignResponse>;
25
- connect(params: KeygenSetupOpts | SignSetupOpts, signer: Signer): Promise<string>;
26
+ connect(setupOpts: KeygenSetupOpts | SignSetupOpts, signer: Signer): Promise<string>;
26
27
  }
package/package.json CHANGED
@@ -1,9 +1,18 @@
1
1
  {
2
2
  "name": "@silencelaboratories/walletprovider-sdk",
3
- "version": "0.0.10",
3
+ "version": "0.2.0",
4
+ "author": "Silence Laboratories",
4
5
  "description": "Frontend SDK for Wallet Providers",
5
- "main": "dist/index.js",
6
- "types": "dist/index.d.ts",
6
+ "main": "./dist/index.cjs.js",
7
+ "module": "./dist/index.esm.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "require": "./dist/index.cjs.js",
13
+ "import": "./dist/index.esm.js"
14
+ }
15
+ },
7
16
  "files": [
8
17
  "dist"
9
18
  ],
@@ -12,27 +21,29 @@
12
21
  "formatcheck": "prettier --check --cache .",
13
22
  "lint": "eslint --cache ./src/**/*.ts",
14
23
  "typecheck": "tsc -p . --noEmit",
15
- "build": "bun run scripts/build.mjs && bun run build:declaration",
24
+ "build": "npm run clean && node build.js && npm run build:declaration",
16
25
  "build:declaration": "tsc -p . --emitDeclarationOnly",
17
- "test": "bun test",
18
- "test:watch": "bun test --watch",
19
- "docs": "bun run build:declaration && api-extractor run --local --verbose && api-documenter markdown -i ./temp -o ./docs"
26
+ "clean": "rimraf dist",
27
+ "prepack": "npm run clean && npm run build && npm run build:declaration",
28
+ "docs": "npm run build:declaration && api-extractor run --local --verbose && api-documenter markdown -i ./temp -o ./docs"
20
29
  },
21
- "type": "module",
22
30
  "devDependencies": {
23
31
  "@eslint/js": "^9.3.0",
24
32
  "@microsoft/api-documenter": "^7.25.2",
25
33
  "@microsoft/api-extractor": "^7.46.2",
26
- "@types/bun": "^1.1.2",
34
+ "esbuild": "^0.23.0",
35
+ "esbuild-node-externals": "^1.14.0",
27
36
  "eslint": "^8.x",
28
37
  "globals": "^15.3.0",
38
+ "npm-dts": "^1.3.13",
29
39
  "prettier": "^3.2.5",
40
+ "rimraf": "^6.0.1",
30
41
  "typescript": "^5.4.5",
31
42
  "typescript-eslint": "^7.11.0"
32
43
  },
33
44
  "dependencies": {
34
- "@noble/ed25519": "^2.1.0",
35
- "@noble/secp256k1": "^2.1.0",
45
+ "@noble/curves": "^1.4.2",
46
+ "js-base64": "^3.7.7",
36
47
  "viem": "^2.11.1"
37
48
  }
38
49
  }
package/dist/index.js DELETED
@@ -1 +0,0 @@
1
- import{toHex as N8} from"viem";function m(Q){return Q.message!==void 0}var V8=1,U8=2;class C{t;n;key_label;metadata;constructor({t:Q,n:Z,key_label:X,permissions:$,ephPK:Y}){if(this.t=Q,this.n=Z,this.key_label=X,this.metadata=[],$)this.metadata.push({tag:V8,value:$});if(Y)this.metadata.push({tag:U8,value:Y})}}class o{authModule;threshold;totalNodes;wp_client;constructor(Q,Z,X,$){if(Z===0)throw new Error("Threshold cannot be 0");this.threshold=Z,this.totalNodes=X,this.authModule=$,this.wp_client=Q}async authenticateAndCreateKey(Q,Z){try{const X=new C({t:this.threshold,n:this.totalNodes,permissions:Z,ephPK:N8(Q)});console.log("Generated Payload:",X);const $=(z)=>this.authModule.authenticate({setup:X,challenge:z}),Y=await this.wp_client.startKeygen({setup:X,signer:$});return console.log("Keygen response:",Y),Y}catch(X){throw console.error(X),X}}async authenticateAndSign(Q,Z){const X={t:this.threshold,key_id:Q,message:Z},$=(z)=>this.authModule.authenticate({setup:X,challenge:z}),Y=await this.wp_client.startSigngen({setup:X,signer:$});return console.log("Sign response:",Y),Y}}import{toHex as H} from"viem";import*as E from"@noble/ed25519";var R8=function(Q,...Z){if(!(Q instanceof Uint8Array))throw new Error("Expected Uint8Array");if(Z.length>0&&!Z.includes(Q.length))throw new Error(`Expected Uint8Array of length ${Z}, not of length=${Q.length}`)};var d=function(Q,Z=!0){if(Q.destroyed)throw new Error("Hash instance has been destroyed");if(Z&&Q.finished)throw new Error("Hash#digest() has already been called")},h=function(Q,Z){R8(Q);const X=Z.outputLen;if(Q.length<X)throw new Error(`digestInto() expects output buffer of length at least ${X}`)};function O8(Q){if(typeof Q!=="string")throw new Error(`utf8ToBytes expected string, got ${typeof Q}`);return new Uint8Array((new TextEncoder()).encode(Q))}function c(Q){if(typeof Q==="string")Q=O8(Q);if(!x8(Q))throw new Error(`expected Uint8Array, got ${typeof Q}`);return Q}function a(Q){const Z=($)=>Q().update(c($)).digest(),X=Q();return Z.outputLen=X.outputLen,Z.blockLen=X.blockLen,Z.create=()=>Q(),Z}/*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) */var x8=(Q)=>Q instanceof Uint8Array;var y=(Q)=>new DataView(Q.buffer,Q.byteOffset,Q.byteLength);var T8=new Uint8Array(new Uint32Array([287454020]).buffer)[0]===68;if(!T8)throw new Error("Non little-endian hardware is not supported");class p{clone(){return this._cloneInto()}}var l8={}.toString;var F8=function(Q,Z,X,$){if(typeof Q.setBigUint64==="function")return Q.setBigUint64(Z,X,$);const Y=BigInt(32),z=BigInt(4294967295),q=Number(X>>Y&z),N=Number(X&z),R=$?4:0,O=$?0:4;Q.setUint32(Z+R,q,$),Q.setUint32(Z+O,N,$)};class u extends p{constructor(Q,Z,X,$){super();this.blockLen=Q,this.outputLen=Z,this.padOffset=X,this.isLE=$,this.finished=!1,this.length=0,this.pos=0,this.destroyed=!1,this.buffer=new Uint8Array(Q),this.view=y(this.buffer)}update(Q){d(this);const{view:Z,buffer:X,blockLen:$}=this;Q=c(Q);const Y=Q.length;for(let z=0;z<Y;){const q=Math.min($-this.pos,Y-z);if(q===$){const N=y(Q);for(;$<=Y-z;z+=$)this.process(N,z);continue}if(X.set(Q.subarray(z,z+q),this.pos),this.pos+=q,z+=q,this.pos===$)this.process(Z,0),this.pos=0}return this.length+=Q.length,this.roundClean(),this}digestInto(Q){d(this),h(Q,this),this.finished=!0;const{buffer:Z,view:X,blockLen:$,isLE:Y}=this;let{pos:z}=this;if(Z[z++]=128,this.buffer.subarray(z).fill(0),this.padOffset>$-z)this.process(X,0),z=0;for(let V=z;V<$;V++)Z[V]=0;F8(X,$-8,BigInt(this.length*8),Y),this.process(X,0);const q=y(Q),N=this.outputLen;if(N%4)throw new Error("_sha2: outputLen should be aligned to 32bit");const R=N/4,O=this.get();if(R>O.length)throw new Error("_sha2: outputLen bigger than state");for(let V=0;V<R;V++)q.setUint32(4*V,O[V],Y)}digest(){const{buffer:Q,outputLen:Z}=this;this.digestInto(Q);const X=Q.slice(0,Z);return this.destroy(),X}_cloneInto(Q){Q||(Q=new this.constructor),Q.set(...this.get());const{blockLen:Z,buffer:X,length:$,finished:Y,destroyed:z,pos:q}=this;if(Q.length=$,Q.pos=q,Q.finished=Y,Q.destroyed=z,$%Z)Q.buffer.set(X);return Q}}var l=function(Q,Z=!1){if(Z)return{h:Number(Q&_),l:Number(Q>>n&_)};return{h:Number(Q>>n&_)|0,l:Number(Q&_)|0}},G8=function(Q,Z=!1){let X=new Uint32Array(Q.length),$=new Uint32Array(Q.length);for(let Y=0;Y<Q.length;Y++){const{h:z,l:q}=l(Q[Y],Z);[X[Y],$[Y]]=[z,q]}return[X,$]},L8=function(Q,Z,X,$){const Y=(Z>>>0)+($>>>0);return{h:Q+X+(Y/4294967296|0)|0,l:Y|0}},_=BigInt(4294967295),n=BigInt(32),j8=(Q,Z)=>BigInt(Q>>>0)<<n|BigInt(Z>>>0),I8=(Q,Z,X)=>Q>>>X,M8=(Q,Z,X)=>Q<<32-X|Z>>>X,D8=(Q,Z,X)=>Q>>>X|Z<<32-X,W8=(Q,Z,X)=>Q<<32-X|Z>>>X,k8=(Q,Z,X)=>Q<<64-X|Z>>>X-32,v8=(Q,Z,X)=>Q>>>X-32|Z<<64-X,P8=(Q,Z)=>Z,w8=(Q,Z)=>Q,K8=(Q,Z,X)=>Q<<X|Z>>>32-X,B8=(Q,Z,X)=>Z<<X|Q>>>32-X,E8=(Q,Z,X)=>Z<<X-32|Q>>>64-X,f8=(Q,Z,X)=>Q<<X-32|Z>>>64-X,C8=(Q,Z,X)=>(Q>>>0)+(Z>>>0)+(X>>>0),m8=(Q,Z,X,$)=>Z+X+$+(Q/4294967296|0)|0,y8=(Q,Z,X,$)=>(Q>>>0)+(Z>>>0)+(X>>>0)+($>>>0),_8=(Q,Z,X,$,Y)=>Z+X+$+Y+(Q/4294967296|0)|0,H8=(Q,Z,X,$,Y)=>(Q>>>0)+(Z>>>0)+(X>>>0)+($>>>0)+(Y>>>0),b8=(Q,Z,X,$,Y,z)=>Z+X+$+Y+z+(Q/4294967296|0)|0;var A8={fromBig:l,split:G8,toBig:j8,shrSH:I8,shrSL:M8,rotrSH:D8,rotrSL:W8,rotrBH:k8,rotrBL:v8,rotr32H:P8,rotr32L:w8,rotlSH:K8,rotlSL:B8,rotlBH:E8,rotlBL:f8,add:L8,add3L:C8,add3H:m8,add4L:y8,add4H:_8,add5H:b8,add5L:H8},J=A8;var[g8,S8]=(()=>J.split(["0x428a2f98d728ae22","0x7137449123ef65cd","0xb5c0fbcfec4d3b2f","0xe9b5dba58189dbbc","0x3956c25bf348b538","0x59f111f1b605d019","0x923f82a4af194f9b","0xab1c5ed5da6d8118","0xd807aa98a3030242","0x12835b0145706fbe","0x243185be4ee4b28c","0x550c7dc3d5ffb4e2","0x72be5d74f27b896f","0x80deb1fe3b1696b1","0x9bdc06a725c71235","0xc19bf174cf692694","0xe49b69c19ef14ad2","0xefbe4786384f25e3","0x0fc19dc68b8cd5b5","0x240ca1cc77ac9c65","0x2de92c6f592b0275","0x4a7484aa6ea6e483","0x5cb0a9dcbd41fbd4","0x76f988da831153b5","0x983e5152ee66dfab","0xa831c66d2db43210","0xb00327c898fb213f","0xbf597fc7beef0ee4","0xc6e00bf33da88fc2","0xd5a79147930aa725","0x06ca6351e003826f","0x142929670a0e6e70","0x27b70a8546d22ffc","0x2e1b21385c26c926","0x4d2c6dfc5ac42aed","0x53380d139d95b3df","0x650a73548baf63de","0x766a0abb3c77b2a8","0x81c2c92e47edaee6","0x92722c851482353b","0xa2bfe8a14cf10364","0xa81a664bbc423001","0xc24b8b70d0f89791","0xc76c51a30654be30","0xd192e819d6ef5218","0xd69906245565a910","0xf40e35855771202a","0x106aa07032bbd1b8","0x19a4c116b8d2d0c8","0x1e376c085141ab53","0x2748774cdf8eeb99","0x34b0bcb5e19b48a8","0x391c0cb3c5c95a63","0x4ed8aa4ae3418acb","0x5b9cca4f7763e373","0x682e6ff3d6b2b8a3","0x748f82ee5defb2fc","0x78a5636f43172f60","0x84c87814a1f0ab72","0x8cc702081a6439ec","0x90befffa23631e28","0xa4506cebde82bde9","0xbef9a3f7b2c67915","0xc67178f2e372532b","0xca273eceea26619c","0xd186b8c721c0c207","0xeada7dd6cde0eb1e","0xf57d4f7fee6ed178","0x06f067aa72176fba","0x0a637dc5a2c898a6","0x113f9804bef90dae","0x1b710b35131c471b","0x28db77f523047d84","0x32caab7b40c72493","0x3c9ebe0a15c9bebc","0x431d67c49c100d4c","0x4cc5d4becb3e42b6","0x597f299cfc657e2a","0x5fcb6fab3ad6faec","0x6c44198c4a475817"].map((Q)=>BigInt(Q))))(),v=new Uint32Array(80),P=new Uint32Array(80);class s extends u{constructor(){super(128,64,16,!1);this.Ah=1779033703|0,this.Al=4089235720|0,this.Bh=3144134277|0,this.Bl=2227873595|0,this.Ch=1013904242|0,this.Cl=4271175723|0,this.Dh=2773480762|0,this.Dl=1595750129|0,this.Eh=1359893119|0,this.El=2917565137|0,this.Fh=2600822924|0,this.Fl=725511199|0,this.Gh=528734635|0,this.Gl=4215389547|0,this.Hh=1541459225|0,this.Hl=327033209|0}get(){const{Ah:Q,Al:Z,Bh:X,Bl:$,Ch:Y,Cl:z,Dh:q,Dl:N,Eh:R,El:O,Fh:V,Fl:T,Gh:F,Gl:G,Hh:j,Hl:I}=this;return[Q,Z,X,$,Y,z,q,N,R,O,V,T,F,G,j,I]}set(Q,Z,X,$,Y,z,q,N,R,O,V,T,F,G,j,I){this.Ah=Q|0,this.Al=Z|0,this.Bh=X|0,this.Bl=$|0,this.Ch=Y|0,this.Cl=z|0,this.Dh=q|0,this.Dl=N|0,this.Eh=R|0,this.El=O|0,this.Fh=V|0,this.Fl=T|0,this.Gh=F|0,this.Gl=G|0,this.Hh=j|0,this.Hl=I|0}process(Q,Z){for(let U=0;U<16;U++,Z+=4)v[U]=Q.getUint32(Z),P[U]=Q.getUint32(Z+=4);for(let U=16;U<80;U++){const W=v[U-15]|0,k=P[U-15]|0,b=J.rotrSH(W,k,1)^J.rotrSH(W,k,8)^J.shrSH(W,k,7),A=J.rotrSL(W,k,1)^J.rotrSL(W,k,8)^J.shrSL(W,k,7),M=v[U-2]|0,D=P[U-2]|0,f=J.rotrSH(M,D,19)^J.rotrBH(M,D,61)^J.shrSH(M,D,6),g=J.rotrSL(M,D,19)^J.rotrBL(M,D,61)^J.shrSL(M,D,6),L=J.add4L(A,g,P[U-7],P[U-16]),S=J.add4H(L,b,f,v[U-7],v[U-16]);v[U]=S|0,P[U]=L|0}let{Ah:X,Al:$,Bh:Y,Bl:z,Ch:q,Cl:N,Dh:R,Dl:O,Eh:V,El:T,Fh:F,Fl:G,Gh:j,Gl:I,Hh:K,Hl:B}=this;for(let U=0;U<80;U++){const W=J.rotrSH(V,T,14)^J.rotrSH(V,T,18)^J.rotrBH(V,T,41),k=J.rotrSL(V,T,14)^J.rotrSL(V,T,18)^J.rotrBL(V,T,41),b=V&F^~V&j,A=T&G^~T&I,M=J.add5L(B,k,A,S8[U],P[U]),D=J.add5H(M,K,W,b,g8[U],v[U]),f=M|0,g=J.rotrSH(X,$,28)^J.rotrBH(X,$,34)^J.rotrBH(X,$,39),L=J.rotrSL(X,$,28)^J.rotrBL(X,$,34)^J.rotrBL(X,$,39),S=X&Y^X&q^Y&q,q8=$&z^$&N^z&N;K=j|0,B=I|0,j=F|0,I=G|0,F=V|0,G=T|0,{h:V,l:T}=J.add(R|0,O|0,D|0,f|0),R=q|0,O=N|0,q=Y|0,N=z|0,Y=X|0,z=$|0;const r=J.add3L(f,L,q8);X=J.add3H(r,D,g,S),$=r|0}({h:X,l:$}=J.add(this.Ah|0,this.Al|0,X|0,$|0)),{h:Y,l:z}=J.add(this.Bh|0,this.Bl|0,Y|0,z|0),{h:q,l:N}=J.add(this.Ch|0,this.Cl|0,q|0,N|0),{h:R,l:O}=J.add(this.Dh|0,this.Dl|0,R|0,O|0),{h:V,l:T}=J.add(this.Eh|0,this.El|0,V|0,T|0),{h:F,l:G}=J.add(this.Fh|0,this.Fl|0,F|0,G|0),{h:j,l:I}=J.add(this.Gh|0,this.Gl|0,j|0,I|0),{h:K,l:B}=J.add(this.Hh|0,this.Hl|0,K|0,B|0),this.set(X,$,Y,z,q,N,R,O,V,T,F,G,j,I,K,B)}roundClean(){v.fill(0),P.fill(0)}destroy(){this.buffer.fill(0),this.set(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)}}var t=a(()=>new s);var n8=function(Q,Z,X){console.log("EPHKEY",X);const $=new C({t:Q.t,n:Q.n,key_label:Q.key_label,permissions:void 0,ephPK:H(X)});return console.log("SETUP_NO_PERM",$),{types:{EIP712Domain:u8,...c8},domain:p8,primaryType:"Request",message:{setup:$,challenge:Z}}};async function e({setup:Q,user_id:Z,challenge:X,browserWallet:$,ephPK:Y,lifetime:z}){if(m(Q))throw new Error("EOA auth cannot be used for Sign requests, please use EphAuth instead");const q=n8(Q,X,Y);console.log("typed request:"),console.log(JSON.stringify(q,void 0,4));const N=await $.signTypedData(Z,q);console.log("User signed a request",N);const R={eoa:Z,ephPK:H(Y),expiry:Math.floor(Date.now()/1000)+z};return{credentials:{credentials:JSON.stringify(R),method:"eoa",id:Z},signature:N}}async function Q8({setup:Q,user_id:Z,challenge:X,ephSK:$,ephPK:Y}){const z={setup:Q,challenge:X},N=H(await E.signAsync((new TextEncoder()).encode(JSON.stringify(z)),$));console.log("AUTH SIGNATURE by eph key",N),console.log("User signed a request",N);const R={eoa:Z,ephPK:H(Y),expiry:0};return{credentials:{credentials:JSON.stringify(R),method:"ephemeral",id:Z},signature:N}}E.etc.sha512Sync=(...Q)=>t(E.etc.concatBytes(...Q));var d8=[{name:"tag",type:"uint16"},{name:"value",type:"string"}],c8={Request:[{name:"setup",type:"KeygenSetupOpts"},{name:"challenge",type:"string"}],KeygenSetupOpts:[{name:"t",type:"uint32"},{name:"n",type:"uint32"},{name:"metadata",type:"TaggedValue[]"}],TaggedValue:d8},p8={name:"SilentShard authentication",version:"0.1.0"},u8=[{name:"name",type:"string"},{name:"version",type:"string"}];import*as X8 from"@noble/ed25519";var i;(function(X){X[X["EOA"]=0]="EOA";X[X["NONE"]=1]="NONE"})(i||(i={}));class Z8{userId;browserWallet;ephPK;lifetime;constructor(Q,Z,X,$=3600){this.userId=Q,this.browserWallet=Z,this.ephPK=X,this.lifetime=$}async authenticate({setup:Q,challenge:Z}){return await e({setup:Q,user_id:this.userId,challenge:Z,browserWallet:this.browserWallet,ephPK:this.ephPK,lifetime:this.lifetime})}}class $8{userId;ephSK;ephPK;constructor(Q,Z){this.userId=Q,this.ephSK=Z,this.ephPK=X8.getPublicKey(this.ephSK)}async authenticate({setup:Q,challenge:Z}){return await Q8({setup:Q,user_id:this.userId,challenge:Z,ephSK:this.ephSK,ephPK:this.ephPK})}}var Y8=(Q)=>btoa(String.fromCodePoint.apply(null,Array.from(Q)));var x;(function(Y){Y[Y["initiated"]=0]="initiated";Y[Y["waitingForSign"]=1]="waitingForSign";Y[Y["waitingForResult"]=2]="waitingForResult";Y[Y["finished"]=3]="finished"})(x||(x={}));class z8{walletProviderId;walletProviderUrl;constructor(Q){this.walletProviderId=Q.walletProviderId,this.walletProviderUrl=Q.walletProviderUrl}getWalletId(){return this.walletProviderId}async startKeygen({setup:Q,signer:Z}){return this.connect(Q,Z).then((X)=>{const $=X.split(":"),Y=$[1].split("=")[1],z=$[0].split("=")[1];return{publicKey:Y,keyId:z}})}async startSigngen({setup:Q,signer:Z}){return this.connect(Q,Z).then((X)=>{const $=X.split(":"),Y=$[0].split("=")[1],z=$[1].split("=")[1];return{sign:Y,recid:parseInt(z)}})}connect(Q,Z){return new Promise((X,$)=>{let Y=x.initiated,z;if(m(Q))z="signgen",Q.message=Y8((new TextEncoder()).encode(Q.message));else z="keygen";const q=new WebSocket(`${this.walletProviderUrl}/${z}`);q.addEventListener("open",(N)=>{switch(console.log(`Connection opened in state ${Y} with event ${JSON.stringify(N,void 0,"\t")}`),Y){case x.initiated:Y=x.waitingForSign,console.log(`Sending setup: ${JSON.stringify(Q)}`),q.send(JSON.stringify(Q));break;case x.waitingForSign:case x.waitingForResult:Y=x.finished,$("Incorrect protocol state");break;case x.finished:break}}),q.addEventListener("message",async(N)=>{switch(console.log(`Connection message in state ${Y} with event ${JSON.stringify(N,void 0,"\t")}`),Y){case x.initiated:Y=x.finished,$("Incorrect protocol state");break;case x.waitingForSign:{Y=x.waitingForResult;const R=await Z(N.data);console.log(`Sending signature: ${JSON.stringify(R)}`),q.send(JSON.stringify(R));break}case x.waitingForResult:Y=x.finished,q.close(),X(N.data);break;case x.finished:break}}),q.addEventListener("error",(N)=>{if(console.log(`Connection error in state ${Y} with event ${JSON.stringify(N,void 0,"\t")}`),Y!=x.finished)Y=x.finished,$("Incorrect protocol state")}),q.addEventListener("close",(N)=>{if(console.log(`Connection closed in state ${Y} with event ${JSON.stringify(N,void 0,"\t")}`),Y!=x.finished)Y=x.finished,$("Incorrect protocol state")})})}}import*as w from"viem";import{publicKeyToAddress as J8,toAccount as D0} from"viem/accounts";import{ProjectivePoint as i8} from"@noble/secp256k1";function r8(Q){if(Q.startsWith("0x"))Q=Q.slice(2);if(Q.startsWith("04"))return J8(`0x${Q} `);else if(Q.startsWith("02")||Q.startsWith("03")){const Z=i8.fromHex(Q).toHex(!1);return J8(`0x${Z}`)}else throw new Error("Invalid public key")}export{r8 as computeAddress,z8 as WalletProviderServiceClient,o as NetworkSigner,$8 as EphAuth,Z8 as EOAAuth,i as AuthMethod};