UNPKG

@privy-io/server-auth

Version:

Server-side client for the Privy API

2 lines (1 loc) 11.9 kB
import*as t from"jose";import{Webhook as e}from"svix";import{objectToCamel as a,objectToSnake as r}from"ts-case-convert";import{normalizePhoneNumber as s}from"@privy-io/public-api";import{PRIVY_API_URL as i,DEFAULT_TIMEOUT_MS as o,PRIVY_WALLET_API_URL as l}from"./constants.mjs";import{formatPrivyError as n,PrivyApiError as u,PrivyClientError as c}from"./errors.mjs";import{Http as p}from"./http.mjs";import{userPath as d,getUserByEmailPath as h,getUserByPhoneNumberPath as m,getUserByWalletAddressPath as y,getUserBySmartWalletAddressPath as w,getUserByFarcasterIdPath as f,getUserByDiscordUsernamePath as _,getUserByGithubUsernamePath as g,getUserByTwitterUsernamePath as A,getUserByTwitterSubjectPath as b,getUserByTelegramUserIdPath as v,getUserByTelegramUsernamePath as j,getUserByCustomAuthIdPath as k,usersPath as U,searchUsersPath as I,importUserPath as T,createWalletsPath as V,appSettingsPath as W,allowlistPath as B,getTestCredentialsPath as E,passwordlessAuthenticatePath as S,setCustomMetadataPath as x}from"./paths.mjs";import{c as K,p as O,a as C,b as P,f as L}from"./utils-DDjlFg8J.mjs";import{WalletApi as F}from"./wallet-api/index.mjs";import"redaxios";import"node-fetch-native";import"./wallet-api/import.mjs";import"@scure/base";import"viem";import"./wallet-api/utils.mjs";import"@hpke/chacha20poly1305";import"@hpke/core";import"@noble/curves/p256";import"@noble/hashes/sha256";import"canonicalize";import"./wallet-api/mappers.mjs";import"./wallet-api/rpc/ethereum.mjs";import"./wallet-api/rpc/solana.mjs";import"./wallet-api/views.mjs";class D{async getUser(t){return"string"==typeof t?this.getUserById(t):this.getUserFromIdToken(t.idToken)}async getUserById(t){try{let e=d(t),a=await this.api.get(e);return K(a.data)}catch(t){throw n(t)}}async getUserByEmail(t){try{let e=h(),a=await this.api.post(e,{address:t});return K(a.data)}catch(t){if(t instanceof u&&404===t.status)return null;throw n(t)}}async getUserByPhoneNumber(t){try{let e=m(),a=await this.api.post(e,{number:t});return K(a.data)}catch(t){if(t instanceof u&&404===t.status)return null;throw n(t)}}async getUserByWalletAddress(t){try{let e=y(),a=await this.api.post(e,{address:t});return K(a.data)}catch(t){if(t instanceof u&&404===t.status)return null;throw n(t)}}async getUserBySmartWalletAddress(t){try{let e=w(),a=await this.api.post(e,{address:t});return K(a.data)}catch(t){if(t instanceof u&&404===t.status)return null;throw n(t)}}async getUserByFarcasterId(t){try{let e=f(),a=await this.api.post(e,{fid:t});return K(a.data)}catch(t){if(t instanceof u&&404===t.status)return null;throw n(t)}}async getUserByDiscordUsername(t){try{let e=_(),a=await this.api.post(e,{username:t});return K(a.data)}catch(t){if(t instanceof u&&404===t.status)return null;throw n(t)}}async getUserByGithubUsername(t){try{let e=g(),a=await this.api.post(e,{username:t});return K(a.data)}catch(t){if(t instanceof u&&404===t.status)return null;throw n(t)}}async getUserByTwitterUsername(t){try{let e=A(),a=await this.api.post(e,{username:t});return K(a.data)}catch(t){if(t instanceof u&&404===t.status)return null;throw n(t)}}async getUserByTwitterSubject(t){try{let e=b(),a=await this.api.post(e,{subject:t});return K(a.data)}catch(t){if(t instanceof u&&404===t.status)return null;throw n(t)}}async getUserByTelegramUserId(t){try{let e=v(),a=await this.api.post(e,{telegram_user_id:t});return K(a.data)}catch(t){if(t instanceof u&&404===t.status)return null;throw n(t)}}async getUserByTelegramUsername(t){try{let e=j(),a=await this.api.post(e,{username:t});return K(a.data)}catch(t){if(t instanceof u&&404===t.status)return null;throw n(t)}}async getUserByCustomAuthId(t){try{let e=k(),a=await this.api.post(e,{custom_user_id:t});return K(a.data)}catch(t){if(t instanceof u&&404===t.status)return null;throw n(t)}}async getUsers(t){try{let e=[],a="string"==typeof t?{searchTerm:t}:{...t},r="",s=0;do{try{let i=void 0===t?await this.api.get(U({cursor:r})):await this.api.post(I(),{...a,...r?{cursor:r}:{}});if(429===i.status){let t=1e3*Math.pow(2,s);await new Promise((e=>setTimeout(e,t))),s++;continue}e.push(...i.data.data.map((t=>K(t)))),r=i.data.next_cursor,s=0}catch(t){if(s>=9)throw n(`Exceeded max attempts (9) with error: ${t}`);let e=1e3*Math.pow(2,s);await new Promise((t=>setTimeout(t,e))),s++}}while(null!==r);return e}catch(t){throw n(t)}}async deleteUser(t){try{let e=d(t);await this.api.delete(e)}catch(t){throw n(t)}}async importUser({linkedAccounts:t,createEthereumWallet:e,createSolanaWallet:a,createEthereumSmartWallet:r,customMetadata:s,createEmbeddedWallet:i,wallets:o}){let l=O(t);try{let t=T(),n=await this.api.post(t,{create_ethereum_wallet:e||i,create_solana_wallet:a,create_ethereum_smart_wallet:r,linked_accounts:l,custom_metadata:s,wallets:C(o)}),u=K(n.data);if(!u)throw Error("Failed to convert user response to user object");return u}catch(t){throw n(t)}}async createWallets({userId:t,createEthereumWallet:e,createSolanaWallet:a,createEthereumSmartWallet:r,numberOfEthereumWalletsToCreate:s,wallets:i}){try{let o=V(this.appId),l=await this.api.post(o,{user_id:t,create_ethereum_wallet:e,create_solana_wallet:a,create_ethereum_smart_wallet:r,number_of_ethereum_wallets_to_create:s,wallets:C(i)});return K(l.data)}catch(t){throw n(t)}}async getAppSettings(){try{let t=W(this.appId),e=await this.api.get(t);return{id:e.data.id,name:e.data.name,verificationKey:e.data.verification_key,logoUrl:e.data.logo_url||void 0,theme:e.data.theme,accentColor:e.data.accent_color||void 0,walletAuth:e.data.wallet_auth,emailAuth:e.data.email_auth,smsAuth:e.data.sms_auth,googleOAuth:e.data.google_oauth,twitterOAuth:e.data.twitter_oauth,discordOAuth:e.data.discord_oauth,githubOAuth:e.data.github_oauth,appleOAuth:e.data.apple_oauth,linkedInOAuth:e.data.linkedin_oauth,tiktokOAuth:e.data.tiktok_oauth,disablePlusEmails:e.data.disable_plus_emails,termsAndConditionsUrl:e.data.terms_and_conditions_url,privacyPolicyUrl:e.data.privacy_policy_url,allowlistEnabled:e.data.allowlist_enabled,allowlistConfig:{errorTitle:e.data.allowlist_config.error_title,errorDetail:e.data.allowlist_config.error_detail,ctaText:e.data.allowlist_config.cta_text,ctaLink:e.data.allowlist_config.cta_link},createdAt:new Date(1e3*e.data.created_at),updatedAt:new Date(1e3*e.data.updated_at)}}catch(t){throw n(t)}}async getAllowlist(){try{let t=B(this.appId);return(await this.api.get(t)).data.map((t=>a(t)))}catch(t){throw n(t)}}async inviteToAllowlist(t){let e=r(t);try{let t=B(this.appId),r=await this.api.post(t,e);return a(r.data)}catch(t){throw n(t)}}async removeFromAllowlist(t){let e=r(t);try{let t=B(this.appId),r=await this.api.delete(t,e);return a(r.data)}catch(t){throw n(t)}}async verifyAuthToken(e,a=""){let r=e.replace(/^Bearer /,""),s="ES256",i=a||await this.getVerificationKey(),o=await t.importSPKI(i,s),l=await t.jwtVerify(r,o,{typ:"JWT",algorithms:[s],issuer:"privy.io",audience:this.appId});return{appId:l.payload.aud,issuer:l.payload.iss,issuedAt:l.payload.iat,expiration:l.payload.exp,sessionId:l.payload.sid,userId:l.payload.sub}}async getVerificationKey(){if(this.verificationKey)return this.verificationKey;let t=await this.getAppSettings();return this.verificationKey=t.verificationKey,this.verificationKey}async verifyWebhook(t,a,r){try{let s=new e(r),i=JSON.stringify(t),o={"svix-id":a.id,"svix-timestamp":a.timestamp,"svix-signature":a.signature};return s.verify(i,o)}catch(t){throw console.error("Webhook verification failed with error: ",t),new c("Webhook verification failed")}}async getTestAccessToken(t={}){try{let e,a=await this.api.get(E(this.appId));if(!a.data?.data)throw new c("Test credentials not enabled for this app");let{email:r,phoneNumber:i}=t,o=a.data.data,l=r?.trim().toLowerCase(),n=i?s(i):void 0;if(l||n){if(l&&!n)e=o.find((t=>t.email.toLowerCase()===l));else if(!l&&n)e=o.find((t=>t.phone_number===n));else if(l&&n&&!(e=o.find((t=>t.email.toLowerCase()===l&&t.phone_number===n))))throw new c("Email and phone number do not correspond to the same test account")}else e=o[0];if(!e)throw new c("Test account not found");let{email:u,otp_code:p}=e;return{accessToken:(await this.api.post(S(),{email:u,code:p})).data.token}}catch(t){throw n(t)}}async setCustomMetadata(t,e){try{let a=x(t),r=await this.api.post(a,{custom_metadata:e}),s=K(r.data);if(!s)throw Error("Failed to convert user response to user object");return s}catch(t){throw n(t)}}async getUserFromIdToken(e){let a=this.appId,r=await this.getVerificationKey(),s=await t.importSPKI(r,"ES256");try{let{payload:r}=await t.jwtVerify(e,s,{issuer:"privy.io",audience:a});if(!r)throw new c("Unable to parse ID token");let i=JSON.parse(r.linked_accounts),o=[];for(let t of i){if("email"===t.type&&o.push({type:"email",address:t.address,latestVerifiedAt:P(t.lv)}),"phone"===t.type&&o.push({type:"phone",number:t.phone_number,latestVerifiedAt:P(t.lv)}),"wallet"===t.type&&o.push({type:"wallet",id:t.id,address:t.address,chainType:t.chain_type,walletClientType:t.wallet_client_type,latestVerifiedAt:P(t.lv)}),"smart_wallet"===t.type&&o.push({type:"smart_wallet",address:t.address,smartWalletType:t.smart_wallet_type,latestVerifiedAt:P(t.lv)}),"farcaster"===t.type&&o.push({type:"farcaster",fid:t.fid,username:t.username,latestVerifiedAt:P(t.lv),ownerAddress:t.oa}),"google_oauth"===t.type&&o.push({type:"google_oauth",subject:t.subject,email:t.email,name:t.name,latestVerifiedAt:P(t.lv)}),"twitter_oauth"===t.type){let e=t.pfp?t.pfp:null;e?.startsWith("default")?e=`https://abs.twimg.com/sticky/default_profile_images/${e}`:e?.startsWith("https://")||(e=`https://pbs.twimg.com/profile_images/${e}`),o.push({type:"twitter_oauth",subject:t.subject,username:t.username,name:t.name?t.name:null,profilePictureUrl:e,latestVerifiedAt:P(t.lv)})}"discord_oauth"===t.type&&o.push({type:"discord_oauth",subject:t.subject,username:t.username,latestVerifiedAt:P(t.lv)}),"github_oauth"===t.type&&o.push({type:"github_oauth",subject:t.subject,username:t.username,latestVerifiedAt:P(t.lv)}),"spotify_oauth"===t.type&&o.push({type:"spotify_oauth",subject:t.subject,latestVerifiedAt:P(t.lv)}),"instagram_oauth"===t.type&&o.push({type:"instagram_oauth",subject:t.subject,username:t.username,latestVerifiedAt:P(t.lv)}),"tiktok_oauth"===t.type&&o.push({type:"tiktok_oauth",subject:t.subject,username:t.username?t.username:void 0,latestVerifiedAt:P(t.lv)}),"linkedin_oauth"===t.type&&o.push({type:"linkedin_oauth",subject:t.subject,email:t.email,latestVerifiedAt:P(t.lv)}),"apple_oauth"===t.type&&o.push({type:"apple_oauth",subject:t.subject,email:t.email,latestVerifiedAt:P(t.lv)}),"cross_app"===t.type&&o.push({type:"cross_app",subject:t.subject,providerApp:{id:t.provider_app_id},embeddedWallets:t.embedded_wallets,smartWallets:t.smart_wallets,latestVerifiedAt:P(t.lv)}),"custom_auth"===t.type&&o.push({type:"custom_auth",customUserId:t.custom_user_id,latestVerifiedAt:P(t.lv)}),"telegram"===t.type&&o.push({type:"telegram",telegramUserId:t.telegram_user_id,username:t.username,latestVerifiedAt:P(t.lv)})}let l=r.custom_metadata?JSON.parse(r.custom_metadata):void 0,{walletAccount:n,smartWalletAccount:u,emailAccount:p,phoneAccount:d,googleAccount:h,twitterAccount:m,discordAccount:y,githubAccount:w,appleAccount:f,linkedInAccount:_,tiktokAccount:g,spotifyAccount:A,instagramAccount:b,customJwtAccount:v,farcasterAccount:j,telegramAccount:k}=L(o);return{id:r.sub,createdAt:P(parseInt(r.cr)),isGuest:"t"===r.guest,linkedAccounts:o,customMetadata:l,email:p,phone:d,wallet:n,smartWallet:u,google:h,twitter:m,discord:y,github:w,apple:f,linkedin:_,tiktok:g,spotify:A,instagram:b,custom:v,farcaster:j,telegram:k}}catch(t){throw n(t)}}constructor(t,e,a={}){this.verificationKey=null;let r=a.apiURL||i,s=a.timeout||o;this.appId=t,this.api=new p(t,e,{baseURL:r,timeout:s});let n=a.walletApi?.apiURL||l;this.walletApi=new F({api:new p(t,e,{baseURL:n,timeout:s}),authorizationPrivateKey:a.walletApi?.authorizationPrivateKey,appId:t})}}export{D as PrivyClient};