@walletconnect/sign-client
Version:
Sign Client for WalletConnect Protocol
1 lines • 66.1 kB
JavaScript
import wt,{EventEmitter as _t}from"events";import{RELAYER_DEFAULT_PROTOCOL as ft,EVENT_CLIENT_SESSION_TRACES as x,EVENT_CLIENT_SESSION_ERRORS as H,TRANSPORT_TYPES as R,EVENT_CLIENT_AUTHENTICATE_TRACES as Q,EVENT_CLIENT_AUTHENTICATE_ERRORS as ce,EVENT_CLIENT_PAIRING_ERRORS as St,EVENT_CLIENT_PAIRING_TRACES as Et,VERIFY_SERVER as Rt,RELAYER_EVENTS as It,EXPIRER_EVENTS as qt,PAIRING_EVENTS as Le,Store as Z,Core as Tt}from"@walletconnect/core";import{IEngine as vt,ISignClient as Pt}from"@walletconnect/types";import{LimitedSet as Nt,mergeRequiredAndOptionalNamespaces as Ot,getInternalError as d,calcExpiry as P,engineEvent as f,createDelayedPromise as ee,getSdkError as b,getDeepLink as At,handleDeeplinkRedirect as xt,isSessionCompatible as bt,hashKey as Te,parseChainId as ve,createEncodedRecap as Ct,getRecapFromResources as Pe,mergeEncodedRecaps as Vt,BASE64URL as pe,TYPE_2 as kt,getLinkModeURL as me,validateSignedCacao as Me,TYPE_1 as Ne,getNamespacedDidChainId as $e,getDidAddress as Ke,getMethodsFromRecap as Ue,getChainsFromRecap as Ge,buildNamespacesFromAuth as Fe,formatMessage as Dt,BASE64 as z,hashMessage as L,isExpired as te,MemoryStore as le,isValidParams as C,isUndefined as Y,isValidRelays as Lt,isValidObject as je,isValidRequiredNamespaces as Mt,isValidNamespaces as Oe,isConformingNamespaces as He,isValidString as J,isValidErrorReason as $t,isValidRelay as Kt,isValidController as Ut,isValidNamespacesChainId as Qe,isValidRequest as Gt,isValidNamespacesRequest as Ft,isValidResponse as jt,isValidEvent as Ht,isValidNamespacesEvent as Qt,getSearchParamFromURL as ze,isTestRun as zt,isReactNative as Yt,getNamespacesChains as Jt,getNamespacesMethods as Xt,getNamespacesEvents as Bt,getSuiDigest as Wt,getNearTransactionIdFromSignedTransaction as Ye,buildSignedExtrinsicHash as Zt,isValidArray as Je,getAlgorandTransactionId as Xe,getSignDirectHash as es,getWalletSendCallsHashes as ts,extractSolanaTransactionId as ss,parseExpirerTarget as is,isValidId as rs,isValidRequestExpiry as ns,populateAppMetadata as os,createLogger as as}from"@walletconnect/utils";import{getLoggerContext as cs}from"@walletconnect/logger";import{THIRTY_DAYS as ps,SEVEN_DAYS as Be,FIVE_MINUTES as q,ONE_HOUR as We,ONE_DAY as M,ONE_SECOND as ls,toMiliseconds as Ze}from"@walletconnect/time";import{payloadId as $,getBigIntRpcId as we,isJsonRpcResult as K,isJsonRpcError as U,formatJsonRpcRequest as se,formatJsonRpcResult as et,formatJsonRpcError as hs,isJsonRpcRequest as ds,isJsonRpcResponse as us}from"@walletconnect/jsonrpc-utils";const Ae="wc",xe=2,be="client",_e=`${Ae}@${xe}:${be}:`,fe={name:be,logger:"error",controller:!1,relayUrl:"wss://relay.walletconnect.org"},gs={session_proposal:"session_proposal",session_update:"session_update",session_extend:"session_extend",session_ping:"session_ping",session_delete:"session_delete",session_expire:"session_expire",session_request:"session_request",session_request_sent:"session_request_sent",session_event:"session_event",proposal_expire:"proposal_expire",session_authenticate:"session_authenticate",session_request_expire:"session_request_expire",session_connect:"session_connect"},ys={database:":memory:"},Ce="WALLETCONNECT_DEEPLINK_CHOICE",ms={created:"history_created",updated:"history_updated",deleted:"history_deleted",sync:"history_sync"},ws="history",_s="0.3",tt="proposal",fs=ps,Ve="Proposal expired",st="session",X=Be,it="engine",I={wc_sessionPropose:{req:{ttl:q,prompt:!0,tag:1100},res:{ttl:q,prompt:!1,tag:1101},reject:{ttl:q,prompt:!1,tag:1120},autoReject:{ttl:q,prompt:!1,tag:1121}},wc_sessionSettle:{req:{ttl:q,prompt:!1,tag:1102},res:{ttl:q,prompt:!1,tag:1103}},wc_sessionUpdate:{req:{ttl:M,prompt:!1,tag:1104},res:{ttl:M,prompt:!1,tag:1105}},wc_sessionExtend:{req:{ttl:M,prompt:!1,tag:1106},res:{ttl:M,prompt:!1,tag:1107}},wc_sessionRequest:{req:{ttl:q*3,prompt:!0,tag:1108},res:{ttl:q*3,prompt:!1,tag:1109}},wc_sessionEvent:{req:{ttl:q,prompt:!0,tag:1110},res:{ttl:q,prompt:!1,tag:1111}},wc_sessionDelete:{req:{ttl:M,prompt:!1,tag:1112},res:{ttl:M,prompt:!1,tag:1113}},wc_sessionPing:{req:{ttl:M,prompt:!1,tag:1114},res:{ttl:M,prompt:!1,tag:1115}},wc_sessionAuthenticate:{req:{ttl:We,prompt:!0,tag:1116},res:{ttl:We,prompt:!1,tag:1117},reject:{ttl:q,prompt:!1,tag:1118},autoReject:{ttl:q,prompt:!1,tag:1119}}},Se={min:q,max:Be},V={idle:"IDLE",active:"ACTIVE"},rt={eth_sendTransaction:{key:""},eth_sendRawTransaction:{key:""},wallet_sendCalls:{key:""},solana_signTransaction:{key:"signature"},solana_signAllTransactions:{key:"transactions"},solana_signAndSendTransaction:{key:"signature"},sui_signAndExecuteTransaction:{key:"digest"},sui_signTransaction:{key:""},hedera_signAndExecuteTransaction:{key:"transactionId"},hedera_executeTransaction:{key:"transactionId"},near_signTransaction:{key:""},near_signTransactions:{key:""},tron_signTransaction:{key:"txID"},xrpl_signTransaction:{key:""},xrpl_signTransactionFor:{key:""},algo_signTxn:{key:""},sendTransfer:{key:"txid"},stacks_stxTransfer:{key:"txId"},polkadot_signTransaction:{key:""},cosmos_signDirect:{key:""}},nt="request",ot=["wc_sessionPropose","wc_sessionRequest","wc_authRequest","wc_sessionAuthenticate"],at="wc",Ss=1.5,ct="auth",pt="authKeys",lt="pairingTopics",ht="requests",he=`${at}@${1.5}:${ct}:`,de=`${he}:PUB_KEY`;class Es extends vt{constructor(a){super(a),this.name=it,this.events=new wt,this.initialized=!1,this.requestQueue={state:V.idle,queue:[]},this.sessionRequestQueue={state:V.idle,queue:[]},this.emittedSessionRequests=new Nt({limit:500}),this.requestQueueDelay=ls,this.expectedPairingMethodMap=new Map,this.recentlyDeletedMap=new Map,this.recentlyDeletedLimit=200,this.relayMessageCache=[],this.pendingSessions=new Map,this.init=async()=>{this.initialized||(await this.cleanup(),this.registerRelayerEvents(),this.registerExpirerEvents(),this.registerPairingEvents(),await this.registerLinkModeListeners(),this.client.core.pairing.register({methods:Object.keys(I)}),this.initialized=!0,setTimeout(async()=>{await this.processPendingMessageEvents(),this.sessionRequestQueue.queue=this.getPendingSessionRequests(),this.processSessionRequestQueue()},Ze(this.requestQueueDelay)))},this.connect=async t=>{this.isInitialized(),await this.confirmOnlineStateOrThrow();const e={...t,requiredNamespaces:t.requiredNamespaces||{},optionalNamespaces:t.optionalNamespaces||{}};await this.isValidConnect(e),e.optionalNamespaces=Ot(e.requiredNamespaces,e.optionalNamespaces),e.requiredNamespaces={};const{pairingTopic:s,requiredNamespaces:i,optionalNamespaces:r,sessionProperties:n,scopedProperties:o,relays:c,authentication:p,walletPay:l}=e,g=p?.[0]?.ttl||I.wc_sessionPropose.req.ttl||q;this.validateRequestExpiry(g);let y=s,u,w=!1;try{if(y){const E=this.client.core.pairing.pairings.get(y);this.client.logger.warn("connect() with existing pairing topic is deprecated and will be removed in the next major release."),w=E.active}}catch(E){throw this.client.logger.error(`connect() -> pairing.get(${y}) failed`),E}if(!y||!w){const{topic:E,uri:D}=await this.client.core.pairing.create({internal:{skipSubscribe:!0}});y=E,u=D}if(!y){const{message:E}=d("NO_MATCHING_KEY",`connect() pairing topic: ${y}`);throw new Error(E)}const h=await this.client.core.crypto.generateKeyPair(),m=P(g),_={requiredNamespaces:i,optionalNamespaces:r,relays:c??[{protocol:ft}],proposer:{publicKey:h,metadata:this.client.metadata},expiryTimestamp:m,pairingTopic:y,...n&&{sessionProperties:n},...o&&{scopedProperties:o},id:$(),...(p||l)&&{requests:{authentication:p?.map(E=>{const{domain:D,chains:ue,nonce:ie,uri:F,exp:B,nbf:re,type:W,statement:ne,requestId:ge,resources:v,signatureTypes:O}=E;return{domain:D,chains:ue,nonce:ie,type:W??"caip122",aud:F,version:"1",iat:new Date().toISOString(),exp:B,nbf:re,statement:ne,requestId:ge,resources:v,signatureTypes:O}}),walletPay:l}}},S=f("session_connect",_.id),{reject:A,resolve:N,done:k}=ee(g,Ve),T=({id:E})=>{E===_.id&&(this.client.events.off("proposal_expire",T),this.pendingSessions.delete(_.id),this.events.emit(S,{error:{message:Ve,code:0}}))};return this.client.events.on("proposal_expire",T),this.events.once(S,({error:E,session:D})=>{this.client.events.off("proposal_expire",T),E?A(E):D&&N(D)}),await this.setProposal(_.id,_),await this.sendProposeSession({proposal:_,publishOpts:{internal:{throwOnFailedPublish:!0},tvf:{correlationId:_.id}}}).catch(E=>{throw this.deleteProposal(_.id),E}),{uri:u,approval:k}},this.pair=async t=>{this.isInitialized(),await this.confirmOnlineStateOrThrow();try{return await this.client.core.pairing.pair(t)}catch(e){throw this.client.logger.error("pair() failed"),e}},this.approve=async t=>{const e=this.client.core.eventClient.createEvent({properties:{topic:t?.id?.toString(),trace:[x.session_approve_started]}});try{this.isInitialized(),await this.confirmOnlineStateOrThrow()}catch(T){throw e.setError(H.no_internet_connection),T}try{await this.isValidProposalId(t?.id)}catch(T){throw this.client.logger.error(`approve() -> proposal.get(${t?.id}) failed`),e.setError(H.proposal_not_found),T}try{await this.isValidApprove(t)}catch(T){throw this.client.logger.error("approve() -> isValidApprove() failed"),e.setError(H.session_approve_namespace_validation_failure),T}const{id:s,relayProtocol:i,namespaces:r,sessionProperties:n,scopedProperties:o,sessionConfig:c,proposalRequestsResponses:p}=t,l=this.client.proposal.get(s);this.client.core.eventClient.deleteEvent({eventId:e.eventId});const{pairingTopic:g,proposer:y,requiredNamespaces:u,optionalNamespaces:w}=l;let h=this.client.core.eventClient?.getEvent({topic:g});h||(h=this.client.core.eventClient?.createEvent({type:x.session_approve_started,properties:{topic:g,trace:[x.session_approve_started,x.session_namespaces_validation_success]}}));const m=await this.client.core.crypto.generateKeyPair(),_=y.publicKey,S=await this.client.core.crypto.generateSharedKey(m,_),A={relay:{protocol:i??"irn"},namespaces:r,controller:{publicKey:m,metadata:this.client.metadata},expiry:P(X),...n&&{sessionProperties:n},...o&&{scopedProperties:o},...c&&{sessionConfig:c},proposalRequestsResponses:p},N=R.relay;h.addTrace(x.subscribing_session_topic);try{await this.client.core.relayer.subscribe(S,{transportType:N,internal:{skipSubscribe:!0}})}catch(T){throw h.setError(H.subscribe_session_topic_failure),T}h.addTrace(x.subscribe_session_topic_success);const k={...A,topic:S,requiredNamespaces:u,optionalNamespaces:w,pairingTopic:g,acknowledged:!1,self:A.controller,peer:{publicKey:y.publicKey,metadata:y.metadata},controller:m,transportType:R.relay,authentication:p?.authentication,walletPayResult:p?.walletPay};await this.client.session.set(S,k),h.addTrace(x.store_session);try{await this.sendApproveSession({sessionTopic:S,proposal:l,pairingProposalResponse:{relay:{protocol:i??"irn"},responderPublicKey:m},sessionSettleRequest:A,publishOpts:{internal:{throwOnFailedPublish:!0},tvf:{correlationId:s,...this.getTVFApproveParams(k)}}}),h.addTrace(x.session_approve_publish_success)}catch(T){throw this.client.logger.error(T),this.client.session.delete(S,b("USER_DISCONNECTED")),await this.client.core.relayer.unsubscribe(S),T}return this.client.core.eventClient.deleteEvent({eventId:h.eventId}),await this.client.core.pairing.updateMetadata({topic:g,metadata:y.metadata}),await this.deleteProposal(s),await this.client.core.pairing.activate({topic:g}),await this.setExpiry(S,P(X)),{topic:S,acknowledged:()=>Promise.resolve(this.client.session.get(S))}},this.reject=async t=>{this.isInitialized(),await this.confirmOnlineStateOrThrow();try{await this.isValidReject(t)}catch(r){throw this.client.logger.error("reject() -> isValidReject() failed"),r}const{id:e,reason:s}=t;let i;try{i=this.client.proposal.get(e).pairingTopic}catch(r){throw this.client.logger.error(`reject() -> proposal.get(${e}) failed`),r}i&&await this.sendError({id:e,topic:i,error:s,rpcOpts:I.wc_sessionPropose.reject}),await this.deleteProposal(e)},this.update=async t=>{this.isInitialized(),await this.confirmOnlineStateOrThrow();try{await this.isValidUpdate(t)}catch(l){throw this.client.logger.error("update() -> isValidUpdate() failed"),l}const{topic:e,namespaces:s}=t,{done:i,resolve:r,reject:n}=ee(q,"Session update request expired without receiving any acknowledgement"),o=$(),c=we().toString(),p=this.client.session.get(e).namespaces;return this.events.once(f("session_update",o),({error:l})=>{l?n(l):r()}),await this.client.session.update(e,{namespaces:s}),await this.sendRequest({topic:e,method:"wc_sessionUpdate",params:{namespaces:s},throwOnFailedPublish:!0,clientRpcId:o,relayRpcId:c}).catch(l=>{this.client.logger.error(l),this.client.session.update(e,{namespaces:p}),n(l)}),{acknowledged:i}},this.extend=async t=>{this.isInitialized(),await this.confirmOnlineStateOrThrow();try{await this.isValidExtend(t)}catch(o){throw this.client.logger.error("extend() -> isValidExtend() failed"),o}const{topic:e}=t,s=$(),{done:i,resolve:r,reject:n}=ee(q,"Session extend request expired without receiving any acknowledgement");return this.events.once(f("session_extend",s),({error:o})=>{o?n(o):r()}),await this.setExpiry(e,P(X)),this.sendRequest({topic:e,method:"wc_sessionExtend",params:{},clientRpcId:s,throwOnFailedPublish:!0}).catch(o=>{n(o)}),{acknowledged:i}},this.request=async t=>{this.isInitialized();try{await this.isValidRequest(t)}catch(h){throw this.client.logger.error("request() -> isValidRequest() failed"),h}const{chainId:e,request:s,topic:i,expiry:r=I.wc_sessionRequest.req.ttl}=t,n=this.client.session.get(i);n?.transportType===R.relay&&await this.confirmOnlineStateOrThrow();const o=$(),c=we().toString(),{done:p,resolve:l,reject:g}=ee(r,"Request expired. Please try again.");this.events.once(f("session_request",o),({error:h,result:m})=>{h?g(h):l(m)});const y="wc_sessionRequest",u=this.getAppLinkIfEnabled(n.peer.metadata,n.transportType);if(u)return await this.sendRequest({clientRpcId:o,relayRpcId:c,topic:i,method:y,params:{request:{...s,expiryTimestamp:P(r)},chainId:e},expiry:r,throwOnFailedPublish:!0,appLink:u}).catch(h=>g(h)),this.client.events.emit("session_request_sent",{topic:i,request:s,chainId:e,id:o}),await p();const w={request:{...s,expiryTimestamp:P(r)},chainId:e};return await Promise.all([new Promise(async h=>{await this.sendRequest({clientRpcId:o,relayRpcId:c,topic:i,method:y,params:w,expiry:r,throwOnFailedPublish:!0,tvf:this.getTVFParams(o,w)}).catch(m=>g(m)),this.client.events.emit("session_request_sent",{topic:i,request:s,chainId:e,id:o}),h()}),new Promise(async h=>{if(!n.sessionConfig?.disableDeepLink){const m=await At(this.client.core.storage,Ce);await xt({id:o,topic:i,wcDeepLink:m})}h()}),p()]).then(h=>h[2])},this.respond=async t=>{this.isInitialized();const e=this.client.core.eventClient.createEvent({properties:{topic:t?.topic||t?.response?.id?.toString(),trace:[x.session_request_response_started]}});try{await this.isValidRespond(t)}catch(c){throw e.addTrace(c?.message),e.setError(H.session_request_response_validation_failure),c}e.addTrace(x.session_request_response_validation_success);const{topic:s,response:i}=t,{id:r}=i,n=this.client.session.get(s);n.transportType===R.relay&&await this.confirmOnlineStateOrThrow();const o=this.getAppLinkIfEnabled(n.peer.metadata,n.transportType);try{e.addTrace(x.session_request_response_publish_started),K(i)?await this.sendResult({id:r,topic:s,result:i.result,throwOnFailedPublish:!0,appLink:o}):U(i)&&await this.sendError({id:r,topic:s,error:i.error,appLink:o}),this.cleanupAfterResponse(t)}catch(c){throw e.addTrace(c?.message),e.setError(H.session_request_response_publish_failure),c}},this.ping=async t=>{this.isInitialized(),await this.confirmOnlineStateOrThrow();try{await this.isValidPing(t)}catch(s){throw this.client.logger.error("ping() -> isValidPing() failed"),s}const{topic:e}=t;if(this.client.session.keys.includes(e)){const s=$(),i=we().toString(),{done:r,resolve:n,reject:o}=ee(q,"Ping request expired without receiving any acknowledgement");this.events.once(f("session_ping",s),({error:c})=>{c?o(c):n()}),await Promise.all([this.sendRequest({topic:e,method:"wc_sessionPing",params:{},throwOnFailedPublish:!0,clientRpcId:s,relayRpcId:i}),r()])}else this.client.core.pairing.pairings.keys.includes(e)&&(this.client.logger.warn("ping() on pairing topic is deprecated and will be removed in the next major release."),await this.client.core.pairing.ping({topic:e}))},this.emit=async t=>{this.isInitialized(),await this.confirmOnlineStateOrThrow(),await this.isValidEmit(t);const{topic:e,event:s,chainId:i}=t,r=we().toString(),n=$();await this.sendRequest({topic:e,method:"wc_sessionEvent",params:{event:s,chainId:i},throwOnFailedPublish:!0,relayRpcId:r,clientRpcId:n})},this.disconnect=async t=>{this.isInitialized(),await this.confirmOnlineStateOrThrow(),await this.isValidDisconnect(t);const{topic:e}=t;if(this.client.session.keys.includes(e))await this.sendRequest({topic:e,method:"wc_sessionDelete",params:b("USER_DISCONNECTED"),throwOnFailedPublish:!0}),await this.deleteSession({topic:e,emitEvent:!1});else if(this.client.core.pairing.pairings.keys.includes(e))await this.client.core.pairing.disconnect({topic:e});else{const{message:s}=d("MISMATCHED_TOPIC",`Session or pairing topic not found: ${e}`);throw new Error(s)}},this.find=t=>(this.isInitialized(),this.client.session.getAll().filter(e=>bt(e,t))),this.getPendingSessionRequests=()=>this.client.pendingRequest.getAll(),this.authenticate=async(t,e)=>{this.isInitialized(),this.isValidAuthenticate(t);const s=e&&this.client.core.linkModeSupportedApps.includes(e)&&this.client.metadata.redirect?.linkMode,i=s?R.link_mode:R.relay;i===R.relay&&await this.confirmOnlineStateOrThrow();const{chains:r,statement:n="",uri:o,domain:c,nonce:p,type:l,exp:g,nbf:y,methods:u=[],expiry:w}=t,h=[...t.resources||[]],{topic:m,uri:_}=await this.client.core.pairing.create({methods:["wc_sessionAuthenticate"],transportType:i});this.client.logger.info({message:"Generated new pairing",pairing:{topic:m,uri:_}});const S=await this.client.core.crypto.generateKeyPair(),A=Te(S);if(await Promise.all([this.client.auth.authKeys.set(de,{responseTopic:A,publicKey:S}),this.client.auth.pairingTopics.set(A,{topic:A,pairingTopic:m})]),await this.client.core.relayer.subscribe(A,{transportType:i}),this.client.logger.info(`sending request to new pairing topic: ${m}`),u.length>0){const{namespace:v}=ve(r[0]);let O=Ct(v,"request",u);Pe(h)&&(O=Vt(O,h.pop())),h.push(O)}const N=w&&w>I.wc_sessionAuthenticate.req.ttl?w:I.wc_sessionAuthenticate.req.ttl,k={authPayload:{type:l??"caip122",chains:r,statement:n,aud:o,domain:c,version:"1",nonce:p,iat:new Date().toISOString(),exp:g,nbf:y,resources:h},requester:{publicKey:S,metadata:this.client.metadata},expiryTimestamp:P(N)},T={eip155:{chains:r,methods:[...new Set(["personal_sign",...u])],events:["chainChanged","accountsChanged"]}},E={requiredNamespaces:{},optionalNamespaces:T,relays:[{protocol:"irn"}],pairingTopic:m,proposer:{publicKey:S,metadata:this.client.metadata},expiryTimestamp:P(I.wc_sessionPropose.req.ttl),id:$()},{done:D,resolve:ue,reject:ie}=ee(N,"Request expired"),F=$(),B=f("session_connect",E.id),re=f("session_request",F),W=async({error:v,session:O})=>{this.events.off(re,ne),v?ie(v):O&&ue({session:O})},ne=async v=>{if(await this.deletePendingAuthRequest(F,{message:"fulfilled",code:0}),v.error){const ae=b("WC_METHOD_UNSUPPORTED","wc_sessionAuthenticate");return v.error.code===ae.code?void 0:(this.events.off(B,W),ie(v.error.message))}await this.deleteProposal(E.id),this.events.off(B,W);const{cacaos:O,responder:j}=v.result,Ee=[],ke=[];for(const ae of O){await Me({cacao:ae,projectId:this.client.core.projectId})||(this.client.logger.error(ae,"Signature verification failed"),ie(b("SESSION_SETTLEMENT_FAILED","Signature verification failed")));const{p:Re}=ae,Ie=Pe(Re.resources),De=[$e(Re.iss)],yt=Ke(Re.iss);if(Ie){const qe=Ue(Ie),mt=Ge(Ie);Ee.push(...qe),De.push(...mt)}for(const qe of De)ke.push(`${qe}:${yt}`)}const oe=await this.client.core.crypto.generateSharedKey(S,j.publicKey);let ye;Ee.length>0&&(ye={topic:oe,acknowledged:!0,self:{publicKey:S,metadata:this.client.metadata},peer:j,controller:j.publicKey,expiry:P(X),requiredNamespaces:{},optionalNamespaces:{},relay:{protocol:"irn"},pairingTopic:m,namespaces:Fe([...new Set(Ee)],[...new Set(ke)]),transportType:i},await this.client.core.relayer.subscribe(oe,{transportType:i}),await this.client.session.set(oe,ye),m&&await this.client.core.pairing.updateMetadata({topic:m,metadata:j.metadata}),ye=this.client.session.get(oe)),this.client.metadata.redirect?.linkMode&&j.metadata.redirect?.linkMode&&j.metadata.redirect?.universal&&e&&(this.client.core.addLinkModeSupportedApp(j.metadata.redirect.universal),this.client.session.update(oe,{transportType:R.link_mode})),ue({auths:O,session:ye})};this.events.once(B,W),this.events.once(re,ne);let ge;try{if(s){const v=se("wc_sessionAuthenticate",k,F);this.client.core.history.set(m,v);const O=await this.client.core.crypto.encode("",v,{type:kt,encoding:pe});ge=me(e,m,O)}else await Promise.all([this.sendRequest({topic:m,method:"wc_sessionAuthenticate",params:k,expiry:t.expiry,throwOnFailedPublish:!0,clientRpcId:F}),this.sendRequest({topic:m,method:"wc_sessionPropose",params:E,expiry:I.wc_sessionPropose.req.ttl,throwOnFailedPublish:!0,clientRpcId:E.id})])}catch(v){throw this.events.off(B,W),this.events.off(re,ne),v}return await this.setProposal(E.id,E),await this.setAuthRequest(F,{request:{...k,verifyContext:{}},pairingTopic:m,transportType:i}),{uri:ge??_,response:D}},this.approveSessionAuthenticate=async t=>{const{id:e,auths:s}=t,i=this.client.core.eventClient.createEvent({properties:{topic:e.toString(),trace:[Q.authenticated_session_approve_started]}});try{this.isInitialized()}catch(h){throw i.setError(ce.no_internet_connection),h}const r=this.getPendingAuthRequest(e);if(!r)throw i.setError(ce.authenticated_session_pending_request_not_found),new Error(`Could not find pending auth request with id ${e}`);const n=r.transportType||R.relay;n===R.relay&&await this.confirmOnlineStateOrThrow();const o=r.requester.publicKey,c=await this.client.core.crypto.generateKeyPair(),p=Te(o),l={type:Ne,receiverPublicKey:o,senderPublicKey:c},g=[],y=[];for(const h of s){if(!await Me({cacao:h,projectId:this.client.core.projectId})){i.setError(ce.invalid_cacao);const N=b("SESSION_SETTLEMENT_FAILED","Signature verification failed");throw await this.sendError({id:e,topic:p,error:N,encodeOpts:l}),new Error(N.message)}i.addTrace(Q.cacaos_verified);const{p:m}=h,_=Pe(m.resources),S=[$e(m.iss)],A=Ke(m.iss);if(_){const N=Ue(_),k=Ge(_);g.push(...N),S.push(...k)}for(const N of S)y.push(`${N}:${A}`)}const u=await this.client.core.crypto.generateSharedKey(c,o);i.addTrace(Q.create_authenticated_session_topic);let w;if(g?.length>0){w={topic:u,acknowledged:!0,self:{publicKey:c,metadata:this.client.metadata},peer:{publicKey:o,metadata:r.requester.metadata},controller:o,expiry:P(X),authentication:s,requiredNamespaces:{},optionalNamespaces:{},relay:{protocol:"irn"},pairingTopic:r.pairingTopic,namespaces:Fe([...new Set(g)],[...new Set(y)]),transportType:n},i.addTrace(Q.subscribing_authenticated_session_topic);try{await this.client.core.relayer.subscribe(u,{transportType:n})}catch(h){throw i.setError(ce.subscribe_authenticated_session_topic_failure),h}i.addTrace(Q.subscribe_authenticated_session_topic_success),await this.client.session.set(u,w),i.addTrace(Q.store_authenticated_session),await this.client.core.pairing.updateMetadata({topic:r.pairingTopic,metadata:r.requester.metadata})}i.addTrace(Q.publishing_authenticated_session_approve);try{await this.sendResult({topic:p,id:e,result:{cacaos:s,responder:{publicKey:c,metadata:this.client.metadata}},encodeOpts:l,throwOnFailedPublish:!0,appLink:this.getAppLinkIfEnabled(r.requester.metadata,n)})}catch(h){throw i.setError(ce.authenticated_session_approve_publish_failure),h}return await this.client.auth.requests.delete(e,{message:"fulfilled",code:0}),await this.client.core.pairing.activate({topic:r.pairingTopic}),this.client.core.eventClient.deleteEvent({eventId:i.eventId}),{session:w}},this.rejectSessionAuthenticate=async t=>{this.isInitialized();const{id:e,reason:s}=t,i=this.getPendingAuthRequest(e);if(!i)throw new Error(`Could not find pending auth request with id ${e}`);i.transportType===R.relay&&await this.confirmOnlineStateOrThrow();const r=i.requester.publicKey,n=await this.client.core.crypto.generateKeyPair(),o=Te(r),c={type:Ne,receiverPublicKey:r,senderPublicKey:n};await this.sendError({id:e,topic:o,error:s,encodeOpts:c,rpcOpts:I.wc_sessionAuthenticate.reject,appLink:this.getAppLinkIfEnabled(i.requester.metadata,i.transportType)}),await this.client.auth.requests.delete(e,{message:"rejected",code:0}),await this.deleteProposal(e)},this.formatAuthMessage=t=>{this.isInitialized();const{request:e,iss:s}=t;return Dt(e,s)},this.processRelayMessageCache=()=>{setTimeout(async()=>{if(this.relayMessageCache.length!==0)for(;this.relayMessageCache.length>0;)try{const t=this.relayMessageCache.shift();t&&await this.onRelayMessage(t)}catch(t){this.client.logger.error(t)}},50)},this.cleanupDuplicatePairings=async t=>{if(t.pairingTopic)try{const e=this.client.core.pairing.pairings.get(t.pairingTopic),s=this.client.core.pairing.pairings.getAll().filter(i=>i.peerMetadata?.url&&i.peerMetadata?.url===t.peer.metadata.url&&i.topic&&i.topic!==e.topic);if(s.length===0)return;this.client.logger.info(`Cleaning up ${s.length} duplicate pairing(s)`),await Promise.all(s.map(i=>this.client.core.pairing.disconnect({topic:i.topic}))),this.client.logger.info("Duplicate pairings clean up finished")}catch(e){this.client.logger.error(e)}},this.deleteSession=async t=>{const{topic:e,expirerHasDeleted:s=!1,emitEvent:i=!0,id:r=0}=t,{self:n}=this.client.session.get(e);await this.client.core.relayer.unsubscribe(e),await this.client.session.delete(e,b("USER_DISCONNECTED")),this.addToRecentlyDeleted(e,"session"),this.client.core.crypto.keychain.has(n.publicKey)&&await this.client.core.crypto.deleteKeyPair(n.publicKey),this.client.core.crypto.keychain.has(e)&&await this.client.core.crypto.deleteSymKey(e),s||this.client.core.expirer.del(e),this.client.core.storage.removeItem(Ce).catch(o=>this.client.logger.warn(o)),e===this.sessionRequestQueue.queue[0]?.topic&&(this.sessionRequestQueue.state=V.idle),await Promise.all(this.getPendingSessionRequests().filter(o=>o.topic===e).map(o=>this.deletePendingSessionRequest(o.id,b("USER_DISCONNECTED")))),i&&this.client.events.emit("session_delete",{id:r,topic:e})},this.deleteProposal=async(t,e)=>{if(e)try{const s=this.client.proposal.get(t);this.client.core.eventClient.getEvent({topic:s.pairingTopic})?.setError(H.proposal_expired)}catch{}await Promise.all([this.client.proposal.delete(t,b("USER_DISCONNECTED")),e?Promise.resolve():this.client.core.expirer.del(t)]),this.addToRecentlyDeleted(t,"proposal")},this.deletePendingSessionRequest=async(t,e,s=!1)=>{await Promise.all([this.client.pendingRequest.delete(t,e),s?Promise.resolve():this.client.core.expirer.del(t)]),this.addToRecentlyDeleted(t,"request"),this.sessionRequestQueue.queue=this.sessionRequestQueue.queue.filter(i=>i.id!==t),s&&(this.sessionRequestQueue.state=V.idle,this.client.events.emit("session_request_expire",{id:t}))},this.deletePendingAuthRequest=async(t,e,s=!1)=>{await Promise.all([this.client.auth.requests.delete(t,e),s?Promise.resolve():this.client.core.expirer.del(t)])},this.setExpiry=async(t,e)=>{this.client.session.keys.includes(t)&&(this.client.core.expirer.set(t,e),await this.client.session.update(t,{expiry:e}))},this.setProposal=async(t,e)=>{this.client.core.expirer.set(t,P(I.wc_sessionPropose.req.ttl)),await this.client.proposal.set(t,e)},this.setAuthRequest=async(t,e)=>{const{request:s,pairingTopic:i,transportType:r=R.relay}=e;this.client.core.expirer.set(t,s.expiryTimestamp),await this.client.auth.requests.set(t,{authPayload:s.authPayload,requester:s.requester,expiryTimestamp:s.expiryTimestamp,id:t,pairingTopic:i,verifyContext:s.verifyContext,transportType:r})},this.setPendingSessionRequest=async t=>{const{id:e,topic:s,params:i,verifyContext:r}=t,n=i.request.expiryTimestamp||P(I.wc_sessionRequest.req.ttl);this.client.core.expirer.set(e,n),await this.client.pendingRequest.set(e,{id:e,topic:s,params:i,verifyContext:r})},this.sendRequest=async t=>{const{topic:e,method:s,params:i,expiry:r,relayRpcId:n,clientRpcId:o,throwOnFailedPublish:c,appLink:p,tvf:l,publishOpts:g={}}=t,y=se(s,i,o);let u;const w=!!p;try{const _=w?pe:z;u=await this.client.core.crypto.encode(e,y,{encoding:_})}catch(_){throw await this.cleanup(),this.client.logger.error(`sendRequest() -> core.crypto.encode() for topic ${e} failed`),_}let h;if(ot.includes(s)){const _=L(JSON.stringify(y)),S=L(u);h=await this.client.core.verify.register({id:S,decryptedId:_})}const m={...I[s].req,...g};if(m.attestation=h,r&&(m.ttl=r),n&&(m.id=n),this.client.core.history.set(e,y),w){const _=me(p,e,u);await global.Linking.openURL(_,this.client.name)}else m.tvf={...l,correlationId:y.id},c?(m.internal={...m.internal,throwOnFailedPublish:!0},await this.client.core.relayer.publish(e,u,m)):this.client.core.relayer.publish(e,u,m).catch(_=>this.client.logger.error(_));return y.id},this.sendProposeSession=async t=>{const{proposal:e,publishOpts:s}=t,i=se("wc_sessionPropose",e,e.id);this.client.core.history.set(e.pairingTopic,i);const r=await this.client.core.crypto.encode(e.pairingTopic,i,{encoding:z}),n=L(JSON.stringify(i)),o=L(r),c=await this.client.core.verify.register({id:o,decryptedId:n});await this.client.core.relayer.publishCustom({payload:{pairingTopic:e.pairingTopic,sessionProposal:r},opts:{...s,publishMethod:"wc_proposeSession",attestation:c}})},this.sendApproveSession=async t=>{const{sessionTopic:e,pairingProposalResponse:s,proposal:i,sessionSettleRequest:r,publishOpts:n}=t,o=et(i.id,s),c=await this.client.core.crypto.encode(i.pairingTopic,o,{encoding:z}),p=se("wc_sessionSettle",r,n?.id),l=await this.client.core.crypto.encode(e,p,{encoding:z});this.client.core.history.set(e,p),await this.client.core.relayer.publishCustom({payload:{sessionTopic:e,pairingTopic:i.pairingTopic,sessionProposalResponse:c,sessionSettlementRequest:l},opts:{...n,publishMethod:"wc_approveSession"}})},this.sendResult=async t=>{const{id:e,topic:s,result:i,throwOnFailedPublish:r,encodeOpts:n,appLink:o}=t,c=et(e,i);let p;const l=o&&typeof global?.Linking<"u";try{const u=l?pe:z;p=await this.client.core.crypto.encode(s,c,{...n||{},encoding:u})}catch(u){throw await this.cleanup(),this.client.logger.error(`sendResult() -> core.crypto.encode() for topic ${s} failed`),u}let g,y;try{g=await this.client.core.history.get(s,e);const u=g.request;try{y=this.getTVFParams(e,u.params,i)}catch(w){this.client.logger.warn(`sendResult() -> getTVFParams() failed: ${w?.message}`)}}catch(u){throw this.client.logger.error(`sendResult() -> history.get(${s}, ${e}) failed`),u}if(l){const u=me(o,s,p);await global.Linking.openURL(u,this.client.name)}else{const u=g.request.method,w=I[u].res;w.tvf={...y,correlationId:e},r?(w.internal={...w.internal,throwOnFailedPublish:!0},await this.client.core.relayer.publish(s,p,w)):this.client.core.relayer.publish(s,p,w).catch(h=>this.client.logger.error(h))}await this.client.core.history.resolve(c)},this.sendError=async t=>{const{id:e,topic:s,error:i,encodeOpts:r,rpcOpts:n,appLink:o}=t,c=hs(e,i);let p;const l=o&&typeof global?.Linking<"u";try{const y=l?pe:z;p=await this.client.core.crypto.encode(s,c,{...r||{},encoding:y})}catch(y){throw await this.cleanup(),this.client.logger.error(`sendError() -> core.crypto.encode() for topic ${s} failed`),y}let g;try{g=await this.client.core.history.get(s,e)}catch(y){throw this.client.logger.error(`sendError() -> history.get(${s}, ${e}) failed`),y}if(l){const y=me(o,s,p);await global.Linking.openURL(y,this.client.name)}else{const y=g.request.method,u=n||I[y].res;this.client.core.relayer.publish(s,p,u)}await this.client.core.history.resolve(c)},this.cleanup=async()=>{const t=[],e=[];this.client.session.getAll().forEach(s=>{let i=!1;te(s.expiry)&&(i=!0),this.client.core.crypto.keychain.has(s.topic)||(i=!0),i&&t.push(s.topic)}),this.client.proposal.getAll().forEach(s=>{te(s.expiryTimestamp)&&e.push(s.id)}),await Promise.all([...t.map(s=>this.deleteSession({topic:s})),...e.map(s=>this.deleteProposal(s))])},this.onProviderMessageEvent=async t=>{!this.initialized||this.relayMessageCache.length>0?this.relayMessageCache.push(t):await this.onRelayMessage(t)},this.onRelayEventRequest=async t=>{this.requestQueue.queue.push(t),await this.processRequestsQueue()},this.processRequestsQueue=async()=>{if(this.requestQueue.state===V.active){this.client.logger.info("Request queue already active, skipping...");return}for(this.client.logger.info(`Request queue starting with ${this.requestQueue.queue.length} requests`);this.requestQueue.queue.length>0;){this.requestQueue.state=V.active;const t=this.requestQueue.queue.shift();if(t)try{await this.processRequest(t)}catch(e){this.client.logger.warn(e)}}this.requestQueue.state=V.idle},this.processRequest=async t=>{const{topic:e,payload:s,attestation:i,transportType:r,encryptedId:n}=t,o=s.method;if(!this.shouldIgnorePairingRequest({topic:e,requestMethod:o}))switch(o){case"wc_sessionPropose":return await this.onSessionProposeRequest({topic:e,payload:s,attestation:i,encryptedId:n});case"wc_sessionSettle":return await this.onSessionSettleRequest(e,s);case"wc_sessionUpdate":return await this.onSessionUpdateRequest(e,s);case"wc_sessionExtend":return await this.onSessionExtendRequest(e,s);case"wc_sessionPing":return await this.onSessionPingRequest(e,s);case"wc_sessionDelete":return await this.onSessionDeleteRequest(e,s);case"wc_sessionRequest":return await this.onSessionRequest({topic:e,payload:s,attestation:i,encryptedId:n,transportType:r});case"wc_sessionEvent":return await this.onSessionEventRequest(e,s);case"wc_sessionAuthenticate":return await this.onSessionAuthenticateRequest({topic:e,payload:s,attestation:i,encryptedId:n,transportType:r});default:return this.client.logger.info(`Unsupported request method ${o}`)}},this.onRelayEventResponse=async t=>{const{topic:e,payload:s,transportType:i}=t,r=(await this.client.core.history.get(e,s.id)).request.method;switch(r){case"wc_sessionPropose":return this.onSessionProposeResponse(e,s,i);case"wc_sessionSettle":return this.onSessionSettleResponse(e,s);case"wc_sessionUpdate":return this.onSessionUpdateResponse(e,s);case"wc_sessionExtend":return this.onSessionExtendResponse(e,s);case"wc_sessionPing":return this.onSessionPingResponse(e,s);case"wc_sessionRequest":return this.onSessionRequestResponse(e,s);case"wc_sessionAuthenticate":return this.onSessionAuthenticateResponse(e,s);default:return this.client.logger.info(`Unsupported response method ${r}`)}},this.onRelayEventUnknownPayload=t=>{const{topic:e}=t,{message:s}=d("MISSING_OR_INVALID",`Decoded payload on topic ${e} is not identifiable as a JSON-RPC request or a response.`);throw new Error(s)},this.shouldIgnorePairingRequest=t=>{const{topic:e,requestMethod:s}=t,i=this.expectedPairingMethodMap.get(e);return!i||i.includes(s)?!1:!!(i.includes("wc_sessionAuthenticate")&&this.client.events.listenerCount("session_authenticate")>0)},this.onSessionProposeRequest=async t=>{const{topic:e,payload:s,attestation:i,encryptedId:r}=t,{params:n,id:o}=s;try{const c=this.client.core.eventClient.getEvent({topic:e});this.client.events.listenerCount("session_proposal")===0&&(console.warn("No listener for session_proposal event"),c?.setError(St.proposal_listener_not_found)),this.isValidConnect({...s.params});const p=n.expiryTimestamp||P(I.wc_sessionPropose.req.ttl),l={id:o,pairingTopic:e,expiryTimestamp:p,attestation:i,encryptedId:r,...n};await this.setProposal(o,l);const g=await this.getVerifyContext({attestationId:i,hash:L(JSON.stringify(s)),encryptedId:r,metadata:l.proposer.metadata});c?.addTrace(Et.emit_session_proposal),this.client.events.emit("session_proposal",{id:o,params:l,verifyContext:g})}catch(c){await this.sendError({id:o,topic:e,error:c,rpcOpts:I.wc_sessionPropose.autoReject}),this.client.logger.error(c)}},this.onSessionProposeResponse=async(t,e,s)=>{const{id:i}=e;if(K(e)){const{result:r}=e;this.client.logger.trace({type:"method",method:"onSessionProposeResponse",result:r});const n=this.client.proposal.get(i);this.client.logger.trace({type:"method",method:"onSessionProposeResponse",proposal:n});const o=n.proposer.publicKey;this.client.logger.trace({type:"method",method:"onSessionProposeResponse",selfPublicKey:o});const c=r.responderPublicKey;this.client.logger.trace({type:"method",method:"onSessionProposeResponse",peerPublicKey:c});const p=await this.client.core.crypto.generateSharedKey(o,c);this.pendingSessions.set(i,{sessionTopic:p,pairingTopic:t,proposalId:i,publicKey:o});const l=await this.client.core.relayer.subscribe(p,{transportType:s});this.client.logger.trace({type:"method",method:"onSessionProposeResponse",subscriptionId:l}),await this.client.core.pairing.activate({topic:t})}else if(U(e)){await this.deleteProposal(i);const r=f("session_connect",i);if(this.events.listenerCount(r)===0)throw new Error(`emitting ${r} without any listeners, 954`);this.events.emit(r,{error:e.error})}},this.onSessionSettleRequest=async(t,e)=>{const{id:s,params:i}=e;try{this.isValidSessionSettleRequest(i);const{relay:r,controller:n,expiry:o,namespaces:c,sessionProperties:p,scopedProperties:l,sessionConfig:g,proposalRequestsResponses:y}=e.params,u=[...this.pendingSessions.values()].find(m=>m.sessionTopic===t);if(!u)return this.client.logger.error(`Pending session not found for topic ${t}`);const w=this.client.proposal.get(u.proposalId),h={topic:t,relay:r,expiry:o,namespaces:c,acknowledged:!0,pairingTopic:u.pairingTopic,requiredNamespaces:w.requiredNamespaces,optionalNamespaces:w.optionalNamespaces,controller:n.publicKey,self:{publicKey:u.publicKey,metadata:this.client.metadata},peer:{publicKey:n.publicKey,metadata:n.metadata},...p&&{sessionProperties:p},...l&&{scopedProperties:l},...g&&{sessionConfig:g},transportType:R.relay,authentication:y?.authentication,walletPayResult:y?.walletPay};await this.client.session.set(h.topic,h),await this.setExpiry(h.topic,h.expiry),await this.client.core.pairing.updateMetadata({topic:u.pairingTopic,metadata:h.peer.metadata}),this.pendingSessions.delete(u.proposalId),this.deleteProposal(u.proposalId,!1),this.cleanupDuplicatePairings(h),await this.sendResult({id:e.id,topic:t,throwOnFailedPublish:!0,result:!0}),this.client.events.emit("session_connect",{session:h}),this.events.emit(f("session_connect",u.proposalId),{session:h})}catch(r){await this.sendError({id:s,topic:t,error:r}),this.client.logger.error(r)}},this.onSessionSettleResponse=async(t,e)=>{const{id:s}=e;K(e)?(await this.client.session.update(t,{acknowledged:!0}),this.events.emit(f("session_approve",s),{})):U(e)&&(await this.client.session.delete(t,b("USER_DISCONNECTED")),this.events.emit(f("session_approve",s),{error:e.error}))},this.onSessionUpdateRequest=async(t,e)=>{const{params:s,id:i}=e;try{const r=`${t}_session_update`,n=le.get(r);if(n&&this.isRequestOutOfSync(n,i)){this.client.logger.warn(`Discarding out of sync request - ${i}`),this.sendError({id:i,topic:t,error:b("INVALID_UPDATE_REQUEST")});return}this.isValidUpdate({topic:t,...s});try{le.set(r,i),await this.client.session.update(t,{namespaces:s.namespaces}),await this.sendResult({id:i,topic:t,result:!0})}catch(o){throw le.delete(r),o}this.client.events.emit("session_update",{id:i,topic:t,params:s})}catch(r){await this.sendError({id:i,topic:t,error:r}),this.client.logger.error(r)}},this.isRequestOutOfSync=(t,e)=>e.toString().slice(0,-3)<t.toString().slice(0,-3),this.onSessionUpdateResponse=(t,e)=>{const{id:s}=e,i=f("session_update",s);if(this.events.listenerCount(i)===0)throw new Error(`emitting ${i} without any listeners`);K(e)?this.events.emit(f("session_update",s),{}):U(e)&&this.events.emit(f("session_update",s),{error:e.error})},this.onSessionExtendRequest=async(t,e)=>{const{id:s}=e;try{this.isValidExtend({topic:t}),await this.setExpiry(t,P(X)),await this.sendResult({id:s,topic:t,result:!0}),this.client.events.emit("session_extend",{id:s,topic:t})}catch(i){await this.sendError({id:s,topic:t,error:i}),this.client.logger.error(i)}},this.onSessionExtendResponse=(t,e)=>{const{id:s}=e,i=f("session_extend",s);if(this.events.listenerCount(i)===0)throw new Error(`emitting ${i} without any listeners`);K(e)?this.events.emit(f("session_extend",s),{}):U(e)&&this.events.emit(f("session_extend",s),{error:e.error})},this.onSessionPingRequest=async(t,e)=>{const{id:s}=e;try{this.isValidPing({topic:t}),await this.sendResult({id:s,topic:t,result:!0,throwOnFailedPublish:!0}),this.client.events.emit("session_ping",{id:s,topic:t})}catch(i){await this.sendError({id:s,topic:t,error:i}),this.client.logger.error(i)}},this.onSessionPingResponse=(t,e)=>{const{id:s}=e,i=f("session_ping",s);setTimeout(()=>{if(this.events.listenerCount(i)===0)throw new Error(`emitting ${i} without any listeners 2176`);K(e)?this.events.emit(f("session_ping",s),{}):U(e)&&this.events.emit(f("session_ping",s),{error:e.error})},500)},this.onSessionDeleteRequest=async(t,e)=>{const{id:s}=e;try{await this.isValidDisconnect({topic:t,reason:e.params}),this.cleanupPendingSentRequestsForTopic({topic:t,error:b("USER_DISCONNECTED")}),await this.deleteSession({topic:t,id:s})}catch(i){this.client.logger.error(i)}},this.onSessionRequest=async t=>{const{topic:e,payload:s,attestation:i,encryptedId:r,transportType:n}=t,{id:o,params:c}=s;try{await this.isValidRequest({topic:e,...c});const p=this.client.session.get(e),l=await this.getVerifyContext({attestationId:i,hash:L(JSON.stringify(se("wc_sessionRequest",c,o))),encryptedId:r,metadata:p.peer.metadata,transportType:n}),g={id:o,topic:e,params:c,verifyContext:l};await this.setPendingSessionRequest(g),n===R.link_mode&&p.peer.metadata.redirect?.universal&&this.client.core.addLinkModeSupportedApp(p.peer.metadata.redirect?.universal),this.client.signConfig?.disableRequestQueue?this.emitSessionRequest(g):(this.addSessionRequestToSessionRequestQueue(g),this.processSessionRequestQueue())}catch(p){await this.sendError({id:o,topic:e,error:p}),this.client.logger.error(p)}},this.onSessionRequestResponse=(t,e)=>{const{id:s}=e,i=f("session_request",s);if(this.events.listenerCount(i)===0)throw new Error(`emitting ${i} without any listeners`);K(e)?this.events.emit(f("session_request",s),{result:e.result}):U(e)&&this.events.emit(f("session_request",s),{error:e.error})},this.onSessionEventRequest=async(t,e)=>{const{id:s,params:i}=e;try{const r=`${t}_session_event_${i.event.name}`,n=le.get(r);if(n&&this.isRequestOutOfSync(n,s)){this.client.logger.info(`Discarding out of sync request - ${s}`);return}this.isValidEmit({topic:t,...i}),this.client.events.emit("session_event",{id:s,topic:t,params:i}),le.set(r,s)}catch(r){await this.sendError({id:s,topic:t,error:r}),this.client.logger.error(r)}},this.onSessionAuthenticateResponse=(t,e)=>{const{id:s}=e;this.client.logger.trace({type:"method",method:"onSessionAuthenticateResponse",topic:t,payload:e}),K(e)?this.events.emit(f("session_request",s),{result:e.result}):U(e)&&this.events.emit(f("session_request",s),{error:e.error})},this.onSessionAuthenticateRequest=async t=>{const{topic:e,payload:s,attestation:i,encryptedId:r,transportType:n}=t;try{const{requester:o,authPayload:c,expiryTimestamp:p}=s.params,l=await this.getVerifyContext({attestationId:i,hash:L(JSON.stringify(s)),encryptedId:r,metadata:o.metadata,transportType:n}),g={requester:o,pairingTopic:e,id:s.id,authPayload:c,verifyContext:l,expiryTimestamp:p};await this.setAuthRequest(s.id,{request:g,pairingTopic:e,transportType:n}),n===R.link_mode&&o.metadata.redirect?.universal&&this.client.core.addLinkModeSupportedApp(o.metadata.redirect.universal),this.client.events.emit("session_authenticate",{topic:e,params:s.params,id:s.id,verifyContext:l})}catch(o){this.client.logger.error(o);const c=s.params.requester.publicKey,p=await this.client.core.crypto.generateKeyPair(),l=this.getAppLinkIfEnabled(s.params.requester.metadata,n),g={type:Ne,receiverPublicKey:c,senderPublicKey:p};await this.sendError({id:s.id,topic:e,error:o,encodeOpts:g,rpcOpts:I.wc_sessionAuthenticate.autoReject,appLink:l})}},this.addSessionRequestToSessionRequestQueue=t=>{this.sessionRequestQueue.queue.push(t)},this.cleanupAfterResponse=t=>{this.deletePendingSessionRequest(t.response.id,{message:"fulfilled",code:0}),setTimeout(()=>{this.sessionRequestQueue.state=V.idle,this.processSessionRequestQueue()},Ze(this.requestQueueDelay))},this.cleanupPendingSentRequestsForTopic=({topic:t,error:e})=>{const s=this.client.core.history.pending;s.length>0&&s.filter(i=>i.topic===t&&i.request.method==="wc_sessionRequest").forEach(i=>{this.events.emit(f("session_request",i.request.id),{error:e})})},this.processSessionRequestQueue=()=>{if(this.sessionRequestQueue.state===V.active){this.client.logger.info("session request queue is already active.");return}const t=this.sessionRequestQueue.queue[0];if(!t){this.client.logger.info("session request queue is empty.");return}try{this.emitSessionRequest(t)}catch(e){this.client.logger.error(e)}},this.emitSessionRequest=t=>{if(this.emittedSessionRequests.has(t.id)){this.client.logger.warn({id:t.id},`Skipping emitting \`session_request\` event for duplicate request. id: ${t.id}`);return}this.sessionRequestQueue.state=V.active,this.emittedSessionRequests.add(t.id),this.client.events.emit("session_request",t)},this.onPairingCreated=t=>{if(t.methods&&this.expectedPairingMethodMap.set(t.topic,t.methods),t.active)return;const e=this.client.proposal.getAll().find(s=>s.pairingTopic===t.topic);e&&this.onSessionProposeRequest({topic:t.topic,payload:se("wc_sessionPropose",{...e,requiredNamespaces:e.requiredNamespaces,optionalNamespaces:e.optionalNamespaces,relays:e.relays,proposer:e.proposer,sessionProperties:e.sessionProperties,scopedProperties:e.scopedProperties},e.id),attestation:e.attestation,encryptedId:e.encryptedId})},this.isValidConnect=async t=>{if(!C(t)){const{message:c}=d("MISSING_OR_INVALID",`connect() params: ${JSON.stringify(t)}`);throw new Error(c)}const{pairingTopic:e,requiredNamespaces:s,optionalNamespaces:i,sessionProperties:r,scopedProperties:n,relays:o}=t;if(Y(e)||await this.isValidPairingTopic(e),!Lt(o,!0)){const{message:c}=d("MISSING_OR_INVALID",`connect() relays: ${o}`);throw new Error(c)}if(s&&!Y(s)&&je(s)!==0){const c="requiredNamespaces are deprecated and are automatically assigned to optionalNamespaces";["fatal","error","silent"].includes(this.client.logger.level)?console.warn(c):this.client.logger.warn(c),this.validateNamespaces(s,"requiredNamespaces")}if(i&&!Y(i)&&je(i)!==0&&this.validateNamespaces(i,"optionalNamespaces"),r&&!Y(r)&&this.validateSessionProps(r,"sessionProperties"),n&&!Y(n)){this.validateSessionProps(n,"scopedProperties");const c=Object.keys(s||{}).concat(Object.keys(i||{}));if(!Object.keys(n).every(p=>c.includes(p.split(":")[0])))throw new Error(`Scoped properties must be a subset of required/optional namespaces, received: ${JSON.stringify(n)}, required/optional namespaces: ${JSON.stringify(c)}`)}},this.validateNamespaces=(t,e)=>{const s=Mt(t,"connect()",e);if(s)throw new Error(s.message)},this.isValidApprove=async t=>{if(!C(t))throw new Error(d("MISSING_OR_INVALID",`approve() params: ${t}`).message);const{id:e,namespaces:s,relayProtocol:i,sessionProperties:r,scopedProperties:n}=t;this.checkRecentlyDeleted(e),await this.isValidProposalId(e);const o=this.client.proposal.get(e),c=Oe(s,"approve()");if(c)throw new Error(c.message);const p=He(o.requiredNamespaces,s,"approve()");if(p)throw new Error(p.message);if(!J(i,!0)){const{message:l}=d("MISSING_OR_INVALID",`approve() relayProtocol: ${i}`);throw new Error(l)}if(r&&!Y(r)&&this.validateSessionProps(r,"sessionProperties"),n&&!Y(n)){this.validateSessionProps(n,"scopedProperties");const l=new Set(Object.keys(s));if(!Object.keys(n).every(g=>l.has(g.split(":")[0])))throw new Error(`Scoped properties must be a subset of approved namespaces, received: ${JSON.stringify(n)}, approved namespaces: ${Array.from(l).join(", ")}`)}},this.isValidReject=async t=>{if(!C(t)){const{message:i}=d("MISSING_OR_INVALID",`reject() params: ${t}`);throw new Error(i)}const{id:e,reason:s}=t;if(this.checkRecentlyDeleted(e),await this.isValidProposalId(e),!$t(s)){const{message:i}=d("MISSING_OR_INVALID",`reject() reason: ${JSON.stringify(s)}`);throw new Error(i)}},this.isValidSessionSettleRequest=t=>{if(!C(t)){const{message:c}=d("MISSING_OR_INVALID",`onSessionSettleRequest() params: ${t}`);throw new Error(c)}const{relay:e,controller:s,namespaces:i,expiry:r}=t;if(!Kt(e)){const{message:c}=d("MISSING_OR_INVALID","onSessionSettleRequest() relay protocol should be a string");throw new Error(c)}const n=Ut(s,"onSessionSettleRequest()");if(n)throw new Error(n.message);const o=Oe(i,"onSessionSettleRequest()");if(o)throw new Error(o.message);if(te(r)){const{message:c}=d("EXPIRED","onSessionSettleRequest()");throw new Error(c)}},this.isValidUpdate=async t=>{if(!C(t)){const{message:o}=d("MISSING_OR_INVALID",`update() params: ${t}`);throw new Error(o)}const{topic:e,namespaces:s}=t;this.checkRecentlyDeleted(e),await this.isValidSessionTopic(e);const i=this.client.session.get(e),r=Oe(s,"update()");if(r)throw new Error(r.message);const n=He(i.requiredNamespaces,s,"update()");if(n)throw new Error(n.message)},this.isValidExtend=async t=>{if(!C(t)){const{message:s}=d("MISSING_OR_INVALID",`extend() params: ${t}`);throw new Error(s)}const{topic:e}=t;this.checkRecentlyDeleted(e),await this.isValidSessionTopic(e)},this.isValidRequest=async t=>{if(!C(t)){const{message:o}=d("MISSING_OR_INVALID",`request() params: ${t}`);throw new Error(o)}const{topic:e,request:s,chainId:i,expiry:r}=t;this.checkRecentlyDeleted(e),await this.isValidSessionTopic(e);const{namespaces:n}=this.client.session.get(e);if(!Qe(n,i)){const{message:o}=d("MISSING_OR_INVALID",`request() chainId: ${i}`);throw new Error(o)}if(!Gt(s)){const{message:o}=d("MISSING_OR_INVALID",`request() ${JSON.stringify(s)}`);throw new Error(o)}if(!Ft(n,i,s.method)){const{message:o}=d("MISSING_OR_INVALID",`reque