🚀 Big News: Socket Acquires Coana to Bring Reachability Analysis to Every Appsec Team.Learn more
Socket
Sign inDemoInstall
Socket

@xmtp/react-sdk

Package Overview
Dependencies
Maintainers
0
Versions
85
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@xmtp/react-sdk - npm Package Compare versions

Comparing version

to
9.0.0

6

lib/index.d.ts

@@ -583,3 +583,3 @@ import * as _xmtp_xmtp_js from '@xmtp/xmtp-js';

allow: (addresses: string[], skipPublish?: boolean) => Promise<void>;
consentState: (address: string) => Promise<_xmtp_xmtp_js.ConsentState>;
consentState: (address: string) => Promise<ConsentState>;
deny: (addresses: string[], skipPublish?: boolean) => Promise<void>;

@@ -589,4 +589,4 @@ entries: Partial<CachedConsentEntryMap>;

isDenied: (address: string) => Promise<boolean>;
loadConsentList: (startTime?: Date) => Promise<_xmtp_xmtp_js.ConsentListEntry[]>;
refreshConsentList: () => Promise<_xmtp_xmtp_js.ConsentListEntry[]>;
loadConsentList: (startTime?: Date) => Promise<Map<string, ConsentState>>;
refreshConsentList: () => Promise<Map<string, ConsentState>>;
};

@@ -593,0 +593,0 @@

@@ -1,2 +0,2 @@

