@silencelaboratories/walletprovider-sdk
Advanced tools
Comparing version 0.2.0 to 0.3.0
@@ -1,4 +0,5 @@ | ||
import { KeygenSetupOpts, SignSetupOpts } from './networkSigner'; | ||
import { AddEphemeralKeyOpts, KeygenSetupOpts, SignSetupOpts } from './networkSigner'; | ||
import { IBrowserWallet } from './EOAauthentication'; | ||
import { PasskeyUser, RelyingPartyConfig } from './passkeyAuthentication'; | ||
import { EphClaim } from './ephemeralAuthentication'; | ||
/** Type of the request authentication | ||
@@ -9,5 +10,4 @@ * @alpha | ||
id: string; | ||
method: string; | ||
method: 'eoa' | 'ephemeral' | 'passkey'; | ||
credentials: string; | ||
ephId?: string; | ||
}; | ||
@@ -17,26 +17,33 @@ export type UserAuthentication = { | ||
signature: string; | ||
passkeyCredentialId?: string; | ||
}; | ||
export interface AuthModule { | ||
authenticate({ setup, challenge, }: { | ||
setup: KeygenSetupOpts | SignSetupOpts; | ||
setup: KeygenSetupOpts | SignSetupOpts | AddEphemeralKeyOpts; | ||
challenge: string; | ||
}): Promise<UserAuthentication>; | ||
} | ||
export interface DkgAuthModule extends AuthModule { | ||
get ephClaim(): EphClaim; | ||
} | ||
/** The `EOAAuth` implementing Externally Owned Account authentication. | ||
* @alpha | ||
*/ | ||
export declare class EOAAuth implements AuthModule { | ||
/** Ephemeral id identify ephemeral key */ | ||
ephId: string; | ||
export declare class EOAAuth implements DkgAuthModule { | ||
/** An interface to the wallet, like MetaMask, that is used to sign the requests */ | ||
browserWallet: IBrowserWallet; | ||
/** Public key of the ephemeral key */ | ||
ephPK: Uint8Array; | ||
/** Lifetime of the ephemeral key */ | ||
lifetime: number; | ||
private browserWallet; | ||
/** the ETH address that is used to do EOA authentication */ | ||
eoa: string; | ||
constructor(ephId: string, eoa: string, browserWallet: IBrowserWallet, ephPK: Uint8Array, lifetime?: number); | ||
private eoa; | ||
/** Ephemeral key claim */ | ||
ephClaim: EphClaim; | ||
/** | ||
* | ||
* @param ephId - Ephemeral key ID | ||
* @param eoa - Ethereum address | ||
* @param browserWallet - Interface to the wallet provider, like MetaMask, that is used to sign the requests | ||
* @param ephPK - Ephemeral public key | ||
* @param lifetime - Lifetime of the ephemeral key. Default is 1 hour | ||
*/ | ||
constructor(ephId: string, eoa: string, browserWallet: IBrowserWallet, ephPK: Uint8Array, lifetime: number); | ||
private validateInputs; | ||
/** | ||
* Prepares a message to present on the Browser Wallet window and requests to sign it. | ||
@@ -60,8 +67,11 @@ * @param setup - Keygen setup options | ||
export declare class EphAuth implements AuthModule { | ||
/** Ephemeral id identify ephemeral key */ | ||
ephId: string; | ||
/** Secret key of the ephemeral keypair */ | ||
ephSK: Uint8Array; | ||
/** Public key of the ephemeral keypair */ | ||
ephPK: Uint8Array; | ||
private ephSK; | ||
/** Ephemeral key claim */ | ||
private ephClaim; | ||
/** | ||
* | ||
* @param ephId - Ephemeral key ID | ||
* @param ephSK - Ephemeral secret key | ||
*/ | ||
constructor(ephId: string, ephSK: Uint8Array); | ||
@@ -83,20 +93,25 @@ /** | ||
*/ | ||
export declare class PasskeyAuth implements AuthModule { | ||
export declare class PasskeyAuth implements DkgAuthModule { | ||
/** Replying party object. Read more: https://developer.mozilla.org/en-US/docs/Web/API/PublicKeyCredentialCreationOptions#rp */ | ||
rpConfig: RelyingPartyConfig; | ||
/** Passkey user information. Read more: https://developer.mozilla.org/en-US/docs/Web/API/PublicKeyCredentialCreationOptions#user */ | ||
user: PasskeyUser; | ||
/** Public key of the ephemeral key */ | ||
ephPK: Uint8Array; | ||
/** Lifetime of the ephemeral key */ | ||
lifetime: number; | ||
/** Ephemeral id identify ephemeral key */ | ||
ephId: string; | ||
/** Credential id that user and authenticator acknowledges about */ | ||
credentialId: string | null; | ||
constructor(rpConfig: RelyingPartyConfig, user: PasskeyUser, ephId: string, ephPK: Uint8Array, lifetime: number | undefined, credentialId: string | null); | ||
authenticate({ setup, challenge }: { | ||
setup: KeygenSetupOpts; | ||
private rpConfig; | ||
/** ID of the acceptable credential by user. App proves that user has passkey credential by passing the value of this field */ | ||
private allowCredentialId; | ||
/** Passkey user information, only requires while registering. Read more: https://developer.mozilla.org/en-US/docs/Web/API/PublicKeyCredentialCreationOptions#user */ | ||
private user; | ||
/** Ephemeral key claim */ | ||
ephClaim: EphClaim; | ||
/** | ||
* | ||
* @param rpConfig - Passkey relying party configuration. Read more: https://developer.mozilla.org/en-US/docs/Web/API/PublicKeyCredentialCreationOptions#rp | ||
* @param user - Passkey user information, only requires while registering. Read more: https://developer.mozilla.org/en-US/docs/Web/API/PublicKeyCredentialCreationOptions#user | ||
* @param allowCredentialId - ID of the acceptable credential by user. App proves that user has passkey credential by passing the value of this field | ||
* @param ephId - Ephemeral key ID | ||
* @param ephPK - Ephemeral public key | ||
* @param lifetime - Lifetime of the ephemeral key. Default is 1 hour | ||
*/ | ||
constructor(rpConfig: RelyingPartyConfig, user: PasskeyUser | null, allowCredentialId: string | null, ephId: string, ephPK: Uint8Array, lifetime: number); | ||
authenticate({ setup, challenge, }: { | ||
setup: KeygenSetupOpts | AddEphemeralKeyOpts; | ||
challenge: string; | ||
}): Promise<UserAuthentication>; | ||
} |
@@ -7,2 +7,3 @@ /** Externally Owned Account (EOA) atuhentication. Uses secret key stored on a wallet to sign requests. | ||
import { type TypedDataDomain } from 'viem'; | ||
import { EphClaim } from './ephemeralAuthentication'; | ||
export type FieldDefinition = { | ||
@@ -51,10 +52,8 @@ name: string; | ||
*/ | ||
export declare function authenticateUsingEOA({ setup, ephId, eoa, challenge, browserWallet, ephPK, lifetime, }: { | ||
export declare function authenticateUsingEOA({ setup, eoa, challenge, browserWallet, ephClaim, }: { | ||
setup: KeygenSetupOpts; | ||
ephId: string; | ||
eoa: string; | ||
challenge: string; | ||
browserWallet: IBrowserWallet; | ||
ephPK: Uint8Array; | ||
lifetime: number; | ||
ephClaim: EphClaim; | ||
}): Promise<UserAuthentication>; |
import { UserAuthentication } from './authentication'; | ||
import { SignSetupOpts } from './networkSigner'; | ||
export type EphClaim = { | ||
export declare class EphClaim { | ||
ephId: string; | ||
ephPK: string; | ||
expiry: number; | ||
}; | ||
constructor(ephId: string, ephPK: Uint8Array, lifetime?: number); | ||
private validateInputs; | ||
toJSON(): string; | ||
} | ||
/** Locally sign the signature requests to network without asking the user, the ephSK is registered during keygen. | ||
* The signature is the authorization for signgen operation | ||
*/ | ||
export declare function authenticateUsingEphKey({ setup, ephId, challenge, ephSK, ephPK, }: { | ||
export declare function authenticateUsingEphKey({ setup, challenge, ephSK, ephClaim, }: { | ||
setup: SignSetupOpts; | ||
ephId: string; | ||
challenge: string; | ||
ephSK: Uint8Array; | ||
ephPK: Uint8Array; | ||
ephClaim: EphClaim; | ||
}): Promise<UserAuthentication>; | ||
export declare function generateEphPrivateKey(): Uint8Array; | ||
export declare function getEphPublicKey(ephSK: Uint8Array): Uint8Array; |
@@ -1,1 +0,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}); | ||
"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,8 +0,9 @@ | ||
export type { SignResponse, KeygenResponse } from './networkSigner'; | ||
export type { SignResponse, KeygenResponse, AddEphemeralKeyResponse } from './networkSigner'; | ||
export type { IBrowserWallet, TypedData } from './EOAauthentication'; | ||
export type { ClientConfig, IWalletProviderServiceClient } from './walletProviderServiceClientInterface'; | ||
export type { PasskeyUser, RelyingPartyConfig } from './passkeyAuthentication'; | ||
export { WalletProviderServiceClient } from './walletProviderServiceClient'; | ||
export { NetworkSigner } from './networkSigner'; | ||
export { EOAAuth, EphAuth, PasskeyAuth } from './authentication'; | ||
export { WalletProviderServiceClient } from './walletProviderServiceClient'; | ||
export { computeAddress } from './viemSigner'; | ||
export { generateEphPrivateKey, getEphPublicKey } from './ephemeralAuthentication'; |
@@ -1,1 +0,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}; | ||
var $=Object.defineProperty,F=Object.defineProperties;var V=Object.getOwnPropertyDescriptors;var O=Object.getOwnPropertySymbols;var H=Object.prototype.hasOwnProperty,L=Object.prototype.propertyIsEnumerable;var w=(n,e,t)=>e in n?$(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t,y=(n,e)=>{for(var t in e||(e={}))H.call(e,t)&&w(n,t,e[t]);if(O)for(var t of O(e))L.call(e,t)&&w(n,t,e[t]);return n},A=(n,e)=>F(n,V(e));var s=(n,e,t)=>w(n,typeof e!="symbol"?e+"":e,t);import{Base64 as Q}from"js-base64";var k=n=>btoa(String.fromCodePoint.apply(null,Array.from(n))),c=n=>Q.fromUint8Array(new Uint8Array(n),!0);var h=(n,e)=>{u(typeof e!="string","".concat(n," must be string")),u((e==null?void 0:e.trim().length)===0,"".concat(n," cannot be empty"))},S=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 C=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=k(new TextEncoder().encode(e.message)));let p=new WebSocket("".concat(this.walletProviderUrl,"/").concat(o));p.addEventListener("open",l=>{switch(console.debug("Connection opened in state ".concat(a," with event ").concat(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 ".concat(a," with event ").concat(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 ".concat(a," with event ").concat(JSON.stringify(l,void 0," "))),a!=3&&(a=3,i("Incorrect protocol state"))}),p.addEventListener("close",l=>{console.debug("Connection closed in state ".concat(a," with event ").concat(JSON.stringify(l,void 0," "))),a!=3&&(a=3,i("Incorrect protocol state"))})})}};var G=1,x=2,z=3,U=[{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:G,value:i})}set ephClaim(e){this.metadata.push({tag:x,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:U}}},P=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:z,value:t})}set ephClaim(e){this.metadata.push({tag:x,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:U}}},I=class{constructor(e,t,r,i){s(this,"authModule");s(this,"threshold");s(this,"totalNodes");s(this,"wp_client");u(t<2,"Threshold = ".concat(t," must be at least 2")),u(r<t,"Total nodes = ".concat(r," must be greater or equal to threshold = ").concat(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 P({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 Y={name:"SilentShard authentication",version:"0.1.0"},X=[{name:"name",type:"string"},{name:"version",type:"string"}];function Z(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:y({EIP712Domain:X},n.requestSchema),domain:Y,primaryType:"Request",message:{setup:r,challenge:e}}}async function R({setup:n,eoa:e,challenge:t,browserWallet:r,ephClaim:i}){let a=Z(n,t,i),o=await r.signTypedData(e,a);return{credentials:{credentials:i.toJSON(),method:"eoa",id:e},signature:o}}import{ed25519 as te}from"@noble/curves/ed25519";import{Base64 as T}from"js-base64";import{hexToBytes as M}from"viem";async function N({user:n,challenge:e,rpConfig:t,ephClaim:r}){let i=M("0x".concat(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:A(y({},n),{id:T.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 D({challenge:n,allowCredentialId:e,rpConfig:t,ephClaim:r}){let i=M("0x".concat(n),{size:32}),a=e?[{type:"public-key",id:T.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 B=c(l.signature),W={rawCredential:JSON.stringify({authenticatorAttachment:p.authenticatorAttachment,id:p.id,rawId:c(p.rawId),response:{authenticatorData:c(l.authenticatorData),clientDataJSON:c(l.clientDataJSON),signature:B,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(W)}}import{toHex as J}from"viem";import{ed25519 as E}from"@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=J(t),this.expiry=Math.floor(Date.now()/1e3)+r}validateInputs(e,t,r){h("ephId",e),S(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=J(E.sign(a.encode(JSON.stringify(i)),t));return{credentials:{credentials:r.toJSON(),method:"ephemeral",id:r.ephId},signature:o}}function j(){return E.utils.randomPrivateKey()}function ee(n){return E.getPublicKey(n)}import{isAddress as ne}from"viem";var K=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(!ne(e),"invalid Ethereum address format"),u(!((t==null?void 0:t.signTypedData)instanceof Function),"invalid browserWallet")}async authenticate({setup:e,challenge:t}){return await R({setup:e,eoa:this.eoa,challenge:t,browserWallet:this.browserWallet,ephClaim:this.ephClaim})}},v=class{constructor(e,t){s(this,"ephSK");s(this,"ephClaim");S(t),this.ephSK=t;let r=te.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})}},b=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 D({allowCredentialId:this.allowCredentialId,challenge:t,rpConfig:this.rpConfig,ephClaim:this.ephClaim});if(this.user)return await N({user:this.user,challenge:t,rpConfig:this.rpConfig,ephClaim:this.ephClaim});throw new Error("Invalid arguments for passkey authentication")}};import{publicKeyToAddress as q,toAccount as Ve}from"viem/accounts";import{secp256k1 as re}from"@noble/curves/secp256k1";import{hashMessage as ze,hashTypedData as Ye,keccak256 as Xe,serializeSignature as Ze,serializeTransaction as je,toHex as tt}from"viem";function ie(n){if(n.startsWith("0x")&&(n=n.slice(2)),n.startsWith("04"))return q("0x".concat(n," "));if(n.startsWith("02")||n.startsWith("03")){let e=re.ProjectivePoint.fromHex(n).toHex(!1);return q("0x".concat(e))}else throw new Error("Invalid public key")}export{K as EOAAuth,v as EphAuth,I as NetworkSigner,b as PasskeyAuth,C as WalletProviderServiceClient,ie as computeAddress,j as generateEphPrivateKey,ee as getEphPublicKey}; |
import { AuthModule, UserAuthentication } from './authentication'; | ||
import { type IWalletProviderServiceClient } from './walletProviderServiceClientInterface'; | ||
import { GetQueryPath, QueryPath, type IWalletProviderServiceClient } from './walletProviderServiceClientInterface'; | ||
import { EphClaim } from './ephemeralAuthentication'; | ||
/** | ||
@@ -23,3 +24,5 @@ * Response from the network for keygen requests | ||
/** | ||
* Optional credential id used for passkey authentication | ||
* Optional credential id used for passkey authentication. | ||
* | ||
* Returned by Authenticator. | ||
*/ | ||
@@ -42,4 +45,11 @@ passkeyCredentialId?: string; | ||
} | ||
/** | ||
* Response from the network for adding ephemeral key request | ||
* @alpha | ||
*/ | ||
export interface AddEphemeralKeyResponse { | ||
status: string; | ||
} | ||
/** Key parameters used during generation */ | ||
export declare class KeygenSetupOpts { | ||
export declare class KeygenSetupOpts implements GetQueryPath { | ||
/** Threshold, number of parties that needs to participate in a protocol in order to produce valid signature */ | ||
@@ -54,17 +64,29 @@ t: number; | ||
*/ | ||
metadata: { | ||
tag: number; | ||
value: string; | ||
}[]; | ||
constructor({ t, n, ephPK, key_label, permissions, }: { | ||
private metadata; | ||
constructor({ t, n, key_label, permissions, }: { | ||
t: number; | ||
n: number; | ||
ephPK: string; | ||
key_label?: string; | ||
permissions?: string; | ||
key_label: string | undefined; | ||
permissions: string | undefined; | ||
}); | ||
set ephClaim(ephClaim: EphClaim); | ||
get queryPath(): QueryPath; | ||
get requestSchema(): { | ||
Request: { | ||
name: string; | ||
type: string; | ||
}[]; | ||
KeygenSetupOpts: { | ||
name: string; | ||
type: string; | ||
}[]; | ||
TaggedValue: { | ||
name: string; | ||
type: string; | ||
}[]; | ||
}; | ||
} | ||
/** Parameters used in Signature execution */ | ||
export type SignSetupOpts = { | ||
/** Nymber of nodes that will participate in the signature execution */ | ||
export declare class SignSetupOpts implements GetQueryPath { | ||
/** Number of nodes that will participate in the signature execution */ | ||
t: number; | ||
@@ -75,5 +97,39 @@ /** Select the key using it's ID */ | ||
message: string; | ||
}; | ||
/** Verifies if passed `params` object is of type SignSetupOpts */ | ||
export declare function isSignSetupOpts(params: KeygenSetupOpts | SignSetupOpts): params is SignSetupOpts; | ||
constructor({ t, key_id, message }: { | ||
t: number; | ||
key_id: string; | ||
message: string; | ||
}); | ||
get queryPath(): QueryPath; | ||
} | ||
export declare class AddEphemeralKeyOpts implements GetQueryPath { | ||
/** Total number of nodes that participate in Adding Ephemeral Key */ | ||
n: number; | ||
/** Select the key using it's ID */ | ||
key_id: string; | ||
/** Metadata for a key. Currently they store the permissions, can be set in a constructor of this class. | ||
If permissions are not set, all operations are allowed. | ||
*/ | ||
private metadata; | ||
constructor({ n, key_id }: { | ||
n: number; | ||
key_id: string; | ||
}); | ||
set ephClaim(ephClaim: EphClaim); | ||
get queryPath(): QueryPath; | ||
get requestSchema(): { | ||
Request: { | ||
name: string; | ||
type: string; | ||
}[]; | ||
AddEphemeralKeyOpts: { | ||
name: string; | ||
type: string; | ||
}[]; | ||
TaggedValue: { | ||
name: string; | ||
type: string; | ||
}[]; | ||
}; | ||
} | ||
/** The `user_authentication` contains signature over the `setup` parameter. */ | ||
@@ -105,5 +161,4 @@ export type UserAuthenticatedRequest<T> = { | ||
constructor(wpClient: IWalletProviderServiceClient, threshold: number, totalNodes: number, authModule: AuthModule); | ||
/** API to generate a distributed key that's generated by Silent Network. | ||
* Uses `authModule` to get authentication of the request from the User | ||
* @param ephKey - ephemeral key used to authenticate the user during the session. | ||
/** Generate a distributed key that's generated by Silent Network. | ||
* Uses `authModule` to authenticate the User with the Silent Network. | ||
* @param permissions - optional permissions that will be stored in the key metadata. | ||
@@ -114,6 +169,7 @@ * The permissions are validated during sign requests. | ||
*/ | ||
authenticateAndCreateKey(ephKey: Uint8Array, permissions?: string): Promise<KeygenResponse>; | ||
/** Generate a signature. Uses `authModule` to authenticate the sign request by the User. | ||
generateKey(permissions?: string): Promise<KeygenResponse>; | ||
/** Generate a signature by the distributed key of Silent Network. | ||
* Uses `authModule` to authenticate the sign request by the User. | ||
* The network chooses `t` nodes to execute the protocol. | ||
* @param keyId - the key id returned from `authenticateAndCreateKey` | ||
* @param keyId - the key id returned from `keygen` | ||
* @param message - the message to sign by the MPC network | ||
@@ -123,3 +179,11 @@ * @returns {@link SignResponse} | ||
*/ | ||
authenticateAndSign(keyId: string, message: string): Promise<SignResponse>; | ||
signMessage(keyId: string, message: string): Promise<SignResponse>; | ||
/** Add new ephemeral key to an exist distributed key on the network. | ||
* Uses `authModule` to authenticate the request by the User. | ||
* @param keyId - the key id returned from `keygen` | ||
* @returns {@link AddEphemeralKeyResponse} | ||
* @public | ||
*/ | ||
addEphemeralKey(keyId: string): Promise<AddEphemeralKeyResponse>; | ||
private setEphClaimOf; | ||
} |
import { UserAuthentication } from './authentication'; | ||
import { EphClaim } from './ephemeralAuthentication'; | ||
/** Information about the user currently registering. Read more: https://w3c.github.io/webauthn/#dom-publickeycredentialcreationoptions-user | ||
@@ -17,17 +18,13 @@ * @alpha | ||
}; | ||
export declare function passkeyRegister({ user, ephId, challenge, rpConfig, ephPK, lifetime, }: { | ||
export declare function passkeyRegister({ user, challenge, rpConfig, ephClaim, }: { | ||
user: PasskeyUser; | ||
ephId: string; | ||
challenge: string; | ||
rpConfig: RelyingPartyConfig; | ||
ephPK: Uint8Array; | ||
lifetime: number; | ||
ephClaim: EphClaim; | ||
}): Promise<UserAuthentication>; | ||
export declare function passkeyLogin({ ephId, challenge, credentialId, rpConfig, ephPK, lifetime, }: { | ||
ephId: string; | ||
export declare function passkeyLogin({ challenge, allowCredentialId, rpConfig, ephClaim, }: { | ||
challenge: string; | ||
credentialId: string; | ||
allowCredentialId: string | null; | ||
rpConfig: RelyingPartyConfig; | ||
ephPK: Uint8Array; | ||
lifetime: number; | ||
ephClaim: EphClaim; | ||
}): Promise<UserAuthentication>; |
@@ -1,3 +0,4 @@ | ||
import * as viem from 'viem'; | ||
import { LocalAccount } from 'viem/accounts'; | ||
import { NetworkSigner } from './networkSigner'; | ||
import { Address } from 'viem'; | ||
/** | ||
@@ -11,6 +12,6 @@ * Create a new viem custom account for signing transactions using | ||
*/ | ||
export declare function createViemAccount(networkSigner: NetworkSigner, keyId: string, publicKey: string): viem.LocalAccount; | ||
export declare function createViemAccount(networkSigner: NetworkSigner, keyId: string, publicKey: string): LocalAccount; | ||
/** Computes ETH address from ECDSA `publicKey` returned by Silent Network | ||
* @public | ||
*/ | ||
export declare function computeAddress(publicKey: string): viem.Address; | ||
export declare function computeAddress(publicKey: string): Address; |
@@ -1,3 +0,4 @@ | ||
import { type KeygenSetupOpts, type KeygenResponse, type SignSetupOpts, type SignResponse } from './networkSigner'; | ||
import { type ClientConfig, IWalletProviderServiceClient, type Signer } from './walletProviderServiceClientInterface'; | ||
import { AuthModule } from './authentication'; | ||
import { type KeygenSetupOpts, type KeygenResponse, type SignSetupOpts, type SignResponse, AddEphemeralKeyOpts, AddEphemeralKeyResponse } from './networkSigner'; | ||
import { type ClientConfig, IWalletProviderServiceClient } from './walletProviderServiceClientInterface'; | ||
/** | ||
@@ -18,11 +19,15 @@ * The Websocket client to the Wallet Provider backend service. | ||
getWalletId(): string; | ||
startKeygen({ setup, signer }: { | ||
startKeygen({ setup, authModule, }: { | ||
setup: KeygenSetupOpts; | ||
signer: Signer; | ||
authModule: AuthModule; | ||
}): Promise<KeygenResponse>; | ||
startSigngen({ setup, signer }: { | ||
startSigngen({ setup, authModule }: { | ||
setup: SignSetupOpts; | ||
signer: Signer; | ||
authModule: AuthModule; | ||
}): Promise<SignResponse>; | ||
connect(setupOpts: KeygenSetupOpts | SignSetupOpts, signer: Signer): Promise<string>; | ||
addEphemeralKey({ setup, authModule, }: { | ||
setup: AddEphemeralKeyOpts; | ||
authModule: AuthModule; | ||
}): Promise<AddEphemeralKeyResponse>; | ||
connect(setupOpts: KeygenSetupOpts | SignSetupOpts | AddEphemeralKeyOpts, authModule: AuthModule): Promise<string>; | ||
} |
@@ -1,3 +0,3 @@ | ||
import { UserAuthentication } from './authentication'; | ||
import { KeygenResponse, KeygenSetupOpts, SignResponse, SignSetupOpts } from './networkSigner'; | ||
import { AuthModule, UserAuthentication } from './authentication'; | ||
import { AddEphemeralKeyOpts, KeygenResponse, KeygenSetupOpts, SignResponse, SignSetupOpts, AddEphemeralKeyResponse } from './networkSigner'; | ||
/** | ||
@@ -27,10 +27,18 @@ * The config used to create Wallet Provider Service backend client. | ||
getWalletId(): string; | ||
startKeygen({ setup, signer }: { | ||
startKeygen({ setup, authModule }: { | ||
setup: KeygenSetupOpts; | ||
signer: Signer; | ||
authModule: AuthModule; | ||
}): Promise<KeygenResponse>; | ||
startSigngen({ setup, signer }: { | ||
startSigngen({ setup, authModule }: { | ||
setup: SignSetupOpts; | ||
signer: Signer; | ||
authModule: AuthModule; | ||
}): Promise<SignResponse>; | ||
addEphemeralKey({ setup, authModule, }: { | ||
setup: AddEphemeralKeyOpts; | ||
authModule: AuthModule; | ||
}): Promise<AddEphemeralKeyResponse>; | ||
} | ||
export type QueryPath = 'signgen' | 'keygen' | 'addEphemeralKey'; | ||
export interface GetQueryPath { | ||
get queryPath(): QueryPath; | ||
} |
{ | ||
"name": "@silencelaboratories/walletprovider-sdk", | ||
"version": "0.2.0", | ||
"version": "0.3.0", | ||
"author": "Silence Laboratories", | ||
@@ -24,3 +24,3 @@ "description": "Frontend SDK for Wallet Providers", | ||
"typecheck": "tsc -p . --noEmit", | ||
"build": "npm run clean && node build.js && npm run build:declaration", | ||
"build": "node build.js && npm run build:declaration", | ||
"build:declaration": "tsc -p . --emitDeclarationOnly", | ||
@@ -35,5 +35,7 @@ "clean": "rimraf dist", | ||
"@microsoft/api-extractor": "^7.46.2", | ||
"esbuild": "^0.23.0", | ||
"esbuild-node-externals": "^1.14.0", | ||
"@types/eslint-plugin-security": "^3.0.0", | ||
"esbuild": "0.24.0", | ||
"esbuild-node-externals": "^1.15.0", | ||
"eslint": "^8.x", | ||
"eslint-plugin-security": "^3.0.1", | ||
"globals": "^15.3.0", | ||
@@ -43,10 +45,10 @@ "npm-dts": "^1.3.13", | ||
"rimraf": "^6.0.1", | ||
"typescript": "^5.4.5", | ||
"typescript": "5.6.3", | ||
"typescript-eslint": "^7.11.0" | ||
}, | ||
"dependencies": { | ||
"@noble/curves": "^1.4.2", | ||
"@noble/curves": "^1.6.0", | ||
"js-base64": "^3.7.7", | ||
"viem": "^2.11.1" | ||
"viem": "2.21.32" | ||
} | ||
} |
@@ -79,6 +79,5 @@ # walletprovider-sdk | ||
// Generate ephemeral secret key esk | ||
const sk = ed.utils.randomPrivateKey(); | ||
ephSK = sk; | ||
const sk = generateEphPrivateKey(); | ||
// Derive public part epk from esk | ||
ephPK = await ed.getPublicKeyAsync(sk); | ||
const ephPK = getEphPublicKey(sk); | ||
// Arbitrary ID to identify the ephemeral key | ||
@@ -103,3 +102,3 @@ const ephId = uuidv4(); | ||
Now you can generate a key, using the [authenticateAndCreateKey](./docs/walletprovider-sdk.networksigner.authenticateandcreatekey.md) method. The method accepts optional permissions. No permissions means _allow all operations_. | ||
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_. | ||
@@ -123,3 +122,3 @@ ```ts | ||
// Generate a new key | ||
let resp: KeygenResponse = await sdk.authenticateAndCreateKey(JSON.stringify(permissions)); | ||
let resp: KeygenResponse = await sdk.generateKey(JSON.stringify(permissions)); | ||
``` | ||
@@ -138,6 +137,5 @@ | ||
// Generate ephemeral secret key esk | ||
const sk = ed.utils.randomPrivateKey(); | ||
ephSK = sk; | ||
const sk = generateEphPrivateKey(); | ||
// Derive public part epk from esk | ||
ephPK = await ed.getPublicKeyAsync(sk); | ||
const ephPK = getEphPublicKey(sk); | ||
// Arbitrary ID to identify the ephemeral key | ||
@@ -177,3 +175,3 @@ const ephId = uuidv4(); | ||
Now you can generate a key like in the EOA example by calling the [authenticateAndCreateKey](./docs/walletprovider-sdk.networksigner.authenticateandcreatekey.md) method. | ||
Now you can generate a key like in the EOA example by calling the [generateKey](./docs/walletprovider-sdk.networksigner.authenticateandcreatekey.md) method. | ||
@@ -196,3 +194,3 @@ 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. | ||
Use the [NetworkSigner.authenticateAndSign](./docs/walletprovider-sdk.networksigner.authenticateandsign.md) method in order to generate a signature. | ||
Use the [NetworkSigner.signMessage](./docs/walletprovider-sdk.networksigner.authenticateandsign.md) method in order to generate a signature. | ||
@@ -221,3 +219,3 @@ ```ts | ||
let resp = await sdk.authenticateAndSign(selectedKeyId, signMessage); | ||
let resp = await sdk.signMessage(selectedKeyId, signMessage); | ||
``` | ||
@@ -224,0 +222,0 @@ |
139323
16
590
14
246
+ Addedviem@2.21.32(transitive)
- Removedeventemitter3@5.0.1(transitive)
- Removedox@0.1.2(transitive)
- Removedviem@2.21.48(transitive)
Updated@noble/curves@^1.6.0
Updatedviem@2.21.32