UNPKG

@micro-stacks/client

Version:

Session client for Stacks apps using micro-stacks

22 lines (18 loc) 27.6 kB
import { hashMessage, recoverSignature, getPublicKeyFromSignature, verifyMessageSignature, authenticate, makeStxTransferToken, makeContractCallToken, makeContractDeployToken, openTransactionPopup, handlePSBTRequest, handleSignMessageRequest, handleSignStructuredDataRequest } from 'micro-stacks/connect'; import { StacksMainnet, ChainID, StacksTestnet } from 'micro-stacks/network'; import Ht from 'zustand/vanilla'; import { subscribeWithSelector, persist } from 'zustand/middleware'; import { hexToBytes, fetchPrivate, getGlobalObject, bytesToHex } from 'micro-stacks/common'; import nt from 'tiny-invariant'; import { publicKeyToStxAddress, c32addressDecode, validateStacksAddress, c32address, StacksNetworkVersion, privateKeyToBase58Address, encryptContent, decryptContent } from 'micro-stacks/crypto'; import { generateGaiaHubConfigSync, putFile, getFile } from 'micro-stacks/storage'; import I from 'fast-deep-equal/es6/index.js'; var et="micro-stacks",P={getItem:n=>null,setItem:(n,t)=>{},removeItem:n=>{}},U=st({storage:typeof window<"u"?window.localStorage:P,serialize:JSON.stringify,deserialize:JSON.parse});function st({storage:n,key:t=et,serialize:e,deserialize:s}){return {...n,getItem:(r,i=null)=>{let o=`${t}.${r.replace(`${t}.`,"")}`,a=n.getItem(o);if(!s)return a??i;try{return a?s(a):i}catch(d){return console.warn(d),i}},setItem:(r,i)=>{let o=`${t}.${r.replace(`${t}.`,"")}`;if(i===null)n.removeItem(o);else try{let a=e?e(i):i;n.setItem(o,a);}catch(a){console.error(a);}},removeItem:r=>n.removeItem(`${t}.${r}`)}}function b(n){return `[@micro-stacks/client] ${n}`}function l(n,t){nt(n,b(t));}var B=(s=>(s.ContractCall="contract_call",s.TokenTransfer="token_transfer",s.ContractDeploy="contract_deploy",s))(B||{}),L=(i=>(i.Authentication="status/Authentication",i.TransactionSigning="status/TransactionSigning",i.MessageSigning="status/MessageSigning",i.StructuredMessageSigning="status/StructuredMessageSigning",i.PsbtSigning="status/PsbtSigning",i))(L||{}),H=(e=>(e.IsLoading="status/IsLoading",e.IsIdle="status/IsIdle",e))(H||{}),M="store",C=typeof document>"u";var it=function(n){var t=n.match(/(?:([^:\/?#]+):)?(?:\/\/([^\/?#]*))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?/);return t};function A(n){if(!!n&&!/[^a-z0-9\:\/\?\#\[\]\@\!\$\&\'\(\)\*\+\,\;\=\.\-\_\~\%]/i.test(n)&&!/%[^0-9a-f]/i.test(n)&&!/%[0-9a-f](:?[^0-9a-f]|$)/i.test(n)){var t=[],e="",s="",r="",i="",o="",a="";if(t=it(n),e=t[1],s=t[2],r=t[3],i=t[4],o=t[5],!!(e&&e.length&&r.length>=0)){if(s&&s.length){if(!(r.length===0||/^\//.test(r)))return}else if(/^\/\//.test(r))return;if(!!/^[a-z][a-z0-9\+\-\.]*$/.test(e.toLowerCase()))return a+=e+":",s&&s.length&&(a+="//"+s),a+=r,i&&i.length&&(a+="?"+i),o&&o.length&&(a+="#"+o),a}}}var ot="(?<domain>([^?#]*)) wants you to sign in with your Stacks account:",at="\\n(?<address>S[A-Z0-9]{40})\\n\\n",ct="((?<statement>[^\\n]+)\\n)?",z="(([^:?#]+):)?(([^?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?",dt=`\\nURI: (?<uri>${z}?)`,ut="\\nVersion: (?<version>1)",lt="\\nChain ID: (?<chainId>[0-9]+)",ht="\\nNonce: (?<nonce>[a-zA-Z0-9]{8,})",O="([0-9]+)-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])[Tt]([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]|60)(.[0-9]+)?(([Zz])|([+|-]([01][0-9]|2[0-3]):[0-5][0-9]))",gt=`\\nIssued At: (?<issuedAt>${O})`,St=`(\\nExpiration Time: (?<expirationTime>${O}))?`,ft=`(\\nNot Before: (?<notBefore>${O}))?`,pt="(\\nRequest ID: (?<requestId>[-._~!$&'()*+,;=:@%a-zA-Z0-9]*))?",It=`(\\nResources:(?<resources>(\\n- ${z}?)+))?`,yt=`^${ot}${at}${ct}${dt}${ut}${lt}${ht}${gt}${St}${ft}${pt}${It}$`,w=class{domain;address;statement;uri;version;chainId;nonce;issuedAt;expirationTime;notBefore;requestId;resources;match;constructor(t){var r,i,o,a,d,u,S,h,c,g,v,D,K,V;let s=new RegExp(yt,"g").exec(t);if(!s)throw new Error("Message did not match the regular expression.");if(this.match=s,this.domain=(r=s==null?void 0:s.groups)==null?void 0:r.domain,this.domain.length===0||!/[^#?]*/.test(this.domain))throw new Error("Domain cannot be empty.");if(this.address=(i=s==null?void 0:s.groups)==null?void 0:i.address,!validateStacksAddress(this.address))throw new Error("Invalid address.");if(this.statement=(o=s==null?void 0:s.groups)==null?void 0:o.statement,this.uri=(a=s==null?void 0:s.groups)==null?void 0:a.uri,!A(this.uri))throw new Error("Invalid URI.");this.version=(d=s==null?void 0:s.groups)==null?void 0:d.version,this.nonce=(u=s==null?void 0:s.groups)==null?void 0:u.nonce,this.chainId=parseInt((S=s==null?void 0:s.groups)==null?void 0:S.chainId),this.issuedAt=(h=s==null?void 0:s.groups)==null?void 0:h.issuedAt,this.expirationTime=(c=s==null?void 0:s.groups)==null?void 0:c.expirationTime,this.notBefore=(g=s==null?void 0:s.groups)==null?void 0:g.notBefore,this.requestId=(v=s==null?void 0:s.groups)==null?void 0:v.requestId,this.resources=(K=(D=s==null?void 0:s.groups)==null?void 0:D.resources)==null?void 0:K.split(` - `).slice(1),((V=this.resources)==null?void 0:V.length)>0&&this.resources.forEach(F=>{if(!A(F))throw new Error(`${F} is not a valid resource.`)});}};var W=["signature","domain","nonce","time"],f=class{constructor(t,e,s){this.type=t,this.expected=e,this.received=s;}type;expected;received};var m=class{domain;address;statement;uri;version;chainId;nonce;issuedAt;expirationTime;notBefore;requestId;resources;constructor(t){typeof t=="string"&&(t=new w(t)),this.domain=t.domain,this.address=t.address,this.statement=t.statement,this.uri=t.uri,this.version=t.version,this.nonce=t.nonce,this.issuedAt=t.issuedAt,this.expirationTime=t.expirationTime,this.notBefore=t.notBefore,this.requestId=t.requestId,this.chainId=t.chainId,this.resources=t.resources,typeof this.chainId=="string"&&(this.chainId=parseInt(this.chainId)),this.validateMessage();}toMessage(){this.validateMessage();let t=`${this.domain} wants you to sign in with your Stacks account:`,e=`URI: ${this.uri}`,s=[t,this.address].join(` `),r=`Version: ${this.version}`,i="Chain ID: "+this.chainId||"1",o=`Nonce: ${this.nonce}`,a=[e,r,i,o];if(this.issuedAt&&Date.parse(this.issuedAt),this.issuedAt=this.issuedAt?this.issuedAt:new Date().toISOString(),a.push(`Issued At: ${this.issuedAt}`),this.expirationTime){let u=`Expiration Time: ${this.expirationTime}`;a.push(u);}this.notBefore&&a.push(`Not Before: ${this.notBefore}`),this.requestId&&a.push(`Request ID: ${this.requestId}`),this.resources&&a.push(["Resources:",...this.resources.map(u=>`- ${u}`)].join(` `));let d=a.join(` `);return s=[s,this.statement].join(` `),this.statement&&(s+=` `),[s,d].join(` `)}prepareMessage(){let t;switch(this.version){case"1":{t=this.toMessage();break}default:{t=this.toMessage();break}}return t}async verify(t){return new Promise(async(e,s)=>{Object.keys(t).forEach(c=>{W.includes(c)||s({success:!1,data:this,error:new Error(`${c} is not a valid key for VerifyParams.`)});});let r=c=>{s(c);},{signature:i,domain:o,nonce:a,time:d}=t;o&&o!==this.domain&&r({success:!1,data:this,error:new f("Domain do not match provided domain for verification.",o,this.domain)}),a&&a!==this.nonce&&r({success:!1,data:this,error:new f("Nonce do not match provided nonce for verification.",a,this.nonce)});let u=new Date(d||new Date);if(this.expirationTime){let c=new Date(this.expirationTime);u.getTime()>=c.getTime()&&r({success:!1,data:this,error:new f("Expired message.",`${u.toISOString()} < ${c.toISOString()}`,`${u.toISOString()} >= ${c.toISOString()}`)});}if(this.notBefore){let c=new Date(this.notBefore);u.getTime()<c.getTime()&&r({success:!1,data:this,error:new f("Message is not valid yet.",`${u.toISOString()} >= ${c.toISOString()}`,`${u.toISOString()} < ${c.toISOString()}`)});}let S;try{S=this.prepareMessage();}catch(c){r({success:!1,data:this,error:c});return}let h;try{let c=hashMessage(S),g=recoverSignature({signature:i}),v=getPublicKeyFromSignature({hash:c,signature:g.signature,recoveryBytes:g.recoveryBytes});verifyMessageSignature({signature:i,message:c})&&(h=publicKeyToStxAddress(v,c32addressDecode(this.address)[0]));}catch{}finally{h!==this.address&&r({success:!1,data:this,error:new f("Signature do not match address of the message.",h,`Resolved address to be ${this.address}`)});}e({success:!0,data:this});})}validateMessage(...t){var r;if(t.length>0)throw new f("Unable to parse the message.","Unexpected argument in the validateMessage function.");if(!this.domain||this.domain.length===0||!/[^#?]*/.test(this.domain))throw new f("Invalid domain.",`${this.domain} to be a valid domain.`);if(!validateStacksAddress(this.address))throw new f("Invalid address.",`${this.address} to be a valid address.`);if(!A(this.uri))throw new f("URI does not conform to RFC 3986.",`${this.uri} to be a valid uri.`);if(this.version!=="1")throw new f("Invalid message version.","1",this.version);let e=(r=this==null?void 0:this.nonce)==null?void 0:r.match(/[a-zA-Z0-9]{8,}/);if(!e||this.nonce.length<8||e[0]!==this.nonce)throw new f("Nonce size smaller then 8 characters or is not alphanumeric.",`Length > 8 (${e==null?void 0:e.length}). Alphanumeric.`,this.nonce);let s=/([0-9]+)-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])[Tt]([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]|60)(\.[0-9]+)?(([Zz])|([+|\-]([01][0-9]|2[0-3]):[0-5][0-9]))/;if(this.issuedAt&&!s.test(this.issuedAt))throw new Error("Invalid time format.");if(this.expirationTime&&!s.test(this.expirationTime))throw new Error("Invalid time format.");if(this.notBefore&&!s.test(this.notBefore))throw new Error("Invalid time format.")}};var y=1;function T({state:n,version:t}){var e,s,r;return JSON.stringify([[(e=n.network)==null?void 0:e.chainId,(r=(s=n.network)==null?void 0:s.getCoreApiUrl)==null?void 0:r.call(s)],[n.currentAccountIndex,n.accounts.map(i=>({appPrivateKey:i.appPrivateKey,address:c32address(i.address[0],hexToBytes(i.address[1])),profile_url:i.profile_url}))],t])}function Et(n){let t=JSON.parse(n),[e,s]=t[0],[r,i]=t[1],o=t[2]??y;return {network:e===ChainID.Mainnet?new StacksMainnet({url:s}):new StacksTestnet({url:s}),currentAccountIndex:r,accounts:i.map(d=>{let[u,S]=c32addressDecode(d.address);return {appPrivateKey:d.appPrivateKey,address:[u,bytesToHex(S)],profile_url:d.profile_url}}),version:o}}var _=n=>{if(n){if(typeof n!="string")return n;if(n==="testnet")return new StacksTestnet}return new StacksMainnet},k=({network:n=new StacksMainnet,...t})=>({statuses:{["status/Authentication"]:"status/IsIdle",["status/TransactionSigning"]:"status/IsIdle",["status/MessageSigning"]:"status/IsIdle",["status/StructuredMessageSigning"]:"status/IsIdle"},network:_(n),appName:t.appName,appIconUrl:t.appIconUrl,accounts:[],currentAccountIndex:0,onPersistState:t.onPersistState,onAuthentication:t.onAuthentication,onNoWalletFound:t.onNoWalletFound,onSignOut:t.onSignOut}),N=(n,t)=>{try{let{version:e,...s}=Et(n);return {state:{...k(t),...s},version:e}}catch{return {state:k(t),version:y}}},j=()=>{if(!getGlobalObject("localStorage",{throwIfUnavailable:!1}))return;let t=localStorage.getItem("MICRO_STACKS_DEBUG");if(t)return JSON.parse(t)};function Tt(n){if(!n)return null;let t=JSON.parse(n);return JSON.stringify([t[0],[t[1][0],t[1][1].map(e=>({...e,appPrivateKey:null}))],t[2]])}var x=class{config;storage;store;debug;fetcher;constructor(t={}){let e={storage:(t==null?void 0:t.storage)??U,network:(t==null?void 0:t.network)??new StacksMainnet,...t},s=typeof e.dehydratedState=="function"?e.dehydratedState(this.storeKey):e.dehydratedState,r=s?N(s,e):{state:k(e),version:y};this.store=Ht(subscribeWithSelector(persist(()=>r.state,{name:M,getStorage:()=>e.storage,version:r.version,serialize:({state:i,version:o})=>T({state:i,version:o??y}),deserialize:i=>N(i,e)}))),this.debug=j(),this.config=e,this.storage=e.storage,this.fetcher=e.fetcher||fetchPrivate;}getState=()=>this.store.getState();setState(t){let e=typeof t=="function"?t(this.store.getState()):t;this.store.setState(e,!0);}resetState(){this.setState(t=>({...t,accounts:[],currentAccountIndex:0}));}get subscribe(){return this.store.subscribe}onStorageUpdate=t=>{if(typeof document<"u"){let e=window.location.host,s=new URL(t.url).host,r=e===s,i=t.key==="micro-stacks.store";if(r&&i){let o=t.newValue;this.hydrate(JSON.parse(o));}}};tabSyncSubscription=t=>{let e=typeof document<"u";return e&&t&&window.addEventListener("storage",this.onStorageUpdate),()=>{e&&t&&window.removeEventListener("storage",this.onStorageUpdate);}};getStacksProvider(){return getGlobalObject("StacksProvider",{throwIfUnavailable:!1})}subscribeToStacksProvider(t,e=100){if(this.getStacksProvider())return t(),()=>{};{let s=setInterval(()=>{!!this.getStacksProvider()&&(t(),clearInterval(s));},e);return ()=>{typeof s<"u"&&clearInterval(s);}}}get storeKey(){return M}onPersistState=t=>{var e,s;return (s=(e=this.store.getState())==null?void 0:e.onPersistState)==null?void 0:s.call(e,t)};get onAuthentication(){var t;return (t=this.store.getState())==null?void 0:t.onAuthentication}get onNoWalletFound(){var t;return (t=this.store.getState())==null?void 0:t.onNoWalletFound}get onSignOut(){var t;return (t=this.store.getState())==null?void 0:t.onSignOut}setOnPersistState=t=>{this.setState(e=>({...e,onPersistState:t})),this.config.onPersistState=t;};setOnNoWalletFound=t=>{this.setState(e=>({...e,onNoWalletFound:t})),this.config.onPersistState=t;};setOnSignOut=t=>{this.setState(e=>({...e,onSignOut:t})),this.config.onSignOut=t;};setOnAuthentication=t=>{this.setState(e=>({...e,onAuthentication:t})),this.config.onAuthentication=t;};persist=async()=>{if(this.onPersistState){let t=this.dehydrate(this.store.getState());await this.onPersistState(t);}};dehydrate(t){return T({state:t??this.store.getState(),version:y})}hydrate(t){let e=N(t,this.config);this.setState(e.state);}selectHasSession=t=>Boolean(t.accounts.length);selectAccounts=t=>t.accounts;selectAccount=t=>this.selectHasSession(t)?t.accounts[t.currentAccountIndex]:void 0;selectNetwork=t=>this.config.enableNetworkSwitching?t.network:_(this.config.network);selectNetworkChain=t=>this.selectNetwork(t).chainId===ChainID.Mainnet?"mainnet":"testnet";selectTestnetStxAddress=t=>{let e=this.selectAccount(t);return e?c32address(e.address[0]===StacksNetworkVersion.mainnetP2SH?StacksNetworkVersion.testnetP2SH:StacksNetworkVersion.testnetP2PKH,hexToBytes(e.address[1])):void 0};selectMainnetStxAddress=t=>{let e=this.selectAccount(t);return e?c32address(e.address[0],hexToBytes(e.address[1])):void 0};selectStxAddress=t=>this.selectNetworkChain(t)==="mainnet"?this.selectMainnetStxAddress(t):this.selectTestnetStxAddress(t);selectAppDetails=t=>t.appName&&t.appIconUrl?{name:t.appName,icon:t.appIconUrl}:void 0;selectIdentityAddress=t=>{let e=this.selectAccount(t);return e!=null&&e.appPrivateKey?privateKeyToBase58Address(e.appPrivateKey):void 0};selectDecentralizedID=t=>{let e=this.selectIdentityAddress(t);return e?`did:btc-addr:${e}`:void 0};selectStatuses=t=>t.statuses;setStatus(t,e){this.setState(s=>({...s,statuses:{...s.statuses,[t]:e}}));}setIsRequestPending(t){this.setStatus(t,"status/IsLoading");}setIsIdle(t){this.setStatus(t,"status/IsIdle");}statuses=()=>this.selectStatuses(this.getState());isSignMessageRequestPending=()=>this.statuses()["status/MessageSigning"];isSignStructuredMessageRequestPending=()=>this.statuses()["status/StructuredMessageSigning"];handleNoStacksProviderFound(){return typeof this.getStacksProvider()>"u"?typeof this.onNoWalletFound<"u"?(this.onNoWalletFound(),!1):(l(this.getStacksProvider(),"The injected `StacksProvider` cannot be found. This is typically because there is no Stacks wallet available, such as the Hiro web wallet extension or the iOS/Android wallet Xverse."),!1):!0}authenticate=async t=>{if(!this.handleNoStacksProviderFound())return;let e=this.selectAppDetails(this.getState());l(e,"App details are not defined for you app. Most functionality (authentication, signing requests) require details be passed to the wallet. Add them to your MicroStacksClient config.");let s=this.selectAccounts(this.getState());this.setIsRequestPending("status/Authentication"),await authenticate({appDetails:e,onFinish:async({profile:r,...i})=>{var S,h;let[o,a]=c32addressDecode(i.addresses.mainnet),d=[o,bytesToHex(a)];s.find(c=>c.address===d)?this.setState(c=>({...c,currentAccountIndex:s.findIndex(g=>g.address===d)})):this.setState(c=>{var g;return {...c,accounts:c.accounts.concat({address:d,appPrivateKey:(g=this.debug)!=null&&g.disableAppPrivateKey?void 0:i.appPrivateKey,decentralizedID:i.decentralizedID,profile_url:i.profile_url}),currentAccountIndex:c.accounts.length}}),(S=t==null?void 0:t.onFinish)==null||S.call(t,i),(h=this.onAuthentication)==null||h.call(this,{profile:r,...i}),await this.persist(),this.setIsIdle("status/Authentication");},onCancel:r=>{var i;this.setIsIdle("status/Authentication"),(i=t==null?void 0:t.onCancel)==null||i.call(t,r);}},P);};signOut=async t=>{var e,s,r,i;return (r=(s=(e=this.store)==null?void 0:e.persist)==null?void 0:s.clearStorage)==null||r.call(s),(i=this.onSignOut)==null||i.call(this),this.resetState(),t==null?void 0:t()};getSignInMessage=({domain:t,nonce:e,version:s="1",statement:r="Sign in with Stacks"})=>{if(!this.handleNoStacksProviderFound())return;let i=this.getState(),o=this.selectAppDetails(i),a=this.selectStxAddress(i);l(o,"App details are not defined for you app. Most functionality (authentication, signing requests) require details be passed to the wallet. Add them to your MicroStacksClient config."),l(a,"No current Stacks address can be found. This could be because a session has been invalidated, or the user is not signed in.");let d=getGlobalObject("document",{throwIfUnavailable:!1})?window.location.origin:"";return new m({domain:o.name,address:a,statement:r,uri:t??d,version:s,chainId:ChainID.Mainnet,nonce:e})};signTransaction=async(t,e)=>{if(!this.handleNoStacksProviderFound())return;let s=this.getState(),r=this.selectAppDetails(s),i=this.selectStxAddress(s),o=this.selectAccount(s),a=this.selectNetwork(s);l(r,"App details are not defined for you app. Most functionality (authentication, signing requests) require details be passed to the wallet. Add them to your MicroStacksClient config."),l(i,"No current Stacks address can be found. This could be because a session has been invalidated, or the user is not signed in."),l(o,"There is not current user session available. Please make sure the user has signed in before attempting this action."),this.setIsRequestPending("status/TransactionSigning");let d,u={privateKey:o.appPrivateKey,appDetails:r,stxAddress:i,network:a,postConditionMode:e.postConditionMode,postConditions:e.postConditions,attachment:e.attachment,sponsored:e.sponsored},h=await(t==="token_transfer"?makeStxTransferToken:t==="contract_call"?makeContractCallToken:makeContractDeployToken)({...u,...e});return l(h,"Transaction JWT could not be created"),await openTransactionPopup({token:h,onFinish:c=>{var g;d=c,(g=e==null?void 0:e.onFinish)==null||g.call(e,c),this.setIsIdle("status/TransactionSigning");},onCancel:c=>{var g;(g=e==null?void 0:e.onCancel)==null||g.call(e,c),this.setIsIdle("status/TransactionSigning");}}),d};signPSBT=async t=>{if(!this.handleNoStacksProviderFound())return;let e=this.getState(),s=this.selectAppDetails(e),r=this.selectStxAddress(e),i=this.selectAccount(e),o=this.selectNetwork(e);l(s,"App details are not defined for you app. Most functionality (authentication, signing requests) require details be passed to the wallet. Add them to your MicroStacksClient config."),l(r,"No current Stacks address can be found. This could be because a session has been invalidated, or the user is not signed in."),l(i,"There is not current user session available. Please make sure the user has signed in before attempting this action."),l(t.hex,"No hex found -- a hex string is required when requesting a PSBT signature."),this.setIsRequestPending("status/PsbtSigning");let a;return await handlePSBTRequest({appDetails:s,privateKey:i.appPrivateKey,stxAddress:r,network:o,allowedSighash:t.allowedSighash,hex:t.hex,signAtIndex:t.signAtIndex,onFinish:d=>{var u;a=d,(u=t==null?void 0:t.onFinish)==null||u.call(t,d),this.setIsIdle("status/PsbtSigning");},onCancel:()=>{var d;(d=t==null?void 0:t.onCancel)==null||d.call(t),this.setIsIdle("status/PsbtSigning");}}),a};signMessage=async t=>{if(!this.handleNoStacksProviderFound())return;let e=this.getState(),s=this.selectAppDetails(e),r=this.selectStxAddress(e),i=this.selectAccount(e),o=this.selectNetwork(e);l(s,"App details are not defined for you app. Most functionality (authentication, signing requests) require details be passed to the wallet. Add them to your MicroStacksClient config."),l(r,"No current Stacks address can be found. This could be because a session has been invalidated, or the user is not signed in."),l(i,"There is not current user session available. Please make sure the user has signed in before attempting this action."),l(t.message,"No message found -- a message is required when requesting a message signature."),this.setIsRequestPending("status/MessageSigning");let a;return await handleSignMessageRequest({appDetails:s,privateKey:i.appPrivateKey,stxAddress:r,network:o,message:t.message,onFinish:d=>{var u;a=d,(u=t==null?void 0:t.onFinish)==null||u.call(t,d),this.setIsIdle("status/MessageSigning");},onCancel:d=>{var u;(u=t==null?void 0:t.onCancel)==null||u.call(t,d),this.setIsIdle("status/MessageSigning");}}),a};signStructuredMessage=async t=>{var d,u,S;if(!this.handleNoStacksProviderFound())return;let e=this.getState(),s=this.selectAppDetails(e),r=this.selectStxAddress(e),i=this.selectAccount(e),o=this.selectNetwork(e);l(s,"App details are not defined for you app. Most functionality (authentication, signing requests) require details be passed to the wallet. Add them to your MicroStacksClient config."),l(r,"No current Stacks address can be found. This could be because a session has been invalidated, or the user is not signed in."),l(i,"There is not current user session available. Please make sure the user has signed in before attempting this action."),l(t.message,"No message found -- a message is required when requesting a message signature."),this.setIsRequestPending("status/StructuredMessageSigning");let a;return await handleSignStructuredDataRequest({appDetails:s,privateKey:i.appPrivateKey,stxAddress:r,network:o,domain:{name:((d=t.domain)==null?void 0:d.name)??s.name,version:((u=t.domain)==null?void 0:u.version)??"1.0.0",chainId:((S=t.domain)==null?void 0:S.chainId)??o.chainId},message:t.message,onFinish:h=>{var c;a=h,(c=t==null?void 0:t.onFinish)==null||c.call(t,h),this.setIsIdle("status/StructuredMessageSigning");},onCancel:h=>{var c;(c=t==null?void 0:t.onCancel)==null||c.call(t,h),this.setIsIdle("status/StructuredMessageSigning");}}),a};setNetwork=t=>{if(!this.config.enableNetworkSwitching)throw new Error(b("Network switching is currently disabled. Set `enableNetworkSwitching` to `true` to enable."));typeof t=="string"?this.setState(s=>({...s,network:t==="mainnet"?new StacksMainnet:new StacksTestnet})):this.setState(s=>({...s,network:t})),this.persist();};selectGaiaHubConfig(t){let e=this.selectHasSession(t),s=this.selectAccount(t);if(!(!e||!(s!=null&&s.appPrivateKey)))return generateGaiaHubConfigSync({gaiaHubUrl:"https://hub.blockstack.org",privateKey:s.appPrivateKey})}putFile=(t,e,{encrypt:s=!0,sign:r})=>{let i=this.selectHasSession(this.getState()),o=this.selectGaiaHubConfig(this.getState()),a=this.selectAccount(this.getState());if(!i){console.warn("There is not current user session available. Please make sure the user has signed in before attempting this action.");return}if(!(a!=null&&a.appPrivateKey)||!o){console.warn("The current user session has no `appPrivateKey` defined. Certain actions require an `appPrivateKey`, such as using gaia or encryption.");return}return putFile(t,e,{privateKey:a.appPrivateKey,gaiaHubConfig:o,encrypt:s,sign:r,wasString:typeof e=="string"})};getFile=(t,{decrypt:e=!0,verify:s})=>{let r=this.selectHasSession(this.getState()),i=this.selectGaiaHubConfig(this.getState()),o=this.selectAccount(this.getState());if(!r){console.warn("There is not current user session available. Please make sure the user has signed in before attempting this action.");return}if(!(o!=null&&o.appPrivateKey)||!i){console.warn("The current user session has no `appPrivateKey` defined. Certain actions require an `appPrivateKey`, such as using gaia or encryption.");return}return getFile(t,{privateKey:o.appPrivateKey,gaiaHubConfig:i,decrypt:e,verify:s})};async fetchBNSName(){var r;let t=this.selectStxAddress(this.getState()),e=this.selectNetwork(this.getState());if(!t){console.warn("No Stacks address found while trying to fetch BNS name");return}let s=e.getCoreApiUrl()+`/v1/addresses/stacks/${t}`;try{let o=await(await this.fetcher(s)).json();return (r=o==null?void 0:o.names)==null?void 0:r[0]}catch(i){console.log("[@micro-stacks/client] fetchBNSName failed",i);}}async fetchZoneFile(){try{let t=this.selectStxAddress(this.getState()),e=this.selectNetwork(this.getState());if(!t){console.warn("No Stacks address found while trying to fetch zonefile name");return}let s=e.getCoreApiUrl()+`/v1/names/${t}/zonefile`;return await(await this.fetcher(s)).json()}catch(t){console.log("[@micro-stacks/client] fetchZoneFile failed",t);}}async fetchProfile(){let t=this.selectAccount(this.getState());if(!!(t!=null&&t.profile_url))try{return await(await this.fetcher(t.profile_url)).json()}catch(e){console.log("[@micro-stacks/client] fetchProfile failed",e);}}encrypt(t,e={}){var s;if((e==null?void 0:e.publicKey)&&(e==null?void 0:e.privateKey))throw Error("Error: do not pass both `publicKey` and `privateKey` to client.encrypt");return encryptContent(t,{...e,privateKey:e.privateKey??((s=this.selectAccount(this.getState()))==null?void 0:s.appPrivateKey)})}decrypt(t,e){var r;let s=e.privateKey??((r=this.selectAccount(this.getState()))==null?void 0:r.appPrivateKey);if(!s)throw Error("You must pass a `privateKey` value to client.decrypt");return decryptContent(t,{privateKey:s})}};var $;function tt(n){let t=(n==null?void 0:n.client)??new x(n==null?void 0:n.config);return C?t:($=t,$)}function p(n){return C?tt(n):$??tt(n)}var Be=({client:n,state:t})=>n.selectAccounts(t||n.getState()),Le=({client:n,state:t})=>n.selectAccount(t||n.getState()),He=({client:n,state:t})=>n.selectStxAddress(t||n.getState()),qe=({client:n,state:t})=>n.selectIdentityAddress(t||n.getState()),ze=({client:n,state:t})=>n.selectDecentralizedID(t||n.getState()),We=({client:n,state:t})=>n.selectNetwork(t||n.getState()),Ge=({client:n,state:t})=>n.selectStatuses(t||n.getState()),je=({client:n,state:t})=>n.selectAppDetails(t||n.getState()),Je=(n,t=p())=>t.subscribe(t.selectAccounts,n,{equalityFn:I}),Ze=(n,t=p())=>t.subscribe(t.selectAccount,n,{equalityFn:I}),Xe=(n,t=p())=>t.subscribe(t.selectStxAddress,n,{equalityFn:I}),Ye=(n,t=p())=>t.subscribe(t.selectIdentityAddress,n,{equalityFn:I}),Qe=(n,t=p())=>t.subscribe(t.selectDecentralizedID,n,{equalityFn:I}),ts=(n,t=p())=>t.subscribe(t.selectNetwork,n,{equalityFn:I}),es=(n,t=p())=>t.subscribe(t.selectStatuses,n,{equalityFn:I}),ss=(n,t=p())=>t.subscribe(t.selectAppDetails,n,{equalityFn:I}); export { et as DEFAULT_PREFIX, C as IS_SSR, x as MicroStacksClient, M as STORE_KEY, m as SignInWithStacksMessage, H as Status, L as StatusKeys, B as TxType, Tt as cleanDehydratedState, $ as client, tt as createClient, st as createStorage, U as defaultStorage, Be as getAccounts, je as getAppDetails, p as getClient, Le as getCurrentAccount, ze as getDecentralizedID, qe as getIdentityAddress, We as getNetwork, Ge as getStatus, He as getStxAddress, P as noopStorage, Je as watchAccounts, ss as watchAppDetails, Ze as watchCurrentAccount, Qe as watchDecentralizedID, Ye as watchIdentityAddress, ts as watchNetwork, es as watchStatus, Xe as watchStxAddress };