import{jsx as e}from"react/jsx-runtime";import{createContext as t,useState as n,useRef as s,useMemo as a,useContext as r,useCallback as o,useEffect as c}from"react";import i from"dexie";import{ContentTypeText as d}from"@xmtp/content-type-text";import{decodeContent as l,ConsentListEntry as u,Client as w,SortDirection as p}from"@xmtp/xmtp-js";export{Client,Compression,SortDirection}from"@xmtp/xmtp-js";import{isAfter as y,min as m,subSeconds as g}from"date-fns";import{v4 as v}from"uuid";import{Mutex as f}from"async-mutex";import{useLiveQuery as h}from"dexie-react-hooks";import{AttachmentCodec as A,RemoteAttachmentCodec as b,ContentTypeAttachment as T,ContentTypeRemoteAttachment as M}from"@xmtp/content-type-remote-attachment";import{z as E}from"zod";import{ReactionCodec as D,ContentTypeReaction as I}from"@xmtp/content-type-reaction";import{ContentTypeId as S}from"@xmtp/content-type-primitives";import{ReplyCodec as C,ContentTypeReply as x}from"@xmtp/content-type-reply";const X={codecs:[],contentTypes:[d.toString()],namespace:"text",validators:{[d.toString()]:e=>"string"==typeof e}},P=e=>{const t=new i("__XMTP2__");t.isOpen()&&t.close();const n=e?.reduce(((e,{schema:t})=>({...e,...t})),{});return t.version(1).stores({...n,conversations:"\n topic,\n [walletAddress+topic],\n [walletAddress+peerAddress],\n createdAt,\n peerAddress,\n updatedAt,\n walletAddress\n ",messages:"\n id,\n [conversationTopic+walletAddress],\n contentFallback,\n contentType,\n conversationTopic,\n senderAddress,\n sentAt,\n status,\n uuid,\n walletAddress\n ",consent:"\n [walletAddress+type+value],\n type,\n value,\n state,\n walletAddress\n "}),t};let L;const q=async e=>{let t,n=!1;try{const e=new i("__XMTP__");await e.open(),n=!0,e.close()}catch{}if(!n)return P(e?.contentTypeConfigs);if(L){return await L}L=new Promise((e=>{t=e}));const s=(()=>{const e=new i("__XMTP__");return e.isOpen()&&e.close(),e.version(1).stores({reactions:"\n ++id,\n [content+referenceXmtpID+schema+senderAddress],\n referenceXmtpID,\n content,\n schema,\n senderAddress,\n sentAt,\n xmtpID\n ",replies:"\n ++id,\n [referenceXmtpID+xmtpID],\n referenceXmtpID,\n xmtpID\n ",conversations:"\n ++id,\n [walletAddress+topic],\n [walletAddress+peerAddress],\n createdAt,\n peerAddress,\n topic,\n updatedAt,\n walletAddress\n ",messages:"\n ++id,\n [conversationTopic+walletAddress],\n contentFallback,\n contentType,\n conversationTopic,\n senderAddress,\n sentAt,\n status,\n uuid,\n walletAddress,\n xmtpID\n ",consent:"\n [walletAddress+peerAddress],\n peerAddress,\n state,\n walletAddress\n "}),e})(),a=P(e?.contentTypeConfigs),r=await s.table("conversations").toArray();await a.table("conversations").bulkAdd(r.map((e=>(delete e.id,e))));const o=await s.table("messages").toArray();await a.table("messages").bulkAdd(o.map((e=>{const t=e.xmtpID;return delete e.xmtpID,{...e,id:t}})));const c=await s.table("consent").toArray();await a.table("consent").bulkAdd(c.map((e=>({type:"address",value:e.peerAddress,state:e.state,walletAddress:e.walletAddress}))));const d=await s.table("reactions").toArray();d.length>0&&await a.table("reactions").bulkAdd(d.map((e=>{const t=e.xmtpID;return delete e.xmtpID,{...e,id:t}})));const l=await s.table("replies").toArray();return l.length>0&&await a.table("replies").bulkAdd(l),s.close(),await s.delete(),t?.(a),a},k=async e=>{await Promise.all(e.tables.map((e=>e.clear())))},B=[X],O=t({codecs:[],contentTypeConfigs:[],dbRef:{current:null},namespaces:{},processors:{},setClient:()=>{},validators:{}}),_=({children:t,client:r,contentTypeConfigs:o})=>{const[c,i]=n(r),d=s(null),l=a((()=>(e=>({...[...B,...e??[]].reduce(((e,t)=>{const n=Object.entries(t.processors??[]).reduce(((t,[n,s])=>({...t,[n]:[...e[n]??[],...s]})),{});return{...e,...n}}),{})}))(o??[])),[o]),u=a((()=>(e=>[...B,...e??[]].reduce(((e,t)=>[...e,...t.codecs??[]]),[]))(o??[])),[o]),w=a((()=>(e=>{const t=[...B,...e??[]],n=[];return t.reduce(((e,t)=>{if(n.includes(t.namespace))throw new Error(`Duplicate content types config namespace detected: "${t.namespace}"`);return n.push(t.namespace),{...e,...(t.contentTypes??[]).reduce(((e,n)=>({...e,[n]:t.namespace})),{})}}),{})})(o??[])),[o]),p=a((()=>(e=>{const t=[...B,...e??[]],n=[];return t.reduce(((e,t)=>{const s={};return Object.entries(t.validators??{}).forEach((([e,t])=>{if(n.includes(e))throw new Error(`Duplicate content validator detected for content type "${e}"`);n.push(e),s[e]=t})),{...e,...s}}),{})})(o??[])),[o]),y=a((()=>({client:c,codecs:u,contentTypeConfigs:o??[],dbRef:d,namespaces:w,processors:l,setClient:i,validators:p})),[c,u,o,w,l,p]);return e(O.Provider,{value:y,children:t})},j=e=>e.startsWith("0x")&&42===e.length,R=async(e,t,n,s)=>{const a=s.table("conversations");return await a.where({walletAddress:e,[t]:n}).first()},F=async(e,t,n)=>R(e,"topic",t,n),U=async(e,t,n)=>R(e,"peerAddress",t,n),N=async(e,t)=>{let n;return(await t.conversations.listFromCache()).some((t=>t.topic===e&&(n=t,!0))),n},z=async(e,t,n)=>{const s=n.table("conversations"),a=await s.where("topic").equals(e).first();a&&await s.update(a,t)},G=async(e,t,n,s,a)=>{const r=await F(e,t,a);if(r){const e=r.metadata||{};e[n]=s,await z(t,{metadata:e},a)}},$=async(e,t,n)=>{await z(e,{updatedAt:t},n)},K=async(e,t,n)=>!!await F(e,t,n),W=(e,t)=>({context:e.context,createdAt:e.createdAt,isReady:!1,peerAddress:e.peerAddress,topic:e.topic,updatedAt:e.createdAt,walletAddress:t}),H=new f,J=async(e,t)=>H.runExclusive((async()=>{const n=t.table("conversations"),s=await n.where({walletAddress:e.walletAddress,topic:e.topic}).first();return s||(await n.add(e),e)})),Q=(e,t)=>{const n=void 0!==e.content;return{content:e.content,contentBytes:n?void 0:e.contentBytes,contentFallback:e.contentFallback,contentType:e.contentType.toString(),conversationTopic:e.contentTopic,status:"unprocessed",hasLoadError:!1,hasSendError:!1,id:e.id,isSending:!1,senderAddress:e.senderAddress,sentAt:e.sent,uuid:v(),walletAddress:t}},V=async(e,t)=>{const n=t.table("messages");return await n.where("id").equals(e).first()},Y=async(e,t)=>{const n=t.table("messages"),s=await V(e.id,t);if(s)return s;const a=await n.add(e);return{...e,id:a}},Z=async(e,t)=>{const n=t.table("messages");await n.where("id").equals(e.id).first()&&await n.delete(e.id)},ee=async(e,t,n)=>{const s=n.table("messages");return await s.update(e,t),{...e,...t}},te=async(e,t,n,s)=>{const a=e.metadata||{};return a[t]=n,ee(e,{metadata:a},s)},ne=[],se=async({client:e,conversation:t,db:n,message:s,namespaces:a,processors:r,validators:o},c=!1)=>{if(!e)return{status:"no_client",message:s};if(ne.includes(s.id))return{status:"queued",message:s};ne.push(s.id);const i=a[s.contentType];try{const a=await V(s.id,n);if(a&&"processed"===a.status)return{status:"duplicate",message:s};const d=o[s.contentType];if(d&&!d(s.content))return{status:"invalid",message:s};const l=async s=>{await G(e.address,t.topic,i,s,n)};if(void 0===s.content)return{status:"unsupported",message:a?s:await Y(s,n)};c&&a&&await Z(a,n),r[s.contentType]&&await Promise.all(r[s.contentType].map((a=>a({client:e,conversation:t,db:n,message:s,processors:r,updateConversationMetadata:l}))));const u=await Y(s,n);!s.isSending&&y(s.sentAt,t.updatedAt)&&await $(t.topic,s.sentAt,n);return{status:"processed",message:await ee(u,{status:"processed"},n)}}finally{const e=ne.indexOf(s.id);e>-1&&ne.splice(e,1)}},ae=async({client:e,conversation:t,db:n,message:s,namespaces:a,processors:r,validators:o,process:c=se,decode:i=l})=>{if(void 0===s.content&&s.contentBytes&&e&&r[s.contentType]){const d=await i(s.contentBytes,e);return void 0===d.content?s:c({conversation:t,client:e,db:n,message:{...s,content:d.content,contentBytes:void 0},namespaces:a,processors:r,validators:o},!0)}return s},re=async(e,t)=>{const n=t.table("messages");return(await n.where({conversationTopic:e}).reverse().sortBy("sentAt"))[0]},oe=async(e,t,n,s)=>s.table("consent").where({walletAddress:e,type:t,value:n}).first(),ce=async(e,t)=>{const n=t.table("consent");return(await n.where({walletAddress:e}).toArray()).map((e=>u.fromAddress(e.value,e.state)))},ie=async(e,t)=>{const n=await ce(e,t);return n.length?Object.fromEntries(n.map((e=>[e.value,e]))):{}},de=async(e,t,n,s)=>{const a=await oe(e,t,n,s);return a?.state??"unknown"},le=async(e,t)=>{const n=await ce(e.address,t);e.contacts.setConsentListEntries(n)},ue=new f,we=async(e,t,n,s,a)=>ue.runExclusive((async()=>{const r=a.table("consent");await r.put({type:t,value:n,state:s,walletAddress:e})})),pe=async(e,t)=>ue.runExclusive((async()=>{const n=t.table("consent");await n.bulkPut(e)})),ye=()=>{const e=r(O),{contentTypeConfigs:t,dbRef:n}=e,s=o((async()=>(n.current||(n.current=await q({contentTypeConfigs:t})),n.current)),[t,n]);return{clearCache:o((async()=>{const e=await s();await k(e)}),[s]),getDbInstance:s}},me=e=>{const[t,a]=n(!1),[c,i]=n(null),d=s(!1),{getDbInstance:l}=ye(),{client:u,setClient:p,codecs:y,processors:m,namespaces:g,validators:v}=r(O),f=o((async({keys:t,options:n,signer:s})=>{if(!u&&(s||t)){if(d.current)return;let r;d.current=!0,i(null),a(!0);try{r=await w.create(s??null,{...n,codecs:y,privateKeyOverride:t}),p(r)}catch(t){throw p(void 0),i(t),e?.(t),t}finally{d.current=!1}a(!1);const o=await l();try{await le(r,o)}catch(t){e?.(t)}try{await(async({client:e,db:t,namespaces:n,processors:s,validators:a,reprocess:r=ae})=>{const o=await(async e=>{const t=e.table("messages");return await t.where({status:"unprocessed"}).toArray()})(t);await Promise.all(o.map((async o=>{const c=await F(e.address,o.conversationTopic,t);c&&await r({conversation:c,client:e,db:t,message:o,namespaces:n,processors:s,validators:a})})))})({client:r,db:o,processors:m,namespaces:g,validators:v})}catch(t){e?.(t)}return d.current=!1,r}return u}),[u,y,l,g,e,m,p,v]),h=o((async()=>{u&&(await u.close(),p(void 0))}),[u,p]);return{client:u,disconnect:h,error:c,initialize:f,isLoading:t}},ge=()=>{const{client:e}=me(),{getDbInstance:t}=ye();return{saveConversation:o((async n=>{if(!e)return;const s=await t();return J(n,s)}),[e,t]),updateConversation:o((async(e,n)=>{const s=await t();await z(e,n,s)}),[t]),updateMetadata:o((async(n,s,a)=>{if(e){const r=await t();await G(e.address,n,s,a,r)}}),[e,t])}},ve=()=>{const{client:e}=me(),{getDbInstance:t}=ye();return{getByTopic:o((async t=>e?N(t,e):void 0),[e]),getCachedByTopic:o((async n=>{if(!e)return;const s=await t();return F(e.address,n,s)}),[e,t]),getCachedByPeerAddress:o((async n=>{if(!e)return;const s=await t();return U(e.address,n,s)}),[e,t]),getLastMessage:o((async e=>{const n=await t();return re(e,n)}),[t]),hasConversationTopic:o((async n=>{if(!e)return!1;const s=await t();return K(e.address,n,s)}),[e,t])}},fe=()=>{const e=r(O),{processors:t,namespaces:n,validators:s}=e,{client:a}=me(),{getDbInstance:c}=ye(),i=o((async(e,r)=>{const o=await c();return se({client:a,conversation:e,db:o,message:r,namespaces:n,processors:t,validators:s})}),[a,c,n,t,s]),l=o((async(e,t)=>{const n=await c();return ee(e,t,n)}),[c]),u=o((async(e,t)=>(async(e,t,n)=>ee(e,{hasSendError:!1,isSending:!1,sendOptions:void 0,sentAt:t},n))(e,t,await c())),[c]),w=o((async e=>{const t=await c();return V(e,t)}),[c]),p=o((async e=>{const t=await c();return Z(e,t)}),[c]),y=o((async(e,t,n,s)=>{if(!a)throw new Error("XMTP client is required to send a message");if(void 0===t)throw new Error("Message content is required to send a message");const{onSuccess:r,onError:o,...w}=s??{},p={...w,contentType:n??d};try{const{message:n,preparedMessage:s}=await(async({client:e,content:t,conversation:n,sendOptions:s})=>{const a=await N(n.topic,e);if(!a)throw new Error("Conversation not found in XMTP client, unable to prepare message");const r=await a.prepareMessage(t,s),o=new Date;return{message:{content:t,contentType:s?.contentType?.toString()??d.toString(),conversationTopic:n.topic,hasLoadError:!1,hasSendError:!1,id:await r.messageID(),isSending:!0,senderAddress:e.address,sentAt:o,status:"unprocessed",uuid:v(),walletAddress:e.address},preparedMessage:r}})({client:a,content:t,conversation:e,sendOptions:p}),{status:o,message:w}=await i(e,n);switch(o){case"invalid":throw new Error("Unable to send message: content is invalid");case"duplicate":throw new Error("Unable to send message: message is a duplicate")}if("processed"===o)try{const t=await c(),n=await s.send();return await $(e.topic,n.sent,t),r?.(n),w.id&&await u(w,n.sent),{cachedMessage:w,sentMessage:n}}catch(e){throw w.id&&await l(w,{hasSendError:!0,sendOptions:p}),e}return{cachedMessage:w}}catch(e){throw o?.(e),e}}),[a,c,i,l,u]),m=o((async e=>{if(!e.hasSendError)throw new Error("Resending a message that hasn't failed to send is not allowed");if(!a)throw new Error("XMTP client is required to send a message");const t=await N(e.conversationTopic,a);if(!t){throw new Error("Conversation not found in XMTP client, unable to send message")}const n=await t.send(e.content,e.sendOptions),s=await c();return await $(t.topic,n.sent,s),await u(e,n.sent),n}),[a,c,u]);return{deleteMessage:p,getMessageByXmtpID:w,processMessage:i,resendMessage:m,sendMessage:y,updateMessage:l}},he=e=>{const[t,a]=n(!1),[r,o]=n(!1),[i,d]=n(null),{client:l}=me(),{processMessage:u}=fe(),{saveConversation:w}=ge(),{hasConversationTopic:y}=ve(),m=(()=>{const{getDbInstance:e}=ye(),{client:t}=me();return h((async()=>t?(await e()).table("conversations").where("walletAddress").equals(t.address).reverse().sortBy("updatedAt"):[]),[t?.address])??[]})(),g=s(!1),{onConversations:v,onError:f}=e??{};return c((()=>{if(!l){const e=new Error("XMTP client is required to fetch conversations");return d(e),void f?.(e)}(async()=>{if(!g.current){g.current=!0,a(!0),o(!1),d(null);try{const e=await l.conversations.list()??[];await Promise.all(e.map((async e=>{if(!await y(e.topic)){const t=await w(W(e,l.address)),n=await e.messages({direction:p.SORT_DIRECTION_DESCENDING,limit:1});if(n.length>0&&t){const e=n[0];await u(t,Q(e,l.address))}}}))),o(!0),v?.(e)}catch(e){throw d(e),f?.(e),e}finally{a(!1),g.current=!1}}})()}),[l,y,v,f,u,w]),{conversations:m,error:i,isLoaded:r,isLoading:t}},Ae=e=>{const[t,s]=n(!1),[a,r]=n(null),{client:c}=me(),{sendMessage:i}=fe(),{saveConversation:d}=ge(),{conversationId:l,metadata:u,onError:w}=e??{};return{error:a,isLoading:t,startConversation:o((async(e,t,n,a)=>{if(void 0===c){const e=new Error("XMTP client is required to start a conversation");return r(e),w?.(e),{cachedConversation:void 0,cachedMessage:void 0,conversation:void 0}}s(!0),r(null);try{const s=await c.conversations.newConversation(e,l&&u?{conversationId:l,metadata:u}:void 0),r=await d(W(s,c.address));if(!r)return{cachedConversation:void 0,cachedMessage:void 0,conversation:s};if(void 0===t)return{cachedConversation:r,cachedMessage:void 0,conversation:s};const{cachedMessage:o}=await i(r,t,n,a);return{cachedConversation:r,cachedMessage:o,conversation:s}}catch(e){throw r(e),w?.(e),e}finally{s(!1)}}),[i,c,l,u,w,d])}},be=e=>{const[t,a]=n(null),r=s(void 0),o=s((async e=>{r.current&&(r.current=void 0),void 0!==e&&(await e).return()})),{client:i}=me(),{saveConversation:d}=ge(),{onConversation:l,onError:u}=e??{};return c((()=>{let e=r.current;const t=o.current;return(async()=>{if(!r.current){if(void 0===i){const e=new Error("XMTP client is not available");return a(e),void u?.(e)}try{if(r.current)return;r.current=i.conversations.stream(),e=r.current;for await(const t of await e)await d(W(t,i.address)),l?.(t)}catch(n){throw a(n),u?.(n),t(e),n}}})(),()=>{t(e)}}),[i,d,u,l]),{error:t}},Te=e=>{const{getDbInstance:t}=ye();return h((async()=>{const n=(await t()).table("messages");return(await n.where({conversationTopic:e}).reverse().sortBy("sentAt")).filter((e=>void 0!==e.content))[0]}),[e])},Me=e=>{const[t,s]=n(!1),[a,r]=n(null),{client:c}=me();return{error:a,isLoading:t,canMessage:o((async t=>{if(!c)throw new Error("XMTP client is required to check if an address is on the network");s(!1),r(null);try{return await c.canMessage(t)}catch(t){throw r(t),e?.(t),t}finally{s(!1)}}),[c,e]),canMessageStatic:o((async(t,n)=>{s(!1),r(null);try{return await w.canMessage(t,n)}catch(t){throw r(t),e?.(t),t}finally{s(!1)}}),[e])}},Ee=(e,t)=>{const[a,r]=n(!1),[i,d]=n(!1),[l,u]=n(null),{processMessage:w}=fe(),{updateConversation:y}=ge(),v=(e=>{const{getDbInstance:t}=ye(),{client:n}=me();return h((async()=>n?(await t()).table("messages").where({conversationTopic:e,walletAddress:n.address}).sortBy("sentAt"):[]),[e])??[]})(e.topic),{client:f}=me(),A=s(!1),{disableAutoSync:b,onError:T,onMessages:M}=t??{},E=o((async()=>{if(A.current)return;if(!f){const e=new Error("XMTP client is not available");return u(e),void T?.(e)}let t;if(A.current=!0,d(!0),r(!1),u(null),e.isReady){const n=m([e.lastSyncedAt??Date.now(),e.updatedAt]);t=g(n,10)}try{const n=await N(e.topic,f),s=new Date,a=await(n?.messages({direction:p.SORT_DIRECTION_ASCENDING,startTime:t}))??[];await Promise.all(a.map((t=>w(e,Q(t,f.address))))),e.isReady||await y(e.topic,{isReady:!0}),await y(e.topic,{lastSyncedAt:s}),r(!0),M?.(a)}catch(e){throw u(e),T?.(e),e}finally{d(!1),A.current=!1}}),[f,e,T,M,w,y]);return c((()=>{E()}),[E]),c((()=>{const e=()=>{document.hidden||b||E()};return document.addEventListener("visibilitychange",e),()=>{document.removeEventListener("visibilitychange",e)}}),[E,b]),{error:l,isLoaded:a,isLoading:i,messages:v}},De=()=>{const{client:e}=me(),{getDbInstance:t}=ye(),n=(()=>{const{getDbInstance:e}=ye(),{client:t}=me();return h((async()=>{if(!t)return{};const n=await e();return ie(t.address,n)}),[t?.address])??{}})(),s=o((async(n,s=!1)=>{if(!e)throw new Error("XMTP client is required");s||await e.contacts.allow(n);const a=await t();await pe(n.map((t=>({value:t,type:"address",state:"allowed",walletAddress:e.address}))),a)}),[e,t]),a=o((async(n,s=!1)=>{if(!e)throw new Error("XMTP client is required");s||await e.contacts.deny(n);const a=await t();await pe(n.map((t=>({value:t,type:"address",state:"denied",walletAddress:e.address}))),a)}),[e,t]);return{allow:s,consentState:o((async n=>{if(!e)throw new Error("XMTP client is required");const s=await t();return de(e.address,"address",n,s)}),[e,t]),deny:a,entries:n,isAllowed:o((async n=>{if(!e)throw new Error("XMTP client is required");const s=await t();return"allowed"===await de(e.address,"address",n,s)}),[e,t]),isDenied:o((async n=>{if(!e)throw new Error("XMTP client is required");const s=await t();return"denied"===await de(e.address,"address",n,s)}),[e,t]),loadConsentList:o((async n=>{if(!e)throw new Error("XMTP client is required");const s=await t(),a=await e.contacts.loadConsentList(n);return a.length>0&&await pe(a.map((t=>({value:t.value,type:"address",state:t.permissionType,walletAddress:e.address}))),s),a}),[e,t]),refreshConsentList:o((async()=>{if(!e)throw new Error("XMTP client is required");const n=await t();await n.table("consent").clear();const s=await(e?.contacts.refreshConsentList());return s.length>0&&await pe(s.map((t=>({value:t.value,type:"address",state:t.permissionType,walletAddress:e.address}))),n),s}),[e,t])}},Ie=e=>{const[t,s]=n(!1),[a,r]=n(null),{sendMessage:c}=fe(),{allow:i,consentState:d}=De(),{onError:l,onSuccess:u}=e??{};return{error:a,isLoading:t,sendMessage:o((async(e,t,n,a)=>{s(!0),r(null);try{const{sentMessage:s}=await c(e,t,n,{...a,onSuccess:u,onError:l});return"allowed"!==await d(e.peerAddress)&&await i([e.peerAddress],!0),s}catch(e){throw r(e),e}finally{s(!1)}}),[c,i,d,l,u])}},Se=e=>{const[t,s]=n(!1),[a,r]=n(null),{resendMessage:c,deleteMessage:i}=fe(),{onError:d,onSuccess:l}=e??{},u=o((async e=>{s(!0),r(null);try{const t=await c(e);return l?.(t),t}catch(e){throw r(e),d?.(e),e}finally{s(!1)}}),[c,d,l]);return{cancel:o((async e=>{try{await i(e)}catch(e){throw r(e),d?.(e),e}}),[i,d]),error:a,isLoading:t,resend:u}},Ce=(e,t)=>{const[a,r]=n(null),o=s(void 0),i=s((async e=>{o.current&&(o.current=void 0),void 0!==e&&(await e).return(void 0)})),{processMessage:d}=fe(),{getCachedByTopic:l}=ve(),{client:u}=me();return c((()=>{let n=o.current;const s=i.current;return(async()=>{if(!o.current){if(void 0===u){const e=new Error("XMTP client is not available");return r(e),void t?.(e)}try{if(o.current)return;o.current=u.conversations.streamAllMessages(),n=o.current;for await(const t of await n){const n=await l(t.conversation.topic);n&&await d(n,Q(t,u.address)),e?.(t)}}catch(e){throw r(e),t?.(e),s(n),e}}})(),()=>{s(n)}}),[e,u,t,d,l]),{error:a}},xe=(e,t)=>{const[a,r]=n(null),o=s(void 0),i=s((async e=>{o.current&&(o.current=void 0),void 0!==e&&(await e).return()})),{processMessage:d}=fe(),{client:l}=me(),{onError:u,onMessage:w}=t??{};return c((()=>{if(!e||!l){const e=new Error("XMTP client and/or conversation is not available");return r(e),u?.(e),()=>{}}let t=o.current;const n=i.current;return(async()=>{if(o.current)return;const s=await N(e.topic,l);if(s)try{if(o.current)return;o.current=s.streamMessages(),t=o.current;for await(const n of await t)await d(e,Q(n,l.address)),w?.(n)}catch(e){throw r(e),u?.(e),n(t),e}})(),()=>{n(t)}}),[l,e,u,w,d]),{error:a}},Xe=(e,t)=>{const{allow:a,deny:r}=De(),[o,i]=n(null),d=s(void 0),l=s((async e=>{d.current&&(d.current=void 0),void 0!==e&&(await e).return()})),{client:u}=me();return c((()=>{let n=d.current;const s=l.current;return(async()=>{if(!d.current){if(void 0===u){const e=new Error("XMTP client is not available");return i(e),void t?.(e)}try{if(d.current)return;d.current=u.contacts.streamConsentList(),n=d.current;for await(const t of await n)t.allowAddress&&a(t.allowAddress.walletAddresses,!0),t.denyAddress&&r(t.denyAddress.walletAddresses,!0),e?.(t)}catch(e){throw i(e),t?.(e),s(n),e}}})(),()=>{s(n)}}),[u,t,e,a,r]),{error:o}},Pe="attachment",Le=e=>{switch(e.contentType){case T.toString():case M.toString():return e.content;default:return}},qe=E.object({filename:E.string(),mimeType:E.string(),data:E.instanceof(Uint8Array)}),ke=E.object({url:E.string(),contentDigest:E.string(),salt:E.instanceof(Uint8Array),nonce:E.instanceof(Uint8Array),secret:E.instanceof(Uint8Array),scheme:E.string(),contentLength:E.number().gte(0),filename:E.string()}),Be={codecs:[new A,new b],contentTypes:[T.toString(),M.toString()],namespace:Pe,validators:{[T.toString()]:e=>{const{success:t}=qe.safeParse(e);return t},[M.toString()]:e=>{const{success:t}=ke.safeParse(e);return t}}},Oe=10485760,_e=(e,t)=>{const{client:r}=me(),{getDbInstance:i}=ye(),{updateMessage:d}=fe(),[l,u]=n(void 0),[w,p]=n("init"),[y,m]=n(void 0),g=s(!1),{disableAutoload:v=!1,autoloadMaxFileSize:f=Oe}=t??{},h=a((()=>(e=>{if(e.contentType===M.toString()){const t=e.metadata?.[Pe];return t}})(e)),[e]),A=o((async(t=!1)=>{if(h&&"loaded"!==w)return m(h),void p("loaded");if(r&&e.contentType===M.toString()&&!h&&"loading"!==w&&"loaded"!==w&&!y&&(e.hasLoadError&&t||!e.hasLoadError))try{p("loading");const t=await b.load(e.content,r);try{const n=await i();await(async(e,t,n)=>{e.contentType===M.toString()&&await te(e,Pe,t,n)})(e,t,n)}catch{}m(t),p("loaded")}catch(t){await d(e,{hasLoadError:!0}),u(new Error("Unable to load remote attachment")),p("error")}else u(new Error("XMTP client is required to load remote attachments")),p("error")}),[h,w,r,e,y,i,d]),E=o((()=>{A(!0)}),[A]);return c((()=>{(async()=>{if(!g.current&&(g.current=!0,!y&&"loading"!==w&&"loaded"!==w))switch(e.contentType){case T.toString():m(e.content),p("loaded"),g.current=!1;break;case M.toString():if(h)return m(h),p("loaded"),void(g.current=!1);if(e.content.contentLength>f)return p("autoloadMaxFileSizeExceeded"),void(g.current=!1);v||await A(),g.current=!1;break;default:u(new Error("Message is not an attachment content type")),p("error"),g.current=!1}})()}),[h,f,v,A,e,y,w]),{attachment:y,error:l,load:E,status:w}},je=e=>{const{getDbInstance:t}=ye();return h((async()=>{if(!e)return[];try{const n=(await t()).table("reactions");return await n.where("referenceXmtpID").equals(e.id).sortBy("sentAt")}catch{return[]}}),[e,t])??[]},Re="reactions",Fe=async(e,t)=>{const n=t.table("reactions");return await n.where("id").equals(e.id).first()},Ue=async(e,t)=>t.table("reactions").where({referenceXmtpID:e}).sortBy("sentAt"),Ne=e=>!!e?.metadata?.[Re],ze=E.object({reference:E.string(),action:E.enum(["added","removed"]),content:E.string(),schema:E.enum(["unicode","shortcode","custom"])}),Ge=e=>{const{success:t}=ze.safeParse(e);return t},$e=new f,Ke={codecs:[new D],contentTypes:[I.toString()],namespace:Re,processors:{[I.toString()]:[async({message:e,db:t})=>{await $e.runExclusive((async()=>{const n=S.fromString(e.contentType);if(I.sameAs(n)&&Ge(e.content)){const n=e.content,s={content:n.content,referenceXmtpID:n.reference,schema:n.schema,senderAddress:e.senderAddress,sentAt:e.sentAt,id:e.id};switch(n.action){case"added":await(async(e,t)=>{const n=t.table("reactions"),s=await Fe(e,t);return s?(await n.update(s.id,{sentAt:e.sentAt}),s.id):n.add(e)})(s,t);break;case"removed":await(async(e,t)=>{const n=t.table("reactions"),s=await Fe(e,t);s&&await n.delete(s.id)})(s,t)}await(async(e,t)=>{const n=await Ue(e,t),s=await V(e,t);s&&await te(s,Re,n.length>0,t)})(n.reference,t)}}))}]},schema:{reactions:"\n id,\n referenceXmtpID,\n content,\n schema,\n senderAddress,\n sentAt\n "},validators:{[I.toString()]:Ge}},We=async(e,t)=>{const n=t.table("replies"),s=await n.where({referenceXmtpID:e.id}).toArray();if(s.length>0){const e=t.table("messages");return await e.where("id").anyOf(s.map((e=>e.xmtpID))).sortBy("sentAt")}return[]},He=async(e,t)=>{const n=t.table("replies");return(await n.where({referenceXmtpID:e.id}).toArray()).length>0},Je=async(e,t)=>{if(x.sameAs(S.fromString(e.contentType))&&"processed"===e.status&&e.content){const n=e.content;return V(n.reference,t)}},Qe=E.object({content:E.any(),contentType:E.object({authorityId:E.string(),typeId:E.string(),versionMajor:E.number().gt(0),versionMinor:E.number().gte(0)}),reference:E.string()}),Ve=e=>{const{success:t}=Qe.safeParse(e);return t},Ye={codecs:[new C],contentTypes:[x.toString()],namespace:"replies",processors:{[x.toString()]:[async({message:e,db:t})=>{const n=S.fromString(e.contentType);if(x.sameAs(n)&&Ve(e.content)){const n=e.content;await(async(e,t,n)=>{const s=n.table("replies"),a=await s.where({referenceXmtpID:e,xmtpID:t}).first();return a?a.id:s.add({referenceXmtpID:e,xmtpID:t})})(n.reference,e.id,t)}}]},schema:{replies:"\n ++id,\n [referenceXmtpID+xmtpID],\n referenceXmtpID,\n xmtpID\n "},validators:{[x.toString()]:Ve}},Ze=e=>{const{getDbInstance:t}=ye(),[s,a]=n(void 0);return c((()=>{(async()=>{if(e){const n=await t(),s=await Je(e,n);s&&a(s)}})()}),[t,e]),{originalMessage:s}},et=e=>{const{getDbInstance:t}=ye();return h((async()=>{if(!e)return[];try{const n=await t();return await We(e,n)}catch{return[]}}),[e,t])??[]};export{_ as XMTPProvider,Be as attachmentContentTypeConfig,pe as bulkPutConsentState,k as clearCache,Z as deleteMessage,Le as getAttachment,ce as getCachedConsentEntries,ie as getCachedConsentEntriesMap,oe as getCachedConsentEntry,de as getCachedConsentState,U as getCachedConversationByPeerAddress,F as getCachedConversationByTopic,N as getConversationByTopic,q as getDbInstance,re as getLastMessage,V as getMessageByXmtpID,Je as getOriginalMessageFromReply,Ue as getReactionsByXmtpID,We as getReplies,K as hasConversationTopic,Ne as hasReaction,He as hasReply,j as isValidAddress,le as loadConsentListFromCache,we as putConsentState,Ke as reactionContentTypeConfig,Ye as replyContentTypeConfig,J as saveConversation,Y as saveMessage,$ as setConversationUpdatedAt,X as textContentTypeConfig,W as toCachedConversation,Q as toCachedMessage,z as updateConversation,G as updateConversationMetadata,ee as updateMessage,te as updateMessageMetadata,_e as useAttachment,Me as useCanMessage,me as useClient,De as useConsent,ve as useConversation,he as useConversations,ye as useDb,Te as useLastMessage,fe as useMessage,Ee as useMessages,je as useReactions,et as useReplies,Ze as useReply,Se as useResendMessage,Ie as useSendMessage,Ae as useStartConversation,Ce as useStreamAllMessages,Xe as useStreamConsentList,be as useStreamConversations,xe as useStreamMessages};
import{jsx as e}from"react/jsx-runtime";import{createContext as t,useState as n,useRef as s,useMemo as r,useContext as a,useCallback as o,useEffect as c}from"react";import i from"dexie";import{ContentTypeText as d}from"@xmtp/content-type-text";import{decodeContent as l,ConsentListEntry as u,Client as w,SortDirection as p}from"@xmtp/xmtp-js";export{Client,Compression,SortDirection}from"@xmtp/xmtp-js";import{isAfter as y,min as m,subSeconds as g}from"date-fns";import{v4 as f}from"uuid";import{Mutex as v}from"async-mutex";import{useLiveQuery as h}from"dexie-react-hooks";import{AttachmentCodec as A,RemoteAttachmentCodec as b,ContentTypeAttachment as T,ContentTypeRemoteAttachment as M}from"@xmtp/content-type-remote-attachment";import{z as E}from"zod";import{ReactionCodec as D,ContentTypeReaction as I}from"@xmtp/content-type-reaction";import{ContentTypeId as S}from"@xmtp/content-type-primitives";import{ReplyCodec as C,ContentTypeReply as x}from"@xmtp/content-type-reply";const X={codecs:[],contentTypes:[d.toString()],namespace:"text",validators:{[d.toString()]:e=>"string"==typeof e}},P=e=>{const t=new i("__XMTP2__");t.isOpen()&&t.close();const n=e?.reduce(((e,{schema:t})=>({...e,...t})),{});return t.version(1).stores({...n,conversations:"\n topic,\n [walletAddress+topic],\n [walletAddress+peerAddress],\n createdAt,\n peerAddress,\n updatedAt,\n walletAddress\n ",messages:"\n id,\n [conversationTopic+walletAddress],\n contentFallback,\n contentType,\n conversationTopic,\n senderAddress,\n sentAt,\n status,\n uuid,\n walletAddress\n ",consent:"\n [walletAddress+type+value],\n type,\n value,\n state,\n walletAddress\n "}),t};let L;const q=async e=>{let t,n=!1;try{const e=new i("__XMTP__");await e.open(),n=!0,e.close()}catch{}if(!n)return P(e?.contentTypeConfigs);if(L){return await L}L=new Promise((e=>{t=e}));const s=(()=>{const e=new i("__XMTP__");return e.isOpen()&&e.close(),e.version(1).stores({reactions:"\n ++id,\n [content+referenceXmtpID+schema+senderAddress],\n referenceXmtpID,\n content,\n schema,\n senderAddress,\n sentAt,\n xmtpID\n ",replies:"\n ++id,\n [referenceXmtpID+xmtpID],\n referenceXmtpID,\n xmtpID\n ",conversations:"\n ++id,\n [walletAddress+topic],\n [walletAddress+peerAddress],\n createdAt,\n peerAddress,\n topic,\n updatedAt,\n walletAddress\n ",messages:"\n ++id,\n [conversationTopic+walletAddress],\n contentFallback,\n contentType,\n conversationTopic,\n senderAddress,\n sentAt,\n status,\n uuid,\n walletAddress,\n xmtpID\n ",consent:"\n [walletAddress+peerAddress],\n peerAddress,\n state,\n walletAddress\n "}),e})(),r=P(e?.contentTypeConfigs),a=await s.table("conversations").toArray();await r.table("conversations").bulkAdd(a.map((e=>(delete e.id,e))));const o=await s.table("messages").toArray();await r.table("messages").bulkAdd(o.map((e=>{const t=e.xmtpID;return delete e.xmtpID,{...e,id:t}})));const c=await s.table("consent").toArray();await r.table("consent").bulkAdd(c.map((e=>({type:"address",value:e.peerAddress,state:e.state,walletAddress:e.walletAddress}))));const d=await s.table("reactions").toArray();d.length>0&&await r.table("reactions").bulkAdd(d.map((e=>{const t=e.xmtpID;return delete e.xmtpID,{...e,id:t}})));const l=await s.table("replies").toArray();return l.length>0&&await r.table("replies").bulkAdd(l),s.close(),await s.delete(),t?.(r),r},k=async e=>{await Promise.all(e.tables.map((e=>e.clear())))},B=[X],O=t({codecs:[],contentTypeConfigs:[],dbRef:{current:null},namespaces:{},processors:{},setClient:()=>{},validators:{}}),_=({children:t,client:a,contentTypeConfigs:o})=>{const[c,i]=n(a),d=s(null),l=r((()=>(e=>({...[...B,...e??[]].reduce(((e,t)=>{const n=Object.entries(t.processors??[]).reduce(((t,[n,s])=>({...t,[n]:[...e[n]??[],...s]})),{});return{...e,...n}}),{})}))(o??[])),[o]),u=r((()=>(e=>[...B,...e??[]].reduce(((e,t)=>[...e,...t.codecs??[]]),[]))(o??[])),[o]),w=r((()=>(e=>{const t=[...B,...e??[]],n=[];return t.reduce(((e,t)=>{if(n.includes(t.namespace))throw new Error(`Duplicate content types config namespace detected: "${t.namespace}"`);return n.push(t.namespace),{...e,...(t.contentTypes??[]).reduce(((e,n)=>({...e,[n]:t.namespace})),{})}}),{})})(o??[])),[o]),p=r((()=>(e=>{const t=[...B,...e??[]],n=[];return t.reduce(((e,t)=>{const s={};return Object.entries(t.validators??{}).forEach((([e,t])=>{if(n.includes(e))throw new Error(`Duplicate content validator detected for content type "${e}"`);n.push(e),s[e]=t})),{...e,...s}}),{})})(o??[])),[o]),y=r((()=>({client:c,codecs:u,contentTypeConfigs:o??[],dbRef:d,namespaces:w,processors:l,setClient:i,validators:p})),[c,u,o,w,l,p]);return e(O.Provider,{value:y,children:t})},j=e=>e.startsWith("0x")&&42===e.length,R=async(e,t,n,s)=>{const r=s.table("conversations");return await r.where({walletAddress:e,[t]:n}).first()},F=async(e,t,n)=>R(e,"topic",t,n),U=async(e,t,n)=>R(e,"peerAddress",t,n),z=async(e,t)=>{let n;return(await t.conversations.listFromCache()).some((t=>t.topic===e&&(n=t,!0))),n},N=async(e,t,n)=>{const s=n.table("conversations"),r=await s.where("topic").equals(e).first();r&&await s.update(r,t)},W=async(e,t,n,s,r)=>{const a=await F(e,t,r);if(a){const e=a.metadata||{};e[n]=s,await N(t,{metadata:e},r)}},G=async(e,t,n)=>{await N(e,{updatedAt:t},n)},$=async(e,t,n)=>!!await F(e,t,n),K=(e,t)=>({context:e.context,createdAt:e.createdAt,isReady:!1,peerAddress:e.peerAddress,topic:e.topic,updatedAt:e.createdAt,walletAddress:t}),H=new v,J=async(e,t)=>H.runExclusive((async()=>{const n=t.table("conversations"),s=await n.where({walletAddress:e.walletAddress,topic:e.topic}).first();return s||(await n.add(e),e)})),Q=(e,t)=>{const n=void 0!==e.content;return{content:e.content,contentBytes:n?void 0:e.contentBytes,contentFallback:e.contentFallback,contentType:e.contentType.toString(),conversationTopic:e.contentTopic,status:"unprocessed",hasLoadError:!1,hasSendError:!1,id:e.id,isSending:!1,senderAddress:e.senderAddress,sentAt:e.sent,uuid:f(),walletAddress:t}},V=async(e,t)=>{const n=t.table("messages");return await n.where("id").equals(e).first()},Y=async(e,t)=>{const n=t.table("messages"),s=await V(e.id,t);if(s)return s;const r=await n.add(e);return{...e,id:r}},Z=async(e,t)=>{const n=t.table("messages");await n.where("id").equals(e.id).first()&&await n.delete(e.id)},ee=async(e,t,n)=>{const s=n.table("messages");return await s.update(e,t),{...e,...t}},te=async(e,t,n,s)=>{const r=e.metadata||{};return r[t]=n,ee(e,{metadata:r},s)},ne=[],se=async({client:e,conversation:t,db:n,message:s,namespaces:r,processors:a,validators:o},c=!1)=>{if(!e)return{status:"no_client",message:s};if(ne.includes(s.id))return{status:"queued",message:s};ne.push(s.id);const i=r[s.contentType];try{const r=await V(s.id,n);if(r&&"processed"===r.status)return{status:"duplicate",message:s};const d=o[s.contentType];if(d&&!d(s.content))return{status:"invalid",message:s};const l=async s=>{await W(e.address,t.topic,i,s,n)};if(void 0===s.content)return{status:"unsupported",message:r?s:await Y(s,n)};c&&r&&await Z(r,n),a[s.contentType]&&await Promise.all(a[s.contentType].map((r=>r({client:e,conversation:t,db:n,message:s,processors:a,updateConversationMetadata:l}))));const u=await Y(s,n);!s.isSending&&y(s.sentAt,t.updatedAt)&&await G(t.topic,s.sentAt,n);return{status:"processed",message:await ee(u,{status:"processed"},n)}}finally{const e=ne.indexOf(s.id);e>-1&&ne.splice(e,1)}},re=async({client:e,conversation:t,db:n,message:s,namespaces:r,processors:a,validators:o,process:c=se,decode:i=l})=>{if(void 0===s.content&&s.contentBytes&&e&&a[s.contentType]){const d=await i(s.contentBytes,e);return void 0===d.content?s:c({conversation:t,client:e,db:n,message:{...s,content:d.content,contentBytes:void 0},namespaces:r,processors:a,validators:o},!0)}return s},ae=async(e,t)=>{const n=t.table("messages");return(await n.where({conversationTopic:e}).reverse().sortBy("sentAt"))[0]},oe=async(e,t,n,s)=>s.table("consent").where({walletAddress:e,type:t,value:n}).first(),ce=async(e,t)=>{const n=t.table("consent");return(await n.where({walletAddress:e}).toArray()).map((e=>u.fromAddress(e.value,e.state)))},ie=async(e,t)=>{const n=await ce(e,t);return n.length?Object.fromEntries(n.map((e=>[e.value,e]))):{}},de=async(e,t,n,s)=>{const r=await oe(e,t,n,s);return r?.state??"unknown"},le=async(e,t)=>{const n=await ce(e.address,t);e.contacts.setConsentListEntries(n)},ue=new v,we=async(e,t,n,s,r)=>ue.runExclusive((async()=>{const a=r.table("consent");await a.put({type:t,value:n,state:s,walletAddress:e})})),pe=async(e,t)=>ue.runExclusive((async()=>{const n=t.table("consent");await n.bulkPut(e)})),ye=()=>{const e=a(O),{contentTypeConfigs:t,dbRef:n}=e,s=o((async()=>(n.current||(n.current=await q({contentTypeConfigs:t})),n.current)),[t,n]);return{clearCache:o((async()=>{const e=await s();await k(e)}),[s]),getDbInstance:s}},me=e=>{const[t,r]=n(!1),[c,i]=n(null),d=s(!1),{getDbInstance:l}=ye(),{client:u,setClient:p,codecs:y,processors:m,namespaces:g,validators:f}=a(O),v=o((async({keys:t,options:n,signer:s})=>{if(!u&&(s||t)){if(d.current)return;let a;d.current=!0,i(null),r(!0);try{a=await w.create(s??null,{...n,codecs:y,privateKeyOverride:t}),p(a)}catch(t){throw p(void 0),i(t),e?.(t),t}finally{d.current=!1}r(!1);const o=await l();try{await le(a,o)}catch(t){e?.(t)}try{await(async({client:e,db:t,namespaces:n,processors:s,validators:r,reprocess:a=re})=>{const o=await(async e=>{const t=e.table("messages");return await t.where({status:"unprocessed"}).toArray()})(t);await Promise.all(o.map((async o=>{const c=await F(e.address,o.conversationTopic,t);c&&await a({conversation:c,client:e,db:t,message:o,namespaces:n,processors:s,validators:r})})))})({client:a,db:o,processors:m,namespaces:g,validators:f})}catch(t){e?.(t)}return d.current=!1,a}return u}),[u,y,l,g,e,m,p,f]),h=o((async()=>{u&&(await u.close(),p(void 0))}),[u,p]);return{client:u,disconnect:h,error:c,initialize:v,isLoading:t}},ge=()=>{const{client:e}=me(),{getDbInstance:t}=ye();return{saveConversation:o((async n=>{if(!e)return;const s=await t();return J(n,s)}),[e,t]),updateConversation:o((async(e,n)=>{const s=await t();await N(e,n,s)}),[t]),updateMetadata:o((async(n,s,r)=>{if(e){const a=await t();await W(e.address,n,s,r,a)}}),[e,t])}},fe=()=>{const{client:e}=me(),{getDbInstance:t}=ye();return{getByTopic:o((async t=>e?z(t,e):void 0),[e]),getCachedByTopic:o((async n=>{if(!e)return;const s=await t();return F(e.address,n,s)}),[e,t]),getCachedByPeerAddress:o((async n=>{if(!e)return;const s=await t();return U(e.address,n,s)}),[e,t]),getLastMessage:o((async e=>{const n=await t();return ae(e,n)}),[t]),hasConversationTopic:o((async n=>{if(!e)return!1;const s=await t();return $(e.address,n,s)}),[e,t])}},ve=()=>{const e=a(O),{processors:t,namespaces:n,validators:s}=e,{client:r}=me(),{getDbInstance:c}=ye(),i=o((async(e,a)=>{const o=await c();return se({client:r,conversation:e,db:o,message:a,namespaces:n,processors:t,validators:s})}),[r,c,n,t,s]),l=o((async(e,t)=>{const n=await c();return ee(e,t,n)}),[c]),u=o((async(e,t)=>(async(e,t,n)=>ee(e,{hasSendError:!1,isSending:!1,sendOptions:void 0,sentAt:t},n))(e,t,await c())),[c]),w=o((async e=>{const t=await c();return V(e,t)}),[c]),p=o((async e=>{const t=await c();return Z(e,t)}),[c]),y=o((async(e,t,n,s)=>{if(!r)throw new Error("XMTP client is required to send a message");if(void 0===t)throw new Error("Message content is required to send a message");const{onSuccess:a,onError:o,...w}=s??{},p={...w,contentType:n??d};try{const{message:n,preparedMessage:s}=await(async({client:e,content:t,conversation:n,sendOptions:s})=>{const r=await z(n.topic,e);if(!r)throw new Error("Conversation not found in XMTP client, unable to prepare message");const a=await r.prepareMessage(t,s),o=new Date;return{message:{content:t,contentType:s?.contentType?.toString()??d.toString(),conversationTopic:n.topic,hasLoadError:!1,hasSendError:!1,id:await a.messageID(),isSending:!0,senderAddress:e.address,sentAt:o,status:"unprocessed",uuid:f(),walletAddress:e.address},preparedMessage:a}})({client:r,content:t,conversation:e,sendOptions:p}),{status:o,message:w}=await i(e,n);switch(o){case"invalid":throw new Error("Unable to send message: content is invalid");case"duplicate":throw new Error("Unable to send message: message is a duplicate")}if("processed"===o)try{const t=await c(),n=await s.send();return await G(e.topic,n.sent,t),a?.(n),w.id&&await u(w,n.sent),{cachedMessage:w,sentMessage:n}}catch(e){throw w.id&&await l(w,{hasSendError:!0,sendOptions:p}),e}return{cachedMessage:w}}catch(e){throw o?.(e),e}}),[r,c,i,l,u]),m=o((async e=>{if(!e.hasSendError)throw new Error("Resending a message that hasn't failed to send is not allowed");if(!r)throw new Error("XMTP client is required to send a message");const t=await z(e.conversationTopic,r);if(!t){throw new Error("Conversation not found in XMTP client, unable to send message")}const n=await t.send(e.content,e.sendOptions),s=await c();return await G(t.topic,n.sent,s),await u(e,n.sent),n}),[r,c,u]);return{deleteMessage:p,getMessageByXmtpID:w,processMessage:i,resendMessage:m,sendMessage:y,updateMessage:l}},he=e=>{const[t,r]=n(!1),[a,o]=n(!1),[i,d]=n(null),{client:l}=me(),{processMessage:u}=ve(),{saveConversation:w}=ge(),{hasConversationTopic:y}=fe(),m=(()=>{const{getDbInstance:e}=ye(),{client:t}=me();return h((async()=>t?(await e()).table("conversations").where("walletAddress").equals(t.address).reverse().sortBy("updatedAt"):[]),[t?.address])??[]})(),g=s(!1),{onConversations:f,onError:v}=e??{};return c((()=>{if(!l){const e=new Error("XMTP client is required to fetch conversations");return d(e),void v?.(e)}(async()=>{if(!g.current){g.current=!0,r(!0),o(!1),d(null);try{const e=await l.conversations.list()??[];await Promise.all(e.map((async e=>{if(!await y(e.topic)){const t=await w(K(e,l.address)),n=await e.messages({direction:p.SORT_DIRECTION_DESCENDING,limit:1});if(n.length>0&&t){const e=n[0];await u(t,Q(e,l.address))}}}))),o(!0),f?.(e)}catch(e){throw d(e),v?.(e),e}finally{r(!1),g.current=!1}}})()}),[l,y,f,v,u,w]),{conversations:m,error:i,isLoaded:a,isLoading:t}},Ae=e=>{const[t,s]=n(!1),[r,a]=n(null),{client:c}=me(),{sendMessage:i}=ve(),{saveConversation:d}=ge(),{conversationId:l,metadata:u,onError:w}=e??{};return{error:r,isLoading:t,startConversation:o((async(e,t,n,r)=>{if(void 0===c){const e=new Error("XMTP client is required to start a conversation");return a(e),w?.(e),{cachedConversation:void 0,cachedMessage:void 0,conversation:void 0}}s(!0),a(null);try{const s=await c.conversations.newConversation(e,l&&u?{conversationId:l,metadata:u}:void 0),a=await d(K(s,c.address));if(!a)return{cachedConversation:void 0,cachedMessage:void 0,conversation:s};if(void 0===t)return{cachedConversation:a,cachedMessage:void 0,conversation:s};const{cachedMessage:o}=await i(a,t,n,r);return{cachedConversation:a,cachedMessage:o,conversation:s}}catch(e){throw a(e),w?.(e),e}finally{s(!1)}}),[i,c,l,u,w,d])}},be=e=>{const[t,r]=n(null),a=s(void 0),o=s((async e=>{a.current&&(a.current=void 0),void 0!==e&&(await e).return()})),{client:i}=me(),{saveConversation:d}=ge(),{onConversation:l,onError:u}=e??{};return c((()=>{let e=a.current;const t=o.current;return(async()=>{if(!a.current){if(void 0===i){const e=new Error("XMTP client is not available");return r(e),void u?.(e)}try{if(a.current)return;a.current=i.conversations.stream(),e=a.current;for await(const t of await e)await d(K(t,i.address)),l?.(t)}catch(n){throw r(n),u?.(n),t(e),n}}})(),()=>{t(e)}}),[i,d,u,l]),{error:t}},Te=e=>{const{getDbInstance:t}=ye();return h((async()=>{const n=(await t()).table("messages");return(await n.where({conversationTopic:e}).reverse().sortBy("sentAt")).filter((e=>void 0!==e.content))[0]}),[e])},Me=e=>{const[t,s]=n(!1),[r,a]=n(null),{client:c}=me();return{error:r,isLoading:t,canMessage:o((async t=>{if(!c)throw new Error("XMTP client is required to check if an address is on the network");s(!1),a(null);try{return await c.canMessage(t)}catch(t){throw a(t),e?.(t),t}finally{s(!1)}}),[c,e]),canMessageStatic:o((async(t,n)=>{s(!1),a(null);try{return await w.canMessage(t,n)}catch(t){throw a(t),e?.(t),t}finally{s(!1)}}),[e])}},Ee=(e,t)=>{const[r,a]=n(!1),[i,d]=n(!1),[l,u]=n(null),{processMessage:w}=ve(),{updateConversation:y}=ge(),f=(e=>{const{getDbInstance:t}=ye(),{client:n}=me();return h((async()=>n?(await t()).table("messages").where({conversationTopic:e,walletAddress:n.address}).sortBy("sentAt"):[]),[e])??[]})(e.topic),{client:v}=me(),A=s(!1),{disableAutoSync:b,onError:T,onMessages:M}=t??{},E=o((async()=>{if(A.current)return;if(!v){const e=new Error("XMTP client is not available");return u(e),void T?.(e)}let t;if(A.current=!0,d(!0),a(!1),u(null),e.isReady){const n=m([e.lastSyncedAt??Date.now(),e.updatedAt]);t=g(n,10)}try{const n=await z(e.topic,v),s=new Date,r=await(n?.messages({direction:p.SORT_DIRECTION_ASCENDING,startTime:t}))??[];await Promise.all(r.map((t=>w(e,Q(t,v.address))))),e.isReady||await y(e.topic,{isReady:!0}),await y(e.topic,{lastSyncedAt:s}),a(!0),M?.(r)}catch(e){throw u(e),T?.(e),e}finally{d(!1),A.current=!1}}),[v,e,T,M,w,y]);return c((()=>{E()}),[E]),c((()=>{const e=()=>{document.hidden||b||E()};return document.addEventListener("visibilitychange",e),()=>{document.removeEventListener("visibilitychange",e)}}),[E,b]),{error:l,isLoaded:r,isLoading:i,messages:f}},De=()=>{const{client:e}=me(),{getDbInstance:t}=ye(),n=(()=>{const{getDbInstance:e}=ye(),{client:t}=me();return h((async()=>{if(!t)return{};const n=await e();return ie(t.address,n)}),[t?.address])??{}})(),s=o((async(n,s=!1)=>{if(!e)throw new Error("XMTP client is required");s||await e.contacts.allow(n);const r=await t();await pe(n.map((t=>({value:t,type:"address",state:"allowed",walletAddress:e.address}))),r)}),[e,t]),r=o((async(n,s=!1)=>{if(!e)throw new Error("XMTP client is required");s||await e.contacts.deny(n);const r=await t();await pe(n.map((t=>({value:t,type:"address",state:"denied",walletAddress:e.address}))),r)}),[e,t]);return{allow:s,consentState:o((async n=>{if(!e)throw new Error("XMTP client is required");const s=await t();return de(e.address,"address",n,s)}),[e,t]),deny:r,entries:n,isAllowed:o((async n=>{if(!e)throw new Error("XMTP client is required");const s=await t();return"allowed"===await de(e.address,"address",n,s)}),[e,t]),isDenied:o((async n=>{if(!e)throw new Error("XMTP client is required");const s=await t();return"denied"===await de(e.address,"address",n,s)}),[e,t]),loadConsentList:o((async n=>{if(!e)throw new Error("XMTP client is required");const s=await t(),r=await e.contacts.loadConsentList(n);if(r.size>0){const t=Array.from(r.entries()).filter((([e])=>e.startsWith("address-"))).map((([e,t])=>[e.split("-")[1],t]));await pe(t.map((([t,n])=>({value:t,type:"address",state:n,walletAddress:e.address}))),s)}return r}),[e,t]),refreshConsentList:o((async()=>{if(!e)throw new Error("XMTP client is required");const n=await t();await n.table("consent").clear();const s=await(e?.contacts.refreshConsentList());if(s.size>0){const t=Array.from(s.entries()).filter((([e])=>e.startsWith("address-"))).map((([e,t])=>[e.split("-")[1],t]));await pe(t.map((([t,n])=>({value:t,type:"address",state:n,walletAddress:e.address}))),n)}return s}),[e,t])}},Ie=e=>{const[t,s]=n(!1),[r,a]=n(null),{sendMessage:c}=ve(),{allow:i,consentState:d}=De(),{onError:l,onSuccess:u}=e??{};return{error:r,isLoading:t,sendMessage:o((async(e,t,n,r)=>{s(!0),a(null);try{const{sentMessage:s}=await c(e,t,n,{...r,onSuccess:u,onError:l});return"allowed"!==await d(e.peerAddress)&&await i([e.peerAddress],!0),s}catch(e){throw a(e),e}finally{s(!1)}}),[c,i,d,l,u])}},Se=e=>{const[t,s]=n(!1),[r,a]=n(null),{resendMessage:c,deleteMessage:i}=ve(),{onError:d,onSuccess:l}=e??{},u=o((async e=>{s(!0),a(null);try{const t=await c(e);return l?.(t),t}catch(e){throw a(e),d?.(e),e}finally{s(!1)}}),[c,d,l]);return{cancel:o((async e=>{try{await i(e)}catch(e){throw a(e),d?.(e),e}}),[i,d]),error:r,isLoading:t,resend:u}},Ce=(e,t)=>{const[r,a]=n(null),o=s(void 0),i=s((async e=>{o.current&&(o.current=void 0),void 0!==e&&(await e).return(void 0)})),{processMessage:d}=ve(),{getCachedByTopic:l}=fe(),{client:u}=me();return c((()=>{let n=o.current;const s=i.current;return(async()=>{if(!o.current){if(void 0===u){const e=new Error("XMTP client is not available");return a(e),void t?.(e)}try{if(o.current)return;o.current=u.conversations.streamAllMessages(),n=o.current;for await(const t of await n){const n=await l(t.conversation.topic);n&&await d(n,Q(t,u.address)),e?.(t)}}catch(e){throw a(e),t?.(e),s(n),e}}})(),()=>{s(n)}}),[e,u,t,d,l]),{error:r}},xe=(e,t)=>{const[r,a]=n(null),o=s(void 0),i=s((async e=>{o.current&&(o.current=void 0),void 0!==e&&(await e).return()})),{processMessage:d}=ve(),{client:l}=me(),{onError:u,onMessage:w}=t??{};return c((()=>{if(!e||!l){const e=new Error("XMTP client and/or conversation is not available");return a(e),u?.(e),()=>{}}let t=o.current;const n=i.current;return(async()=>{if(o.current)return;const s=await z(e.topic,l);if(s)try{if(o.current)return;o.current=s.streamMessages(),t=o.current;for await(const n of await t)await d(e,Q(n,l.address)),w?.(n)}catch(e){throw a(e),u?.(e),n(t),e}})(),()=>{n(t)}}),[l,e,u,w,d]),{error:r}},Xe=(e,t)=>{const{allow:r,deny:a}=De(),[o,i]=n(null),d=s(void 0),l=s((async e=>{d.current&&(d.current=void 0),void 0!==e&&(await e).return()})),{client:u}=me();return c((()=>{let n=d.current;const s=l.current;return(async()=>{if(!d.current){if(void 0===u){const e=new Error("XMTP client is not available");return i(e),void t?.(e)}try{if(d.current)return;d.current=u.contacts.streamConsentList(),n=d.current;for await(const t of await n)t.allowAddress&&r(t.allowAddress.walletAddresses,!0),t.denyAddress&&a(t.denyAddress.walletAddresses,!0),e?.(t)}catch(e){throw i(e),t?.(e),s(n),e}}})(),()=>{s(n)}}),[u,t,e,r,a]),{error:o}},Pe="attachment",Le=e=>{switch(e.contentType){case T.toString():case M.toString():return e.content;default:return}},qe=E.object({filename:E.string(),mimeType:E.string(),data:E.instanceof(Uint8Array)}),ke=E.object({url:E.string(),contentDigest:E.string(),salt:E.instanceof(Uint8Array),nonce:E.instanceof(Uint8Array),secret:E.instanceof(Uint8Array),scheme:E.string(),contentLength:E.number().gte(0),filename:E.string()}),Be={codecs:[new A,new b],contentTypes:[T.toString(),M.toString()],namespace:Pe,validators:{[T.toString()]:e=>{const{success:t}=qe.safeParse(e);return t},[M.toString()]:e=>{const{success:t}=ke.safeParse(e);return t}}},Oe=10485760,_e=(e,t)=>{const{client:a}=me(),{getDbInstance:i}=ye(),{updateMessage:d}=ve(),[l,u]=n(void 0),[w,p]=n("init"),[y,m]=n(void 0),g=s(!1),{disableAutoload:f=!1,autoloadMaxFileSize:v=Oe}=t??{},h=r((()=>(e=>{if(e.contentType===M.toString()){const t=e.metadata?.[Pe];return t}})(e)),[e]),A=o((async(t=!1)=>{if(h&&"loaded"!==w)return m(h),void p("loaded");if(a&&e.contentType===M.toString()&&!h&&"loading"!==w&&"loaded"!==w&&!y&&(e.hasLoadError&&t||!e.hasLoadError))try{p("loading");const t=await b.load(e.content,a);try{const n=await i();await(async(e,t,n)=>{e.contentType===M.toString()&&await te(e,Pe,t,n)})(e,t,n)}catch{}m(t),p("loaded")}catch(t){await d(e,{hasLoadError:!0}),u(new Error("Unable to load remote attachment")),p("error")}else u(new Error("XMTP client is required to load remote attachments")),p("error")}),[h,w,a,e,y,i,d]),E=o((()=>{A(!0)}),[A]);return c((()=>{(async()=>{if(!g.current&&(g.current=!0,!y&&"loading"!==w&&"loaded"!==w))switch(e.contentType){case T.toString():m(e.content),p("loaded"),g.current=!1;break;case M.toString():if(h)return m(h),p("loaded"),void(g.current=!1);if(e.content.contentLength>v)return p("autoloadMaxFileSizeExceeded"),void(g.current=!1);f||await A(),g.current=!1;break;default:u(new Error("Message is not an attachment content type")),p("error"),g.current=!1}})()}),[h,v,f,A,e,y,w]),{attachment:y,error:l,load:E,status:w}},je=e=>{const{getDbInstance:t}=ye();return h((async()=>{if(!e)return[];try{const n=(await t()).table("reactions");return await n.where("referenceXmtpID").equals(e.id).sortBy("sentAt")}catch{return[]}}),[e,t])??[]},Re="reactions",Fe=async(e,t)=>{const n=t.table("reactions");return await n.where("id").equals(e.id).first()},Ue=async(e,t)=>t.table("reactions").where({referenceXmtpID:e}).sortBy("sentAt"),ze=e=>!!e?.metadata?.[Re],Ne=E.object({reference:E.string(),action:E.enum(["added","removed"]),content:E.string(),schema:E.enum(["unicode","shortcode","custom"])}),We=e=>{const{success:t}=Ne.safeParse(e);return t},Ge=new v,$e={codecs:[new D],contentTypes:[I.toString()],namespace:Re,processors:{[I.toString()]:[async({message:e,db:t})=>{await Ge.runExclusive((async()=>{const n=S.fromString(e.contentType);if(I.sameAs(n)&&We(e.content)){const n=e.content,s={content:n.content,referenceXmtpID:n.reference,schema:n.schema,senderAddress:e.senderAddress,sentAt:e.sentAt,id:e.id};switch(n.action){case"added":await(async(e,t)=>{const n=t.table("reactions"),s=await Fe(e,t);return s?(await n.update(s.id,{sentAt:e.sentAt}),s.id):n.add(e)})(s,t);break;case"removed":await(async(e,t)=>{const n=t.table("reactions"),s=await Fe(e,t);s&&await n.delete(s.id)})(s,t)}await(async(e,t)=>{const n=await Ue(e,t),s=await V(e,t);s&&await te(s,Re,n.length>0,t)})(n.reference,t)}}))}]},schema:{reactions:"\n id,\n referenceXmtpID,\n content,\n schema,\n senderAddress,\n sentAt\n "},validators:{[I.toString()]:We}},Ke=async(e,t)=>{const n=t.table("replies"),s=await n.where({referenceXmtpID:e.id}).toArray();if(s.length>0){const e=t.table("messages");return await e.where("id").anyOf(s.map((e=>e.xmtpID))).sortBy("sentAt")}return[]},He=async(e,t)=>{const n=t.table("replies");return(await n.where({referenceXmtpID:e.id}).toArray()).length>0},Je=async(e,t)=>{if(x.sameAs(S.fromString(e.contentType))&&"processed"===e.status&&e.content){const n=e.content;return V(n.reference,t)}},Qe=E.object({content:E.any(),contentType:E.object({authorityId:E.string(),typeId:E.string(),versionMajor:E.number().gt(0),versionMinor:E.number().gte(0)}),reference:E.string()}),Ve=e=>{const{success:t}=Qe.safeParse(e);return t},Ye={codecs:[new C],contentTypes:[x.toString()],namespace:"replies",processors:{[x.toString()]:[async({message:e,db:t})=>{const n=S.fromString(e.contentType);if(x.sameAs(n)&&Ve(e.content)){const n=e.content;await(async(e,t,n)=>{const s=n.table("replies"),r=await s.where({referenceXmtpID:e,xmtpID:t}).first();return r?r.id:s.add({referenceXmtpID:e,xmtpID:t})})(n.reference,e.id,t)}}]},schema:{replies:"\n ++id,\n [referenceXmtpID+xmtpID],\n referenceXmtpID,\n xmtpID\n "},validators:{[x.toString()]:Ve}},Ze=e=>{const{getDbInstance:t}=ye(),[s,r]=n(void 0);return c((()=>{(async()=>{if(e){const n=await t(),s=await Je(e,n);s&&r(s)}})()}),[t,e]),{originalMessage:s}},et=e=>{const{getDbInstance:t}=ye();return h((async()=>{if(!e)return[];try{const n=await t();return await Ke(e,n)}catch{return[]}}),[e,t])??[]};export{_ as XMTPProvider,Be as attachmentContentTypeConfig,pe as bulkPutConsentState,k as clearCache,Z as deleteMessage,Le as getAttachment,ce as getCachedConsentEntries,ie as getCachedConsentEntriesMap,oe as getCachedConsentEntry,de as getCachedConsentState,U as getCachedConversationByPeerAddress,F as getCachedConversationByTopic,z as getConversationByTopic,q as getDbInstance,ae as getLastMessage,V as getMessageByXmtpID,Je as getOriginalMessageFromReply,Ue as getReactionsByXmtpID,Ke as getReplies,$ as hasConversationTopic,ze as hasReaction,He as hasReply,j as isValidAddress,le as loadConsentListFromCache,we as putConsentState,$e as reactionContentTypeConfig,Ye as replyContentTypeConfig,J as saveConversation,Y as saveMessage,G as setConversationUpdatedAt,X as textContentTypeConfig,K as toCachedConversation,Q as toCachedMessage,N as updateConversation,W as updateConversationMetadata,ee as updateMessage,te as updateMessageMetadata,_e as useAttachment,Me as useCanMessage,me as useClient,De as useConsent,fe as useConversation,he as useConversations,ye as useDb,Te as useLastMessage,ve as useMessage,Ee as useMessages,je as useReactions,et as useReplies,Ze as useReply,Se as useResendMessage,Ie as useSendMessage,Ae as useStartConversation,Ce as useStreamAllMessages,Xe as useStreamConsentList,be as useStreamConversations,xe as useStreamMessages};
//# sourceMappingURL=index.js.map
{
"name": "@xmtp/react-sdk",
"version": "8.0.1",
"version": "9.0.0",
"description": "XMTP client SDK for React apps written in TypeScript",

@@ -98,3 +98,3 @@ "keywords": [

"@xmtp/tsconfig": "workspace:*",
"@xmtp/xmtp-js": "^12.1.0",
"@xmtp/xmtp-js": "^13.0.0",
"eslint": "^8.57.0",

@@ -101,0 +101,0 @@ "eslint-config-xmtp-web": "workspace:*",

import { useCallback } from "react";
import type { ConsentState } from "@xmtp/xmtp-js";
import { useClient } from "@/hooks/useClient";

@@ -116,9 +117,15 @@ import { useDb } from "@/hooks/useDb";

const newEntries = await client.contacts.loadConsentList(startTime);
if (newEntries.length > 0) {
if (newEntries.size > 0) {
const addresses = Array.from(newEntries.entries())
.filter(([entry]) => entry.startsWith("address-"))
.map(
([entry, state]) =>
[entry.split("-")[1], state] as [string, ConsentState],
);
// update DB
await bulkPutConsentState(
newEntries.map((entry) => ({
value: entry.value,
addresses.map(([address, state]) => ({
value: address,
type: "address",
state: entry.permissionType,
state,
walletAddress: client.address,

@@ -142,9 +149,15 @@ })),

const newEntries = await client?.contacts.refreshConsentList();
if (newEntries.length > 0) {
if (newEntries.size > 0) {
const addresses = Array.from(newEntries.entries())
.filter(([entry]) => entry.startsWith("address-"))
.map(
([entry, state]) =>
[entry.split("-")[1], state] as [string, ConsentState],
);
// update DB
await bulkPutConsentState(
newEntries.map((entry) => ({
value: entry.value,
addresses.map(([address, state]) => ({
value: address,
type: "address",
state: entry.permissionType,
state,
walletAddress: client.address,

@@ -151,0 +164,0 @@ })),

Sorry, the diff of this file is not supported yet