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

@xmtp/react-sdk

Package Overview
Dependencies
Maintainers
7
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
7.0.0

5

lib/index.d.ts
import * as _xmtp_xmtp_js from '@xmtp/xmtp-js';
import { InvitationContext, Client, Conversation, SendOptions, DecodedMessage, decodeContent, ContentCodec, ClientOptions, ContentTypeId, ConsentState, ConsentListEntry, PrivatePreferencesAction } from '@xmtp/xmtp-js';
import { InvitationContext, Client, Conversation, SendOptions, DecodedMessage, decodeContent, ClientOptions, ConsentState, ConsentListEntry, PrivatePreferencesAction } from '@xmtp/xmtp-js';
export * from '@xmtp/xmtp-js';
export { Client, Compression, ContentTypeId, ContentTypeText, SortDirection } from '@xmtp/xmtp-js';
export { Client, Compression, SortDirection } from '@xmtp/xmtp-js';
import * as Dexie from 'dexie';
import Dexie__default, { Table, Dexie as Dexie$1 } from 'dexie';
import { ContentCodec, ContentTypeId } from '@xmtp/content-type-primitives';
import { Attachment, RemoteAttachment } from '@xmtp/content-type-remote-attachment';

@@ -8,0 +9,0 @@ import { Reaction } from '@xmtp/content-type-reaction';

2

lib/index.js

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

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

@@ -73,8 +73,10 @@ "keywords": [

"dependencies": {
"@xmtp/content-type-primitives": "^1.0.1",
"@xmtp/content-type-text": "^1.0.0",
"async-mutex": "^0.5.0",
"date-fns": "^3.4.0",
"date-fns": "^3.6.0",
"dexie": "^3.2.6",
"dexie-react-hooks": "^1.1.7",
"uuid": "^9.0.1",
"zod": "^3.22.4"
"uuid": "^10.0.0",
"zod": "^3.23.8"
},

@@ -91,7 +93,8 @@ "devDependencies": {

"@vitest/coverage-v8": "^1.3.1",
"@xmtp/content-type-reaction": "^1.1.7",
"@xmtp/content-type-remote-attachment": "^1.1.8",
"@xmtp/content-type-reply": "^1.1.9",
"@xmtp/content-type-reaction": "^1.1.9",
"@xmtp/content-type-remote-attachment": "^1.1.9",
"@xmtp/content-type-reply": "^1.1.11",
"@xmtp/content-type-text": "^1.0.0",
"@xmtp/tsconfig": "workspace:*",
"@xmtp/xmtp-js": "^11.5.0",
"@xmtp/xmtp-js": "^12.0.0",
"eslint": "^8.57.0",

@@ -115,2 +118,3 @@ "eslint-config-xmtp-web": "workspace:*",

"peerDependencies": {
"@xmtp/content-type-primitives": "^1.0.1",
"@xmtp/content-type-reaction": "^1.1.7",

@@ -117,0 +121,0 @@ "@xmtp/content-type-remote-attachment": "^1.1.8",

@@ -6,6 +6,6 @@ import type { Reaction } from "@xmtp/content-type-reaction";

} from "@xmtp/content-type-reaction";
import { ContentTypeId } from "@xmtp/xmtp-js";
import type { Dexie, Table } from "dexie";
import { Mutex } from "async-mutex";
import { z } from "zod";
import { ContentTypeId } from "@xmtp/content-type-primitives";
import type {

@@ -12,0 +12,0 @@ ContentTypeConfiguration,

import type { Reply } from "@xmtp/content-type-reply";
import { ReplyCodec, ContentTypeReply } from "@xmtp/content-type-reply";
import { ContentTypeId } from "@xmtp/xmtp-js";
import type { Dexie, Table } from "dexie";
import { z } from "zod";
import { ContentTypeId } from "@xmtp/content-type-primitives";
import type {

@@ -7,0 +7,0 @@ CachedMessage,

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

import { ContentTypeText } from "@xmtp/xmtp-js";
import { ContentTypeText } from "@xmtp/content-type-text";
import type { ContentTypeConfiguration } from "../db";

@@ -3,0 +3,0 @@

import Dexie from "dexie";
import type { Client, ContentCodec } from "@xmtp/xmtp-js";
import type { Client } from "@xmtp/xmtp-js";
import type { ContentCodec } from "@xmtp/content-type-primitives";
import type { CachedMessage } from "@/helpers/caching/messages";

@@ -4,0 +5,0 @@ import type { CachedConversation } from "./conversations";

@@ -7,3 +7,3 @@ import type {

} from "@xmtp/xmtp-js";
import { ContentTypeText, decodeContent } from "@xmtp/xmtp-js";
import { decodeContent } from "@xmtp/xmtp-js";
import type { Table } from "dexie";

@@ -13,2 +13,3 @@ import type Dexie from "dexie";

import { v4 } from "uuid";
import { ContentTypeText } from "@xmtp/content-type-text";
import type {

@@ -15,0 +16,0 @@ ContentTypeMessageProcessors,

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

import type { ContentCodec } from "@xmtp/xmtp-js";
import type { ContentCodec } from "@xmtp/content-type-primitives";
import {

@@ -3,0 +3,0 @@ defaultContentTypeConfigs,

import { useCallback, useContext } from "react";
import { ContentTypeText } from "@xmtp/xmtp-js";
import type { SendOptions, ContentTypeId } from "@xmtp/xmtp-js";
import type { SendOptions } from "@xmtp/xmtp-js";
import type { ContentTypeId } from "@xmtp/content-type-primitives";
import { ContentTypeText } from "@xmtp/content-type-text";
import { XMTPContext } from "@/contexts/XMTPContext";

@@ -5,0 +6,0 @@ import {

@@ -1,3 +0,4 @@

import type { ContentTypeId, DecodedMessage, SendOptions } from "@xmtp/xmtp-js";
import type { DecodedMessage, SendOptions } from "@xmtp/xmtp-js";
import { useCallback, useState } from "react";
import type { ContentTypeId } from "@xmtp/content-type-primitives";
import type { OnError } from "../sharedTypes";

@@ -4,0 +5,0 @@ import { type CachedConversation } from "@/helpers/caching/conversations";

import { useCallback, useState } from "react";
import type { ContentTypeId, InvitationContext } from "@xmtp/xmtp-js";
import type { InvitationContext } from "@xmtp/xmtp-js";
import type { ContentTypeId } from "@xmtp/content-type-primitives";
import { useClient } from "./useClient";

@@ -4,0 +5,0 @@ import type { OnError } from "../sharedTypes";

@@ -128,11 +128,5 @@ // context

export {
Client,
SortDirection,
ContentTypeId,
ContentTypeText,
Compression,
} from "@xmtp/xmtp-js";
export { Client, SortDirection, Compression } from "@xmtp/xmtp-js";
// re-export types from the JS SDK
export type * from "@xmtp/xmtp-js";

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet