diff --git a/dist/assets/Account-DBY_D3gV.js b/dist/assets/Account-DBY_D3gV.js new file mode 100644 index 00000000..7d823260 --- /dev/null +++ b/dist/assets/Account-DBY_D3gV.js @@ -0,0 +1,2 @@ +import{r as c,j as e}from"./react-vendor-C-OVADYf.js";import{u as _}from"./deployment-q_dUxQhv.js";import{w as D,x as O,y as X,b as l,s as C}from"./charts-D9P2NM_R.js";import{C as w}from"./assets-vq5YX_ys.js";import{u as T,f as L}from"./useAssetUsdEstimates-D3OGu5BF.js";import{A as F}from"./AddressLabelBadge-BTvgU-lx.js";import{f as M}from"./date-vendor-boStncAG.js";import"./vendor-CdKO02NA.js";import"./stellar-sdk-Cld1ipgo.js";import"./charts-vendor-BYXr-dPO.js";import"./icons-vendor-C7uAdRPq.js";function S(r,n){return r==="native"?"XLM":n||"Unknown"}function s({label:r,value:n,mono:o=!0,accent:p,copyValue:i,secondaryValue:x}){const f={fontSize:"12px",color:p||"var(--text-primary)",fontFamily:o?"var(--font-mono)":"var(--font-display)",wordBreak:"break-all",textAlign:"right"};return e.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"flex-start",gap:"16px",padding:"10px 18px",borderBottom:"1px solid var(--border)"},children:[e.jsx("span",{style:{fontSize:"11px",color:"var(--text-muted)",textTransform:"uppercase",letterSpacing:"0.8px",flexShrink:0},children:r}),e.jsxs("div",{style:{display:"flex",flexDirection:"column",alignItems:"flex-end",gap:"4px",minWidth:0},children:[i?e.jsx(w,{value:i,textStyle:f,children:n??"—"}):e.jsx("span",{style:f,children:n??"—"}),x&&e.jsx("span",{style:{fontSize:"11px",color:"var(--text-muted)",fontFamily:"var(--font-mono)"},children:x})]})]})}function Y(){const{accountData:r,connectedAddress:n,network:o,networkStats:p}=_(),[i,x]=c.useState([]),[f,y]=c.useState(!1),[z,h]=c.useState(null),[k,g]=c.useState(null),[W,m]=c.useState(!1),d=c.useMemo(()=>r?D(r,p,i.length):null,[r,p,i.length]);if(c.useEffect(()=>{if(!n){x([]),y(!1),h(null),g(null),m(!1);return}let t=!0;return y(!0),h(null),m(!0),g(null),O(n,o).then(a=>{t&&g(a)}).finally(()=>{t&&m(!1)}),X(n,o).then(a=>{t&&x(a)}).catch(a=>{t&&h(a.message)}).finally(()=>{t&&y(!1)}),()=>{t=!1}},[n,o]),!r)return e.jsx("div",{style:{padding:"32px",textAlign:"center",color:"var(--text-muted)"},children:"No account loaded"});const v=r.balances?.find(t=>t.asset_type==="native"),b=r.balances?.filter(t=>t.asset_type!=="native")||[],u=r.signers||[],I=r.flags||{},j=r.thresholds||{},E=W?"Loading...":k?M(new Date(k),"MMM d, yyyy"):"Unknown",{getEstimate:R}=T({balances:r?.balances||[],connectedAddress:n,network:o,refreshKey:r}),A=v?R(v):null;return e.jsxs("div",{className:"animate-in",style:{display:"flex",flexDirection:"column",gap:"20px"},children:[e.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",gap:"12px",flexWrap:"wrap"},children:[e.jsx("div",{style:{fontFamily:"var(--font-display)",fontSize:"22px",fontWeight:700},children:"Account Detail"}),e.jsx(DataSourceBadge,{dataSource,offline})]}),offline&&r&&e.jsxs("div",{style:{display:"flex",alignItems:"flex-start",gap:"10px",padding:"12px 16px",background:dataSource==="cache-stale"?"var(--amber-glow)":"var(--bg-elevated)",border:`1px solid ${dataSource==="cache-stale"?"var(--amber)":"var(--border)"}`,borderRadius:"var(--radius-md)",color:dataSource==="cache-stale"?"var(--amber)":"var(--text-muted)",fontSize:"12px",lineHeight:1.5},children:[e.jsx("span",{style:{fontSize:"16px",flexShrink:0},children:dataSource==="cache-stale"?"⚠":"ℹ"}),e.jsxs("div",{style:{flex:1,minWidth:0},children:[e.jsx("div",{style:{fontWeight:600,color:dataSource==="cache-stale"?"var(--amber)":"var(--text-secondary)",marginBottom:"2px"},children:dataSource==="cache-stale"?"Using stale cached data":"Offline read-only mode"}),e.jsx("div",{children:dataSource==="cache-stale"?"Cached account data is older than 5 minutes. All write actions are disabled. Reconnect to refresh.":"Displaying last-known cached account data. Write actions (faucet, contract invocation, transaction submission) are blocked until reconnected."}),accountCachedAt&&e.jsxs("div",{style:{marginTop:"4px",fontSize:"11px",color:"var(--text-muted)",fontFamily:"var(--font-mono)"},children:["Last cached: ",M(new Date(accountCachedAt),"MMM d, yyyy HH:mm:ss")]})]})]}),e.jsxs("div",{style:{background:"var(--bg-card)",border:"1px solid var(--border)",borderRadius:"var(--radius-lg)",overflow:"hidden"},children:[e.jsx("div",{style:{padding:"14px 18px",borderBottom:"1px solid var(--border)",fontFamily:"var(--font-display)",fontWeight:600,fontSize:"13px"},children:"Identity"}),e.jsx(s,{label:"Public Key",value:n,copyValue:n??void 0}),e.jsx(s,{label:"Account ID",value:r.account_id,copyValue:r.account_id}),e.jsx(s,{label:"Sequence",value:r.sequence}),e.jsx(s,{label:"Created",value:E,mono:!1}),e.jsx(s,{label:"XLM Balance",value:v?l(v.balance)+" XLM":"—",accent:"var(--cyan)",secondaryValue:A?`Est. ${L(A.usd)}`:null}),e.jsx(s,{label:"Subentry Count",value:r.subentry_count}),e.jsx("div",{style:{padding:"10px 18px"},children:e.jsx("a",{href:`https://stellar.expert/explorer/${o}/account/${n}`,target:"_blank",rel:"noopener noreferrer",style:{fontSize:"12px",color:"var(--cyan)",display:"inline-flex",alignItems:"center",gap:"4px"},children:"View on Stellar Expert ↗"})})]}),d&&e.jsxs("div",{style:{background:"var(--bg-card)",border:"1px solid var(--border)",borderRadius:"var(--radius-lg)",overflow:"hidden"},children:[e.jsx("div",{style:{padding:"14px 18px",borderBottom:"1px solid var(--border)",fontFamily:"var(--font-display)",fontWeight:600,fontSize:"13px"},children:"Reserve Breakdown"}),e.jsx(s,{label:"Base Reserve",value:l(d.baseReserve)+" XLM"}),e.jsx(s,{label:"Signer Reserve",value:l(d.signerReserve)+" XLM"}),e.jsx(s,{label:"Asset Reserve",value:l(d.assetReserve)+" XLM"}),e.jsx(s,{label:"Offer Reserve",value:l(d.offerReserve)+" XLM"}),e.jsx(s,{label:"Subentry Reserve",value:l(d.subentryReserve)+" XLM"}),e.jsx("div",{style:{padding:"12px 18px",borderBottom:"1px solid var(--border)",background:"var(--bg-elevated)"},children:e.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center"},children:[e.jsx("span",{style:{fontSize:"11px",color:"var(--text-muted)",textTransform:"uppercase",letterSpacing:"0.8px"},children:"Total Locked"}),e.jsxs("span",{style:{fontSize:"12px",color:"var(--amber)",fontFamily:"var(--font-mono)",fontWeight:600},children:[l(d.totalReserves)," XLM"]})]})}),e.jsx("div",{style:{padding:"12px 18px",borderBottom:"1px solid var(--border)",background:"var(--cyan-glow-sm)"},children:e.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center"},children:[e.jsx("span",{style:{fontSize:"11px",color:"var(--text-muted)",textTransform:"uppercase",letterSpacing:"0.8px"},children:"Available Spendable"}),e.jsxs("span",{style:{fontSize:"12px",color:"var(--cyan)",fontFamily:"var(--font-mono)",fontWeight:600},children:[l(d.availableBalance)," XLM"]})]})}),e.jsx("div",{style:{padding:"10px 18px"},children:e.jsx("a",{href:"https://developers.stellar.org/docs/glossary/fees/#minimum-balance",target:"_blank",rel:"noopener noreferrer",style:{fontSize:"12px",color:"var(--cyan)",display:"inline-flex",alignItems:"center",gap:"4px"},children:"Learn about Stellar reserves ↗"})})]}),e.jsxs("div",{style:{background:"var(--bg-card)",border:"1px solid var(--border)",borderRadius:"var(--radius-lg)",overflow:"hidden"},children:[e.jsx("div",{style:{padding:"14px 18px",borderBottom:"1px solid var(--border)",fontFamily:"var(--font-display)",fontWeight:600,fontSize:"13px"},children:"Asset Balances"}),b.length===0?e.jsx("div",{style:{padding:"16px 18px",fontSize:"12px",color:"var(--text-muted)"},children:"No non-native assets"}):b.map((t,a)=>{const B=R(t);return e.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",gap:"16px",padding:"12px 18px",borderBottom:ae.jsxs("div",{style:{display:"flex",justifyContent:"space-between",padding:"10px 18px",borderBottom:"1px solid var(--border)"},children:[e.jsx("span",{style:{fontSize:"11px",color:"var(--text-muted)",textTransform:"uppercase",letterSpacing:"0.8px"},children:t.replace(/_/g," ")}),e.jsx("span",{style:{fontSize:"11px",padding:"2px 8px",borderRadius:"3px",background:a?"var(--green-glow)":"var(--bg-elevated)",border:`1px solid ${a?"var(--green)":"var(--border)"}`,color:a?"var(--green)":"var(--text-muted)"},children:a?"TRUE":"FALSE"})]},t))]}),u.length>0&&e.jsxs("div",{style:{background:"var(--bg-card)",border:"1px solid var(--border)",borderRadius:"var(--radius-lg)",overflow:"hidden"},children:[e.jsxs("div",{style:{padding:"14px 18px",borderBottom:"1px solid var(--border)",fontFamily:"var(--font-display)",fontWeight:600,fontSize:"13px"},children:["Signers (",u.length,")"]}),u.map((t,a)=>e.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",padding:"10px 18px",borderBottom:ae.jsxs("div",{style:{padding:"12px 18px",borderBottom:a_.getState().setActiveTab("claimableBalances"),style:{padding:"8px 14px",borderRadius:"var(--radius-sm)",border:"1px solid var(--cyan-dim)",background:"var(--cyan-glow)",color:"var(--cyan)",fontSize:"12px",fontFamily:"var(--font-mono)",cursor:"pointer"},children:"View ⊛"})]})]})}export{Y as default}; +//# sourceMappingURL=Account-DBY_D3gV.js.map diff --git a/dist/assets/Account-DBY_D3gV.js.map b/dist/assets/Account-DBY_D3gV.js.map new file mode 100644 index 00000000..487351cb --- /dev/null +++ b/dist/assets/Account-DBY_D3gV.js.map @@ -0,0 +1 @@ +{"version":3,"file":"Account-DBY_D3gV.js","sources":["../../src/components/dashboard/Account.tsx"],"sourcesContent":["import React, { useEffect, useState, useMemo } from 'react';\r\nimport { format } from 'date-fns';\r\nimport type { Horizon } from '@stellar/stellar-sdk';\r\nimport { useStore } from '../../lib/store';\r\nimport {\r\n shortAddress,\r\n formatXLM,\r\n fetchAccountCreationDate,\r\n fetchAccountOffers,\r\n calculateAccountReserves,\r\n} from '../../lib/stellar';\r\nimport CopyableValue from './CopyableValue';\r\nimport useAssetUsdEstimates, { formatEstimatedUsd } from '../../hooks/useAssetUsdEstimates';\r\nimport AddressLabelBadge from '../addressLabels/AddressLabelBadge';\r\nimport type { AccountOffer, ReservesInfo, InfoRowProps } from './types';\r\n\r\nfunction formatAsset(assetType: string, assetCode?: string): string {\r\n if (assetType === 'native') return 'XLM';\r\n return assetCode || 'Unknown';\r\n}\r\n\r\nfunction InfoRow({ label, value, mono = true, accent, copyValue, secondaryValue }: InfoRowProps) {\r\n const textStyle: React.CSSProperties = {\r\n fontSize: '12px',\r\n color: accent || 'var(--text-primary)',\r\n fontFamily: mono ? 'var(--font-mono)' : 'var(--font-display)',\r\n wordBreak: 'break-all',\r\n textAlign: 'right',\r\n };\r\n\r\n return (\r\n \r\n \r\n {label}\r\n \r\n \r\n {copyValue ? (\r\n \r\n {value ?? '—'}\r\n \r\n ) : (\r\n {value ?? '—'}\r\n )}\r\n {secondaryValue && (\r\n \r\n {secondaryValue}\r\n \r\n )}\r\n \r\n \r\n );\r\n}\r\n\r\nexport default function Account() {\r\n const { accountData, connectedAddress, network, networkStats } = useStore();\r\n const [offers, setOffers] = useState([]);\r\n const [offersLoading, setOffersLoading] = useState(false);\r\n const [offersError, setOffersError] = useState(null);\r\n const [createdAt, setCreatedAt] = useState(null);\r\n const [createdAtLoading, setCreatedAtLoading] = useState(false);\r\n\r\n const reserves = useMemo(() => {\r\n if (!accountData) return null;\r\n return calculateAccountReserves(accountData, networkStats, offers.length);\r\n }, [accountData, networkStats, offers.length]);\r\n\r\n useEffect(() => {\r\n if (!connectedAddress) {\r\n setOffers([]);\r\n setOffersLoading(false);\r\n setOffersError(null);\r\n setCreatedAt(null);\r\n setCreatedAtLoading(false);\r\n return;\r\n }\r\n\r\n let isActive = true;\r\n\r\n setOffersLoading(true);\r\n setOffersError(null);\r\n setCreatedAtLoading(true);\r\n setCreatedAt(null);\r\n\r\n fetchAccountCreationDate(connectedAddress, network)\r\n .then((date: Date) => {\r\n if (!isActive) return;\r\n setCreatedAt(date);\r\n })\r\n .finally(() => {\r\n if (!isActive) return;\r\n setCreatedAtLoading(false);\r\n });\r\n\r\n fetchAccountOffers(connectedAddress, network)\r\n .then((res: AccountOffer[]) => {\r\n if (!isActive) return;\r\n setOffers(res);\r\n })\r\n .catch((err: Error) => {\r\n if (!isActive) return;\r\n setOffersError(err.message);\r\n })\r\n .finally(() => {\r\n if (!isActive) return;\r\n setOffersLoading(false);\r\n });\r\n\r\n return () => {\r\n isActive = false;\r\n };\r\n }, [connectedAddress, network]);\r\n\r\n if (!accountData)\r\n return (\r\n
\r\n No account loaded\r\n
\r\n );\r\n\r\n const xlm = accountData.balances?.find((b: { asset_type: string }) => b.asset_type === 'native');\r\n const otherAssets =\r\n accountData.balances?.filter((b: { asset_type: string }) => b.asset_type !== 'native') || [];\r\n const signers = accountData.signers || [];\r\n const flags = accountData.flags || {};\r\n const thresholds = accountData.thresholds || {};\r\n const createdValue = createdAtLoading\r\n ? 'Loading...'\r\n : createdAt\r\n ? format(new Date(createdAt), 'MMM d, yyyy')\r\n : 'Unknown';\r\n const { getEstimate } = useAssetUsdEstimates({\r\n balances: accountData?.balances || [],\r\n connectedAddress,\r\n network,\r\n refreshKey: accountData,\r\n });\r\n const xlmEstimate = xlm ? getEstimate(xlm) : null;\r\n\r\n return (\r\n
\r\n \r\n
\r\n Account Detail\r\n
\r\n \r\n
\r\n\r\n {offline && accountData && (\r\n \r\n \r\n {dataSource === 'cache-stale' ? '⚠' : 'ℹ'}\r\n \r\n
\r\n \r\n {dataSource === 'cache-stale' ? 'Using stale cached data' : 'Offline read-only mode'}\r\n
\r\n
\r\n {dataSource === 'cache-stale'\r\n ? 'Cached account data is older than 5 minutes. All write actions are disabled. Reconnect to refresh.'\r\n : 'Displaying last-known cached account data. Write actions (faucet, contract invocation, transaction submission) are blocked until reconnected.'}\r\n
\r\n {accountCachedAt && (\r\n \r\n Last cached: {format(new Date(accountCachedAt), 'MMM d, yyyy HH:mm:ss')}\r\n \r\n )}\r\n \r\n \r\n )}\r\n\r\n \r\n \r\n Identity\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n \r\n View on Stellar Expert ↗\r\n \r\n
\r\n \r\n\r\n {reserves && (\r\n \r\n \r\n Reserve Breakdown\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n \r\n Total Locked\r\n \r\n \r\n {formatXLM(reserves.totalReserves)} XLM\r\n \r\n
\r\n \r\n \r\n
\r\n \r\n Available Spendable\r\n \r\n \r\n {formatXLM(reserves.availableBalance)} XLM\r\n \r\n
\r\n \r\n
\r\n \r\n Learn about Stellar reserves ↗\r\n \r\n
\r\n \r\n )}\r\n\r\n \r\n \r\n Asset Balances\r\n \r\n {otherAssets.length === 0 ? (\r\n
\r\n No non-native assets\r\n
\r\n ) : (\r\n otherAssets.map((asset: Horizon.BalanceLine, index: number) => {\r\n const estimate = getEstimate(asset);\r\n\r\n return (\r\n \r\n
\r\n
\r\n {formatAsset(asset.asset_type, (asset as Horizon.BalanceLineAsset).asset_code)}\r\n
\r\n {(asset as Horizon.BalanceLineAsset).asset_issuer && (\r\n \r\n \r\n {shortAddress((asset as Horizon.BalanceLineAsset).asset_issuer)}\r\n \r\n )}\r\n
\r\n \r\n \r\n {formatXLM(asset.balance)}\r\n \r\n {estimate && (\r\n \r\n Est. {formatEstimatedUsd(estimate.usd)}\r\n \r\n )}\r\n \r\n \r\n );\r\n })\r\n )}\r\n \r\n\r\n \r\n \r\n Thresholds\r\n \r\n \r\n \r\n \r\n \r\n\r\n \r\n \r\n Flags\r\n \r\n {Object.entries(flags).map(([key, val]) => (\r\n \r\n \r\n {key.replace(/_/g, ' ')}\r\n \r\n \r\n {val ? 'TRUE' : 'FALSE'}\r\n \r\n \r\n ))}\r\n \r\n\r\n {signers.length > 0 && (\r\n \r\n \r\n Signers ({signers.length})\r\n \r\n {signers.map((s: Horizon.AccountSigner, i: number) => (\r\n \r\n \r\n \r\n {shortAddress(s.key)}\r\n \r\n \r\n weight: {s.weight}\r\n \r\n \r\n ))}\r\n \r\n )}\r\n\r\n \r\n \r\n Open Offers\r\n \r\n {offersLoading ? (\r\n
\r\n Loading offers...\r\n
\r\n ) : offersError ? (\r\n
\r\n Error: {offersError}\r\n
\r\n ) : offers.length === 0 ? (\r\n
\r\n No open offers\r\n
\r\n ) : (\r\n
\r\n {offers.map((offer, i) => (\r\n \r\n \r\n \r\n Offer ID: {offer.id}\r\n \r\n \r\n View ↗\r\n \r\n
\r\n
\r\n
\r\n Selling:{' '}\r\n {formatXLM(offer.amount)}{' '}\r\n {formatAsset(offer.selling.asset_type, offer.selling.asset_code)}\r\n
\r\n
\r\n Buying:{' '}\r\n {formatAsset(offer.buying.asset_type, offer.buying.asset_code)}\r\n
\r\n
\r\n
\r\n
\r\n Price: {offer.price}\r\n
\r\n
\r\n Ratio: {offer.price_r.n}/\r\n {offer.price_r.d}\r\n
\r\n
\r\n \r\n ))}\r\n \r\n )}\r\n \r\n\r\n \r\n
\r\n \r\n Claimable Balances\r\n
\r\n
\r\n View and simulate claiming pending balances\r\n
\r\n \r\n useStore.getState().setActiveTab('claimableBalances')}\r\n style={{\r\n padding: '8px 14px',\r\n borderRadius: 'var(--radius-sm)',\r\n border: '1px solid var(--cyan-dim)',\r\n background: 'var(--cyan-glow)',\r\n color: 'var(--cyan)',\r\n fontSize: '12px',\r\n fontFamily: 'var(--font-mono)',\r\n cursor: 'pointer',\r\n }}\r\n >\r\n View ⊛\r\n \r\n \r\n \r\n );\r\n}\r\n"],"names":["formatAsset","assetType","assetCode","InfoRow","label","value","mono","accent","copyValue","secondaryValue","textStyle","jsxs","jsx","CopyableValue","Account","accountData","connectedAddress","network","networkStats","useStore","offers","setOffers","useState","offersLoading","setOffersLoading","offersError","setOffersError","createdAt","setCreatedAt","createdAtLoading","setCreatedAtLoading","reserves","useMemo","calculateAccountReserves","useEffect","isActive","fetchAccountCreationDate","date","fetchAccountOffers","res","err","xlm","b","otherAssets","signers","flags","thresholds","createdValue","format","getEstimate","useAssetUsdEstimates","xlmEstimate","formatXLM","formatEstimatedUsd","asset","index","estimate","AddressLabelBadge","shortAddress","key","val","s","i","offer"],"mappings":"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"} \ No newline at end of file diff --git a/dist/assets/Account-DVnu8bsp.js b/dist/assets/Account-DVnu8bsp.js deleted file mode 100644 index 364e53b5..00000000 --- a/dist/assets/Account-DVnu8bsp.js +++ /dev/null @@ -1,2 +0,0 @@ -import{r as x,j as e}from"./react-vendor-CsepHXsi.js";import{u as B}from"./deployment-BPDW632H.js";import{w as W,x as X,y as D,b as l,s as L}from"./charts-OWQBHTRD.js";import{C as w}from"./assets-dICfUuxl.js";import{u as O,f as F}from"./useAssetUsdEstimates-Debo4POu.js";import{A as C}from"./AddressLabelBadge-DrPlZQOF.js";import{f as T}from"./date-vendor-boStncAG.js";import"./vendor-Du79euYq.js";import"./stellar-sdk-or8ZbYCb.js";import"./charts-vendor-BIh5SzZ7.js";import"./icons-vendor-BqasJArU.js";function S(t,a){return t==="native"?"XLM":a||"Unknown"}function n({label:t,value:a,mono:o=!0,accent:c,copyValue:i,secondaryValue:p}){const f={fontSize:"12px",color:c||"var(--text-primary)",fontFamily:o?"var(--font-mono)":"var(--font-display)",wordBreak:"break-all",textAlign:"right"};return e.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"flex-start",gap:"16px",padding:"10px 18px",borderBottom:"1px solid var(--border)"},children:[e.jsx("span",{style:{fontSize:"11px",color:"var(--text-muted)",textTransform:"uppercase",letterSpacing:"0.8px",flexShrink:0},children:t}),e.jsxs("div",{style:{display:"flex",flexDirection:"column",alignItems:"flex-end",gap:"4px",minWidth:0},children:[i?e.jsx(w,{value:i,textStyle:f,children:a??"—"}):e.jsx("span",{style:f,children:a??"—"}),p&&e.jsx("span",{style:{fontSize:"11px",color:"var(--text-muted)",fontFamily:"var(--font-mono)"},children:p})]})]})}function Y(){const{accountData:t,connectedAddress:a,network:o,networkStats:c}=B(),[i,p]=x.useState([]),[f,y]=x.useState(!1),[z,g]=x.useState(null),[k,m]=x.useState(null),[M,h]=x.useState(!1),d=x.useMemo(()=>t?W(t,c,i.length):null,[t,c,i.length]);if(x.useEffect(()=>{if(!a){p([]),y(!1),g(null),m(null),h(!1);return}let r=!0;return y(!0),g(null),h(!0),m(null),X(a,o).then(s=>{r&&m(s)}).finally(()=>{r&&h(!1)}),D(a,o).then(s=>{r&&p(s)}).catch(s=>{r&&g(s.message)}).finally(()=>{r&&y(!1)}),()=>{r=!1}},[a,o]),!t)return e.jsx("div",{style:{padding:"32px",textAlign:"center",color:"var(--text-muted)"},children:"No account loaded"});const v=t.balances?.find(r=>r.asset_type==="native"),b=t.balances?.filter(r=>r.asset_type!=="native")||[],u=t.signers||[],E=t.flags||{},j=t.thresholds||{},I=M?"Loading...":k?T(new Date(k),"MMM d, yyyy"):"Unknown",{getEstimate:R}=O({balances:t?.balances||[],connectedAddress:a,network:o,refreshKey:t}),_=v?R(v):null;return e.jsxs("div",{className:"animate-in",style:{display:"flex",flexDirection:"column",gap:"20px"},children:[e.jsx("div",{style:{fontFamily:"var(--font-display)",fontSize:"22px",fontWeight:700},children:"Account Detail"}),e.jsxs("div",{style:{background:"var(--bg-card)",border:"1px solid var(--border)",borderRadius:"var(--radius-lg)",overflow:"hidden"},children:[e.jsx("div",{style:{padding:"14px 18px",borderBottom:"1px solid var(--border)",fontFamily:"var(--font-display)",fontWeight:600,fontSize:"13px"},children:"Identity"}),e.jsx(n,{label:"Public Key",value:a,copyValue:a??void 0}),e.jsx(n,{label:"Account ID",value:t.account_id,copyValue:t.account_id}),e.jsx(n,{label:"Sequence",value:t.sequence}),e.jsx(n,{label:"Created",value:I,mono:!1}),e.jsx(n,{label:"XLM Balance",value:v?l(v.balance)+" XLM":"—",accent:"var(--cyan)",secondaryValue:_?`Est. ${F(_.usd)}`:null}),e.jsx(n,{label:"Subentry Count",value:t.subentry_count}),e.jsx("div",{style:{padding:"10px 18px"},children:e.jsx("a",{href:`https://stellar.expert/explorer/${o}/account/${a}`,target:"_blank",rel:"noopener noreferrer",style:{fontSize:"12px",color:"var(--cyan)",display:"inline-flex",alignItems:"center",gap:"4px"},children:"View on Stellar Expert ↗"})})]}),d&&e.jsxs("div",{style:{background:"var(--bg-card)",border:"1px solid var(--border)",borderRadius:"var(--radius-lg)",overflow:"hidden"},children:[e.jsx("div",{style:{padding:"14px 18px",borderBottom:"1px solid var(--border)",fontFamily:"var(--font-display)",fontWeight:600,fontSize:"13px"},children:"Reserve Breakdown"}),e.jsx(n,{label:"Base Reserve",value:l(d.baseReserve)+" XLM"}),e.jsx(n,{label:"Signer Reserve",value:l(d.signerReserve)+" XLM"}),e.jsx(n,{label:"Asset Reserve",value:l(d.assetReserve)+" XLM"}),e.jsx(n,{label:"Offer Reserve",value:l(d.offerReserve)+" XLM"}),e.jsx(n,{label:"Subentry Reserve",value:l(d.subentryReserve)+" XLM"}),e.jsx("div",{style:{padding:"12px 18px",borderBottom:"1px solid var(--border)",background:"var(--bg-elevated)"},children:e.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center"},children:[e.jsx("span",{style:{fontSize:"11px",color:"var(--text-muted)",textTransform:"uppercase",letterSpacing:"0.8px"},children:"Total Locked"}),e.jsxs("span",{style:{fontSize:"12px",color:"var(--amber)",fontFamily:"var(--font-mono)",fontWeight:600},children:[l(d.totalReserves)," XLM"]})]})}),e.jsx("div",{style:{padding:"12px 18px",borderBottom:"1px solid var(--border)",background:"var(--cyan-glow-sm)"},children:e.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center"},children:[e.jsx("span",{style:{fontSize:"11px",color:"var(--text-muted)",textTransform:"uppercase",letterSpacing:"0.8px"},children:"Available Spendable"}),e.jsxs("span",{style:{fontSize:"12px",color:"var(--cyan)",fontFamily:"var(--font-mono)",fontWeight:600},children:[l(d.availableBalance)," XLM"]})]})}),e.jsx("div",{style:{padding:"10px 18px"},children:e.jsx("a",{href:"https://developers.stellar.org/docs/glossary/fees/#minimum-balance",target:"_blank",rel:"noopener noreferrer",style:{fontSize:"12px",color:"var(--cyan)",display:"inline-flex",alignItems:"center",gap:"4px"},children:"Learn about Stellar reserves ↗"})})]}),e.jsxs("div",{style:{background:"var(--bg-card)",border:"1px solid var(--border)",borderRadius:"var(--radius-lg)",overflow:"hidden"},children:[e.jsx("div",{style:{padding:"14px 18px",borderBottom:"1px solid var(--border)",fontFamily:"var(--font-display)",fontWeight:600,fontSize:"13px"},children:"Asset Balances"}),b.length===0?e.jsx("div",{style:{padding:"16px 18px",fontSize:"12px",color:"var(--text-muted)"},children:"No non-native assets"}):b.map((r,s)=>{const A=R(r);return e.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",gap:"16px",padding:"12px 18px",borderBottom:se.jsxs("div",{style:{display:"flex",justifyContent:"space-between",padding:"10px 18px",borderBottom:"1px solid var(--border)"},children:[e.jsx("span",{style:{fontSize:"11px",color:"var(--text-muted)",textTransform:"uppercase",letterSpacing:"0.8px"},children:r.replace(/_/g," ")}),e.jsx("span",{style:{fontSize:"11px",padding:"2px 8px",borderRadius:"3px",background:s?"var(--green-glow)":"var(--bg-elevated)",border:`1px solid ${s?"var(--green)":"var(--border)"}`,color:s?"var(--green)":"var(--text-muted)"},children:s?"TRUE":"FALSE"})]},r))]}),u.length>0&&e.jsxs("div",{style:{background:"var(--bg-card)",border:"1px solid var(--border)",borderRadius:"var(--radius-lg)",overflow:"hidden"},children:[e.jsxs("div",{style:{padding:"14px 18px",borderBottom:"1px solid var(--border)",fontFamily:"var(--font-display)",fontWeight:600,fontSize:"13px"},children:["Signers (",u.length,")"]}),u.map((r,s)=>e.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",padding:"10px 18px",borderBottom:se.jsxs("div",{style:{padding:"12px 18px",borderBottom:sB.getState().setActiveTab("claimableBalances"),style:{padding:"8px 14px",borderRadius:"var(--radius-sm)",border:"1px solid var(--cyan-dim)",background:"var(--cyan-glow)",color:"var(--cyan)",fontSize:"12px",fontFamily:"var(--font-mono)",cursor:"pointer"},children:"View ⊛"})]})]})}export{Y as default}; -//# sourceMappingURL=Account-DVnu8bsp.js.map diff --git a/dist/assets/Account-DVnu8bsp.js.map b/dist/assets/Account-DVnu8bsp.js.map deleted file mode 100644 index 5b8875b9..00000000 --- a/dist/assets/Account-DVnu8bsp.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"Account-DVnu8bsp.js","sources":["../../src/components/dashboard/Account.tsx"],"sourcesContent":["import React, { useEffect, useState, useMemo } from 'react'\nimport { format } from 'date-fns'\nimport type { Horizon } from '@stellar/stellar-sdk'\nimport { useStore } from '../../lib/store'\nimport { shortAddress, formatXLM, fetchAccountCreationDate, fetchAccountOffers, calculateAccountReserves } from '../../lib/stellar'\nimport CopyableValue from './CopyableValue'\nimport useAssetUsdEstimates, { formatEstimatedUsd } from '../../hooks/useAssetUsdEstimates'\nimport AddressLabelBadge from '../addressLabels/AddressLabelBadge'\nimport type { AccountOffer, ReservesInfo, InfoRowProps } from './types'\n\nfunction formatAsset(assetType: string, assetCode?: string): string {\n if (assetType === 'native') return 'XLM'\n return assetCode || 'Unknown'\n}\n\nfunction InfoRow({ label, value, mono = true, accent, copyValue, secondaryValue }: InfoRowProps) {\n const textStyle: React.CSSProperties = {\n fontSize: '12px',\n color: accent || 'var(--text-primary)',\n fontFamily: mono ? 'var(--font-mono)' : 'var(--font-display)',\n wordBreak: 'break-all',\n textAlign: 'right',\n }\n\n return (\n
\n {label}\n
\n {copyValue ? (\n \n {value ?? '—'}\n \n ) : (\n {value ?? '—'}\n )}\n {secondaryValue && (\n \n {secondaryValue}\n \n )}\n
\n
\n )\n}\n\nexport default function Account() {\n const { accountData, connectedAddress, network, networkStats } = useStore()\n const [offers, setOffers] = useState([])\n const [offersLoading, setOffersLoading] = useState(false)\n const [offersError, setOffersError] = useState(null)\n const [createdAt, setCreatedAt] = useState(null)\n const [createdAtLoading, setCreatedAtLoading] = useState(false)\n\n const reserves = useMemo(() => {\n if (!accountData) return null\n return calculateAccountReserves(accountData, networkStats, offers.length)\n }, [accountData, networkStats, offers.length])\n\n useEffect(() => {\n if (!connectedAddress) {\n setOffers([])\n setOffersLoading(false)\n setOffersError(null)\n setCreatedAt(null)\n setCreatedAtLoading(false)\n return\n }\n\n let isActive = true\n\n setOffersLoading(true)\n setOffersError(null)\n setCreatedAtLoading(true)\n setCreatedAt(null)\n\n fetchAccountCreationDate(connectedAddress, network)\n .then((date: Date) => {\n if (!isActive) return\n setCreatedAt(date)\n })\n .finally(() => {\n if (!isActive) return\n setCreatedAtLoading(false)\n })\n\n fetchAccountOffers(connectedAddress, network)\n .then((res: AccountOffer[]) => {\n if (!isActive) return\n setOffers(res)\n })\n .catch((err: Error) => {\n if (!isActive) return\n setOffersError(err.message)\n })\n .finally(() => {\n if (!isActive) return\n setOffersLoading(false)\n })\n\n return () => {\n isActive = false\n }\n }, [connectedAddress, network])\n\n if (!accountData) return (\n
No account loaded
\n )\n\n const xlm = accountData.balances?.find((b: { asset_type: string }) => b.asset_type === 'native')\n const otherAssets = accountData.balances?.filter((b: { asset_type: string }) => b.asset_type !== 'native') || []\n const signers = accountData.signers || []\n const flags = accountData.flags || {}\n const thresholds = accountData.thresholds || {}\n const createdValue = createdAtLoading ? 'Loading...' : createdAt ? format(new Date(createdAt), 'MMM d, yyyy') : 'Unknown'\n const { getEstimate } = useAssetUsdEstimates({\n balances: accountData?.balances || [],\n connectedAddress,\n network,\n refreshKey: accountData,\n })\n const xlmEstimate = xlm ? getEstimate(xlm) : null\n\n return (\n
\n
Account Detail
\n\n
\n
Identity
\n \n \n \n \n \n \n
\n \n View on Stellar Expert ↗\n \n
\n
\n\n {reserves && (\n
\n
\n Reserve Breakdown\n
\n \n \n \n \n \n
\n
\n \n Total Locked\n \n \n {formatXLM(reserves.totalReserves)} XLM\n \n
\n
\n
\n
\n \n Available Spendable\n \n \n {formatXLM(reserves.availableBalance)} XLM\n \n
\n
\n
\n \n Learn about Stellar reserves ↗\n \n
\n
\n )}\n\n
\n
\n Asset Balances\n
\n {otherAssets.length === 0 ? (\n
No non-native assets
\n ) : (\n otherAssets.map((asset: Horizon.BalanceLine, index: number) => {\n const estimate = getEstimate(asset)\n\n return (\n \n
\n
\n {formatAsset(asset.asset_type, (asset as Horizon.BalanceLineAsset).asset_code)}\n
\n {(asset as Horizon.BalanceLineAsset).asset_issuer && (\n \n \n {shortAddress((asset as Horizon.BalanceLineAsset).asset_issuer)}\n \n )}\n
\n
\n \n {formatXLM(asset.balance)}\n \n {estimate && (\n \n Est. {formatEstimatedUsd(estimate.usd)}\n \n )}\n
\n
\n )\n })\n )}\n
\n\n
\n
Thresholds
\n \n \n \n
\n\n
\n
Flags
\n {Object.entries(flags).map(([key, val]) => (\n
\n \n {key.replace(/_/g, ' ')}\n \n \n {val ? 'TRUE' : 'FALSE'}\n \n
\n ))}\n
\n\n {signers.length > 0 && (\n
\n
\n Signers ({signers.length})\n
\n {signers.map((s: Horizon.AccountSigner, i: number) => (\n
\n \n \n {shortAddress(s.key)}\n \n weight: {s.weight}\n
\n ))}\n
\n )}\n\n
\n
\n Open Offers\n
\n {offersLoading ? (\n
Loading offers...
\n ) : offersError ? (\n
Error: {offersError}
\n ) : offers.length === 0 ? (\n
No open offers
\n ) : (\n
\n {offers.map((offer, i) => (\n
\n
\n Offer ID: {offer.id}\n \n View ↗\n \n
\n
\n
Selling: {formatXLM(offer.amount)} {formatAsset(offer.selling.asset_type, offer.selling.asset_code)}
\n
Buying: {formatAsset(offer.buying.asset_type, offer.buying.asset_code)}
\n
\n
\n
Price: {offer.price}
\n
Ratio: {offer.price_r.n}/{offer.price_r.d}
\n
\n
\n ))}\n
\n )}\n
\n\n
\n
\n
Claimable Balances
\n
View and simulate claiming pending balances
\n
\n useStore.getState().setActiveTab('claimableBalances')}\n style={{\n padding: '8px 14px',\n borderRadius: 'var(--radius-sm)',\n border: '1px solid var(--cyan-dim)',\n background: 'var(--cyan-glow)',\n color: 'var(--cyan)',\n fontSize: '12px',\n fontFamily: 'var(--font-mono)',\n cursor: 'pointer',\n }}\n >\n View ⊛\n \n
\n \n )\n}\n"],"names":["formatAsset","assetType","assetCode","InfoRow","label","value","mono","accent","copyValue","secondaryValue","textStyle","jsxs","jsx","CopyableValue","Account","accountData","connectedAddress","network","networkStats","useStore","offers","setOffers","useState","offersLoading","setOffersLoading","offersError","setOffersError","createdAt","setCreatedAt","createdAtLoading","setCreatedAtLoading","reserves","useMemo","calculateAccountReserves","useEffect","isActive","fetchAccountCreationDate","date","fetchAccountOffers","res","err","xlm","b","otherAssets","signers","flags","thresholds","createdValue","format","getEstimate","useAssetUsdEstimates","xlmEstimate","formatXLM","formatEstimatedUsd","asset","index","estimate","AddressLabelBadge","shortAddress","key","val","s","i","offer"],"mappings":"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"} \ No newline at end of file diff --git a/dist/assets/AccountComparison-BOAvjkeU.js.map b/dist/assets/AccountComparison-BOAvjkeU.js.map deleted file mode 100644 index 6332494f..00000000 --- a/dist/assets/AccountComparison-BOAvjkeU.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"AccountComparison-BOAvjkeU.js","sources":["../../src/components/dashboard/AccountComparison.tsx"],"sourcesContent":["import React, { useState, useEffect, useMemo, type ChangeEvent, type ReactNode, type ReactElement } from 'react';\nimport { useStore } from '../../lib/store';\nimport { shortAddress } from '../../lib/stellar';\nimport CopyableValue from './CopyableValue';\nimport { fetchAccountDetails, type AccountDetails } from '../../lib/stellar';\nimport { isPublicKey } from '../../lib/stellar';\nimport Card from './Card';\nimport type { ComparisonSlot } from '../../lib/store';\n\ninterface ComparisonRowProps {\n label: string\n values: ReactNode[]\n highlight?: number | null\n}\n\ninterface DiffBadgeProps {\n text: string\n variant: 'positive' | 'negative' | 'neutral'\n}\n\ninterface MetricCardProps {\n title: string\n accounts: (AccountDetails | null)[]\n format: (val: AccountDetails | null) => ReactNode\n highlight?: (val: AccountDetails | null) => boolean\n}\n\ninterface AnalysisRow {\n label: string\n values: ReactNode[]\n highlight?: number | null\n}\n\ninterface ComparisonData {\n rows: AnalysisRow[]\n}\n\nconst DiffBadge = ({ text, variant }: DiffBadgeProps) => {\n const colors: Record = {\n positive: { bg: 'var(--green-glow-sm)', border: 'var(--green)', color: 'var(--green)' },\n negative: { bg: 'var(--red-glow-sm)', border: 'var(--red)', color: 'var(--red)' },\n neutral: { bg: 'var(--bg-elevated)', border: 'var(--border)', color: 'var(--text-muted)' },\n };\n\n return (\n \n {text}\n \n );\n};\n\nconst ComparisonRow = ({ label, values, highlight }: ComparisonRowProps) => (\n
\n
{label}
\n {values.map((val: ReactNode, i: number) => (\n
\n {val ?? }\n
\n ))}\n
\n);\n\nconst MetricCard = ({ title, accounts, format, highlight }: MetricCardProps) => {\n const values = accounts.map((a, i) => ({\n value: format(a),\n isHighlight: highlight ? highlight(a) : false\n }));\n\n return (\n
\n
\n {title}\n
\n
\n {values.map((v, i) => (\n
\n {v.value}\n
\n ))}\n
\n
\n );\n};\n\nfunction buildComparison(accounts: (AccountDetails | null)[]): ComparisonData {\n if (!accounts.length || accounts.every(a => a === null)) {\n return { rows: [] };\n }\n\n const rows: AnalysisRow[] = [];\n\n const balances = accounts.map(a => a?.balances?.reduce((sum: number, b: { balance?: string }) =>\n sum + parseFloat(b.balance || '0'), 0) ?? null);\n rows.push({\n label: 'Total Balance (XLM)',\n values: balances.map(b => b !== null ? b.toLocaleString(undefined, { maximumFractionDigits: 2 }) : '—'),\n highlight: balances.indexOf(Math.max(...balances.filter((b): b is number => b !== null)))\n });\n\n const homeDomains = accounts.map(a => a?.home_domain || null);\n rows.push({\n label: 'Home Domain',\n values: homeDomains.map(d => d || '—'),\n });\n\n const hasThresholds = accounts.map(a => (a?.thresholds?.low_weight && a?.thresholds?.med_weight && a?.thresholds?.high_weight) ? true : false);\n rows.push({\n label: 'Thresholds Set',\n values: hasThresholds.map(t => t ? '✓' : '✗'),\n });\n\n const signerCounts = accounts.map(a => (a?.signers?.length ?? 0));\n rows.push({\n label: 'Signers',\n values: signerCounts.map(c => c.toString()),\n highlight: signerCounts.indexOf(Math.max(...signerCounts))\n });\n\n const seqNums = accounts.map(a => a?.sequence ? BigInt(a.sequence) : null);\n rows.push({\n label: 'Sequence',\n values: seqNums.map(s => s !== null ? `${(Number(s) & 0xFFFFFFFFFFFFFFFF).toString(16).padStart(16, '0').substring(0, 8)}…` : '—'),\n });\n\n return { rows };\n}\n\nexport default function AccountComparison() {\n const { comparisonSlots, addComparisonSlot, removeComparisonSlot, updateComparisonSlot, network } = useStore();\n const [accounts, setAccounts] = useState<(AccountDetails | null)[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n const [inputValue, setInputValue] = useState('');\n\n const currentSlots = comparisonSlots || [];\n\n useEffect(() => {\n if (currentSlots.length === 0) {\n setAccounts([]);\n return;\n }\n\n let cancelled = false;\n\n async function loadAccounts() {\n setIsLoading(true);\n const results: (AccountDetails | null)[] = [];\n\n for (const slot of currentSlots) {\n if (cancelled) break;\n try {\n const details = await fetchAccountDetails(slot.address);\n results.push(details);\n } catch {\n results.push(null);\n }\n }\n\n if (!cancelled) {\n setAccounts(results);\n setIsLoading(false);\n }\n }\n\n loadAccounts();\n\n return () => { cancelled = true; };\n }, [currentSlots.map((s: ComparisonSlot) => s.address).join(',')]);\n\n const comparison = useMemo(() => buildComparison(accounts), [accounts]);\n\n const handleAddAccount = () => {\n const address = inputValue.trim();\n if (!address || !isPublicKey(address)) return;\n addComparisonSlot({ id: `slot-${Date.now()}`, address, label: shortAddress(address, 6) });\n setInputValue('');\n };\n\n const handleAccountChange = (index: number, e: ChangeEvent) => {\n const slot = currentSlots[index];\n if (slot) {\n updateComparisonSlot(slot.id, { ...slot, address: e.target.value });\n }\n };\n\n const handleRemoveAccount = (index: number) => {\n const slot = currentSlots[index];\n if (slot) removeComparisonSlot(slot.id);\n };\n\n const allLoaded = accounts.length > 0 && accounts.every(a => a !== null);\n\n const netWorthCard = (\n {\n if (!a) return '—';\n const total = a.balances?.reduce((s, b) => s + parseFloat(b.balance || '0'), 0) || 0;\n return `${total.toLocaleString(undefined, { maximumFractionDigits: 2 })} XLM`;\n }}\n highlight={(a) => {\n if (!a) return false;\n const total = a.balances?.reduce((s, b) => s + parseFloat(b.balance || '0'), 0) || 0;\n const max = Math.max(...accounts.filter(Boolean).map(acc =>\n acc!.balances?.reduce((s, b) => s + parseFloat(b.balance || '0'), 0) || 0\n ));\n return total === max && max > 0;\n }}\n />\n );\n\n const signerCard = (\n a?.signers?.length?.toString() ?? '—'}\n highlight={(a) => {\n if (!a?.signers) return false;\n const max = Math.max(...accounts.filter(Boolean).map(acc => acc!.signers?.length || 0));\n return a.signers.length === max && max > 0;\n }}\n />\n );\n\n const subEntryCard = (\n a?.num_subentries?.toString() ?? '—'}\n highlight={(a) => {\n if (!a?.num_subentries) return false;\n const max = Math.max(...accounts.filter(Boolean).map(acc => acc!.num_subentries || 0));\n return a.num_subentries === max && max > 0;\n }}\n />\n );\n\n return (\n
\n
\n
\n Account Comparison\n
\n

\n Compare key metrics across multiple Stellar accounts side by side.\n

\n
\n\n
\n
\n
\n \n ) => setInputValue(e.target.value)}\n placeholder=\"GABCDEF1234...\"\n onKeyDown={(e: React.KeyboardEvent) => { if (e.key === 'Enter') handleAddAccount(); }}\n style={{\n padding: '10px 12px',\n background: 'var(--bg-canvas)',\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius-sm)',\n color: 'var(--text-primary)',\n fontSize: '13px',\n fontFamily: 'var(--font-mono)',\n outline: 'none',\n transition: 'var(--transition)',\n }}\n />\n
\n \n + Add Account\n \n
\n\n {currentSlots.length > 0 && (\n
\n {currentSlots.map((slot: ComparisonSlot, index: number) => (\n
\n \n {index + 1}\n \n ) => handleAccountChange(index, e)}\n style={{\n flex: 1,\n padding: '8px 10px',\n background: 'var(--bg-canvas)',\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius-sm)',\n color: 'var(--text-primary)',\n fontSize: '12px',\n fontFamily: 'var(--font-mono)',\n outline: 'none',\n minWidth: 0,\n }}\n />\n \n {accounts[index] ? shortAddress(accounts[index]?.id || '', 6) : '—'}\n \n handleRemoveAccount(index)}\n style={{\n padding: '4px 10px',\n background: 'transparent',\n color: 'var(--red)',\n border: '1px solid var(--red)',\n borderRadius: 'var(--radius-sm)',\n fontSize: '12px',\n cursor: 'pointer',\n transition: 'var(--transition)',\n opacity: 0.7,\n }}\n >\n ✕\n \n
\n ))}\n
\n )}\n
\n\n {isLoading && (\n
\n Loading account data...\n
\n )}\n\n {!isLoading && currentSlots.length === 0 && (\n
\n
⚖️
\n
Add two or more accounts to compare
\n
\n Compare balances, thresholds, signers, and more.\n
\n
\n )}\n\n {!isLoading && currentSlots.length > 0 && (\n
\n
\n {netWorthCard}\n {signerCard}\n {subEntryCard}\n
\n\n
\n
\n Detailed Comparison\n
\n
\n {comparison.rows.length > 0 ? (\n comparison.rows.map((row: AnalysisRow, i: number) => (\n \n ))\n ) : (\n
\n No comparison data available.\n
\n )}\n
\n
\n
\n )}\n
\n );\n}\n"],"names":["ComparisonRow","label","values","highlight","jsxs","jsx","val","i","MetricCard","title","accounts","format","v","buildComparison","a","rows","balances","sum","b","homeDomains","d","hasThresholds","t","signerCounts","c","seqNums","s","AccountComparison","comparisonSlots","addComparisonSlot","removeComparisonSlot","updateComparisonSlot","network","useStore","setAccounts","useState","isLoading","setIsLoading","inputValue","setInputValue","currentSlots","useEffect","cancelled","loadAccounts","results","slot","details","fetchAccountDetails","comparison","useMemo","handleAddAccount","address","isPublicKey","shortAddress","handleAccountChange","index","e","handleRemoveAccount","netWorthCard","total","max","acc","signerCard","subEntryCard","row"],"mappings":"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"} \ No newline at end of file diff --git a/dist/assets/AccountComparison-BOAvjkeU.js b/dist/assets/AccountComparison-DlSxH1IA.js similarity index 95% rename from dist/assets/AccountComparison-BOAvjkeU.js rename to dist/assets/AccountComparison-DlSxH1IA.js index cefec96f..8fe8fa6e 100644 --- a/dist/assets/AccountComparison-BOAvjkeU.js +++ b/dist/assets/AccountComparison-DlSxH1IA.js @@ -1,2 +1,2 @@ -import{r as v,j as t}from"./react-vendor-CsepHXsi.js";import{u as F}from"./deployment-BPDW632H.js";import{L as h,s as w,M as R}from"./charts-OWQBHTRD.js";import"./vendor-Du79euYq.js";import"./stellar-sdk-or8ZbYCb.js";import"./charts-vendor-BIh5SzZ7.js";import"./icons-vendor-BqasJArU.js";import"./date-vendor-boStncAG.js";const B=({label:s,values:l,highlight:d})=>t.jsxs("div",{style:{display:"grid",gridTemplateColumns:"140px repeat(auto-fit, minmax(120px, 1fr))",gap:"12px",padding:"10px 14px",borderBottom:"1px solid var(--border)",alignItems:"center",background:d!==void 0?"var(--cyan-glow-sm)":"transparent",transition:"var(--transition)",fontSize:"13px"},children:[t.jsx("div",{style:{color:"var(--text-muted)",fontWeight:500,fontSize:"12px"},children:s}),l.map((c,x)=>t.jsx("div",{style:{fontFamily:"var(--font-mono)",color:"var(--text-primary)",fontWeight:d===x?700:400,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:c??t.jsx("span",{style:{color:"var(--text-muted)"},children:"—"})},x))]}),b=({title:s,accounts:l,format:d,highlight:c})=>{const x=l.map((a,m)=>({value:d(a),isHighlight:c?c(a):!1}));return t.jsxs("div",{style:{background:"var(--bg-elevated)",border:"1px solid var(--border)",borderRadius:"var(--radius-md)",padding:"16px",transition:"var(--transition)"},children:[t.jsx("div",{style:{fontSize:"12px",color:"var(--text-muted)",fontWeight:500,marginBottom:"12px",textTransform:"uppercase",letterSpacing:"1px"},children:s}),t.jsx("div",{style:{display:"flex",gap:"12px",flexWrap:"wrap"},children:x.map((a,m)=>t.jsx("div",{style:{flex:1,minWidth:"100px",padding:"10px 14px",background:"var(--bg-canvas)",borderRadius:"var(--radius-sm)",border:`1px solid ${a.isHighlight?"var(--cyan)":"var(--border)"}`,color:"var(--text-primary)",fontSize:"14px",fontFamily:"var(--font-mono)",fontWeight:a.isHighlight?700:400},children:a.value},m))})]})};function M(s){if(!s.length||s.every(r=>r===null))return{rows:[]};const l=[],d=s.map(r=>r?.balances?.reduce((f,o)=>f+parseFloat(o.balance||"0"),0)??null);l.push({label:"Total Balance (XLM)",values:d.map(r=>r!==null?r.toLocaleString(void 0,{maximumFractionDigits:2}):"—"),highlight:d.indexOf(Math.max(...d.filter(r=>r!==null)))});const c=s.map(r=>r?.home_domain||null);l.push({label:"Home Domain",values:c.map(r=>r||"—")});const x=s.map(r=>!!(r?.thresholds?.low_weight&&r?.thresholds?.med_weight&&r?.thresholds?.high_weight));l.push({label:"Thresholds Set",values:x.map(r=>r?"✓":"✗")});const a=s.map(r=>r?.signers?.length??0);l.push({label:"Signers",values:a.map(r=>r.toString()),highlight:a.indexOf(Math.max(...a))});const m=s.map(r=>r?.sequence?BigInt(r.sequence):null);return l.push({label:"Sequence",values:m.map(r=>r!==null?`${(Number(r)&18446744073709552e3).toString(16).padStart(16,"0").substring(0,8)}…`:"—")}),{rows:l}}function q(){const{comparisonSlots:s,addComparisonSlot:l,removeComparisonSlot:d,updateComparisonSlot:c,network:x}=F(),[a,m]=v.useState([]),[r,f]=v.useState(!1),[o,y]=v.useState(""),p=s||[];v.useEffect(()=>{if(p.length===0){m([]);return}let e=!1;async function i(){f(!0);const n=[];for(const u of p){if(e)break;try{const g=await R(u.address);n.push(g)}catch{n.push(null)}}e||(m(n),f(!1))}return i(),()=>{e=!0}},[p.map(e=>e.address).join(",")]);const S=v.useMemo(()=>M(a),[a]),j=()=>{const e=o.trim();!e||!h(e)||(l({id:`slot-${Date.now()}`,address:e,label:w(e,6)}),y(""))},C=(e,i)=>{const n=p[e];n&&c(n.id,{...n,address:i.target.value})},z=e=>{const i=p[e];i&&d(i.id)};a.length>0&&a.every(e=>e!==null);const A=t.jsx(b,{title:"Net Worth",accounts:a,format:e=>e?`${(e.balances?.reduce((n,u)=>n+parseFloat(u.balance||"0"),0)||0).toLocaleString(void 0,{maximumFractionDigits:2})} XLM`:"—",highlight:e=>{if(!e)return!1;const i=e.balances?.reduce((u,g)=>u+parseFloat(g.balance||"0"),0)||0,n=Math.max(...a.filter(Boolean).map(u=>u.balances?.reduce((g,D)=>g+parseFloat(D.balance||"0"),0)||0));return i===n&&n>0}}),k=t.jsx(b,{title:"Signers",accounts:a,format:e=>e?.signers?.length?.toString()??"—",highlight:e=>{if(!e?.signers)return!1;const i=Math.max(...a.filter(Boolean).map(n=>n.signers?.length||0));return e.signers.length===i&&i>0}}),W=t.jsx(b,{title:"Subentries",accounts:a,format:e=>e?.num_subentries?.toString()??"—",highlight:e=>{if(!e?.num_subentries)return!1;const i=Math.max(...a.filter(Boolean).map(n=>n.num_subentries||0));return e.num_subentries===i&&i>0}});return t.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:"20px"},children:[t.jsxs("div",{children:[t.jsx("div",{style:{fontFamily:"var(--font-display)",fontSize:"22px",fontWeight:700,marginBottom:"8px"},children:"Account Comparison"}),t.jsx("p",{style:{fontSize:"13px",color:"var(--text-muted)",lineHeight:1.6,margin:0},children:"Compare key metrics across multiple Stellar accounts side by side."})]}),t.jsxs("div",{className:"card",style:{padding:"20px",background:"var(--bg-elevated)",border:"1px solid var(--border)",borderRadius:"var(--radius-md)"},children:[t.jsxs("div",{style:{display:"flex",gap:"10px",flexWrap:"wrap",alignItems:"flex-end"},children:[t.jsxs("div",{style:{flex:1,minWidth:"200px",display:"flex",flexDirection:"column",gap:"4px"},children:[t.jsx("label",{style:{fontSize:"12px",color:"var(--text-muted)",fontWeight:500},children:"Stellar Address"}),t.jsx("input",{type:"text",value:o,onChange:e=>y(e.target.value),placeholder:"GABCDEF1234...",onKeyDown:e=>{e.key==="Enter"&&j()},style:{padding:"10px 12px",background:"var(--bg-canvas)",border:"1px solid var(--border)",borderRadius:"var(--radius-sm)",color:"var(--text-primary)",fontSize:"13px",fontFamily:"var(--font-mono)",outline:"none",transition:"var(--transition)"}})]}),t.jsx("button",{onClick:j,disabled:!o.trim()||!h(o.trim()),style:{padding:"10px 18px",background:o.trim()&&h(o.trim())?"var(--cyan)":"var(--bg-elevated)",color:o.trim()&&h(o.trim())?"white":"var(--text-muted)",border:`1px solid ${o.trim()&&h(o.trim())?"var(--cyan)":"var(--border)"}`,borderRadius:"var(--radius-sm)",fontSize:"13px",fontWeight:600,cursor:o.trim()&&h(o.trim())?"pointer":"not-allowed",transition:"var(--transition)",whiteSpace:"nowrap"},children:"+ Add Account"})]}),p.length>0&&t.jsx("div",{style:{marginTop:"16px",display:"flex",flexDirection:"column",gap:"8px"},children:p.map((e,i)=>t.jsxs("div",{style:{display:"flex",gap:"8px",alignItems:"center"},children:[t.jsx("span",{style:{width:"22px",height:"22px",borderRadius:"50%",background:"var(--cyan)",color:"white",display:"flex",alignItems:"center",justifyContent:"center",fontSize:"11px",fontWeight:700,flexShrink:0},children:i+1}),t.jsx("input",{type:"text",value:e.address,onChange:n=>C(i,n),style:{flex:1,padding:"8px 10px",background:"var(--bg-canvas)",border:"1px solid var(--border)",borderRadius:"var(--radius-sm)",color:"var(--text-primary)",fontSize:"12px",fontFamily:"var(--font-mono)",outline:"none",minWidth:0}}),t.jsx("span",{style:{fontSize:"11px",color:"var(--text-muted)",fontFamily:"var(--font-mono)"},children:a[i]?w(a[i]?.id||"",6):"—"}),t.jsx("button",{onClick:()=>z(i),style:{padding:"4px 10px",background:"transparent",color:"var(--red)",border:"1px solid var(--red)",borderRadius:"var(--radius-sm)",fontSize:"12px",cursor:"pointer",transition:"var(--transition)",opacity:.7},children:"✕"})]},e.id))})]}),r&&t.jsx("div",{style:{textAlign:"center",padding:"40px",color:"var(--text-muted)"},children:"Loading account data..."}),!r&&p.length===0&&t.jsxs("div",{style:{textAlign:"center",padding:"60px 20px",color:"var(--text-muted)"},children:[t.jsx("div",{style:{fontSize:"36px",marginBottom:"12px",opacity:.4},children:"⚖️"}),t.jsx("div",{style:{fontSize:"14px"},children:"Add two or more accounts to compare"}),t.jsx("div",{style:{fontSize:"12px",marginTop:"6px"},children:"Compare balances, thresholds, signers, and more."})]}),!r&&p.length>0&&t.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:"16px"},children:[t.jsxs("div",{style:{display:"grid",gridTemplateColumns:"repeat(auto-fit, minmax(250px, 1fr))",gap:"12px"},children:[A,k,W]}),t.jsxs("div",{className:"card",style:{background:"var(--bg-elevated)",border:"1px solid var(--border)",borderRadius:"var(--radius-md)",overflow:"hidden"},children:[t.jsx("div",{style:{padding:"14px",borderBottom:"1px solid var(--border)",fontSize:"14px",fontWeight:600,color:"var(--text-primary)"},children:"Detailed Comparison"}),t.jsx("div",{style:{overflowX:"auto"},children:S.rows.length>0?S.rows.map((e,i)=>t.jsx(B,{label:e.label,values:e.values,highlight:e.highlight},i)):t.jsx("div",{style:{padding:"30px",textAlign:"center",color:"var(--text-muted)",fontSize:"13px"},children:"No comparison data available."})})]})]})]})}export{q as default}; -//# sourceMappingURL=AccountComparison-BOAvjkeU.js.map +import{r as v,j as t}from"./react-vendor-C-OVADYf.js";import{u as F}from"./deployment-q_dUxQhv.js";import{M as h,s as w,Q as R}from"./charts-D9P2NM_R.js";import"./vendor-CdKO02NA.js";import"./stellar-sdk-Cld1ipgo.js";import"./date-vendor-boStncAG.js";import"./charts-vendor-BYXr-dPO.js";import"./icons-vendor-C7uAdRPq.js";const B=({label:s,values:l,highlight:d})=>t.jsxs("div",{style:{display:"grid",gridTemplateColumns:"140px repeat(auto-fit, minmax(120px, 1fr))",gap:"12px",padding:"10px 14px",borderBottom:"1px solid var(--border)",alignItems:"center",background:d!==void 0?"var(--cyan-glow-sm)":"transparent",transition:"var(--transition)",fontSize:"13px"},children:[t.jsx("div",{style:{color:"var(--text-muted)",fontWeight:500,fontSize:"12px"},children:s}),l.map((c,x)=>t.jsx("div",{style:{fontFamily:"var(--font-mono)",color:"var(--text-primary)",fontWeight:d===x?700:400,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:c??t.jsx("span",{style:{color:"var(--text-muted)"},children:"—"})},x))]}),b=({title:s,accounts:l,format:d,highlight:c})=>{const x=l.map((a,m)=>({value:d(a),isHighlight:c?c(a):!1}));return t.jsxs("div",{style:{background:"var(--bg-elevated)",border:"1px solid var(--border)",borderRadius:"var(--radius-md)",padding:"16px",transition:"var(--transition)"},children:[t.jsx("div",{style:{fontSize:"12px",color:"var(--text-muted)",fontWeight:500,marginBottom:"12px",textTransform:"uppercase",letterSpacing:"1px"},children:s}),t.jsx("div",{style:{display:"flex",gap:"12px",flexWrap:"wrap"},children:x.map((a,m)=>t.jsx("div",{style:{flex:1,minWidth:"100px",padding:"10px 14px",background:"var(--bg-canvas)",borderRadius:"var(--radius-sm)",border:`1px solid ${a.isHighlight?"var(--cyan)":"var(--border)"}`,color:"var(--text-primary)",fontSize:"14px",fontFamily:"var(--font-mono)",fontWeight:a.isHighlight?700:400},children:a.value},m))})]})};function M(s){if(!s.length||s.every(r=>r===null))return{rows:[]};const l=[],d=s.map(r=>r?.balances?.reduce((f,o)=>f+parseFloat(o.balance||"0"),0)??null);l.push({label:"Total Balance (XLM)",values:d.map(r=>r!==null?r.toLocaleString(void 0,{maximumFractionDigits:2}):"—"),highlight:d.indexOf(Math.max(...d.filter(r=>r!==null)))});const c=s.map(r=>r?.home_domain||null);l.push({label:"Home Domain",values:c.map(r=>r||"—")});const x=s.map(r=>!!(r?.thresholds?.low_weight&&r?.thresholds?.med_weight&&r?.thresholds?.high_weight));l.push({label:"Thresholds Set",values:x.map(r=>r?"✓":"✗")});const a=s.map(r=>r?.signers?.length??0);l.push({label:"Signers",values:a.map(r=>r.toString()),highlight:a.indexOf(Math.max(...a))});const m=s.map(r=>r?.sequence?BigInt(r.sequence):null);return l.push({label:"Sequence",values:m.map(r=>r!==null?`${(Number(r)&18446744073709552e3).toString(16).padStart(16,"0").substring(0,8)}…`:"—")}),{rows:l}}function q(){const{comparisonSlots:s,addComparisonSlot:l,removeComparisonSlot:d,updateComparisonSlot:c,network:x}=F(),[a,m]=v.useState([]),[r,f]=v.useState(!1),[o,y]=v.useState(""),p=s||[];v.useEffect(()=>{if(p.length===0){m([]);return}let e=!1;async function i(){f(!0);const n=[];for(const u of p){if(e)break;try{const g=await R(u.address);n.push(g)}catch{n.push(null)}}e||(m(n),f(!1))}return i(),()=>{e=!0}},[p.map(e=>e.address).join(",")]);const S=v.useMemo(()=>M(a),[a]),j=()=>{const e=o.trim();!e||!h(e)||(l({id:`slot-${Date.now()}`,address:e,label:w(e,6)}),y(""))},C=(e,i)=>{const n=p[e];n&&c(n.id,{...n,address:i.target.value})},z=e=>{const i=p[e];i&&d(i.id)};a.length>0&&a.every(e=>e!==null);const A=t.jsx(b,{title:"Net Worth",accounts:a,format:e=>e?`${(e.balances?.reduce((n,u)=>n+parseFloat(u.balance||"0"),0)||0).toLocaleString(void 0,{maximumFractionDigits:2})} XLM`:"—",highlight:e=>{if(!e)return!1;const i=e.balances?.reduce((u,g)=>u+parseFloat(g.balance||"0"),0)||0,n=Math.max(...a.filter(Boolean).map(u=>u.balances?.reduce((g,D)=>g+parseFloat(D.balance||"0"),0)||0));return i===n&&n>0}}),k=t.jsx(b,{title:"Signers",accounts:a,format:e=>e?.signers?.length?.toString()??"—",highlight:e=>{if(!e?.signers)return!1;const i=Math.max(...a.filter(Boolean).map(n=>n.signers?.length||0));return e.signers.length===i&&i>0}}),W=t.jsx(b,{title:"Subentries",accounts:a,format:e=>e?.num_subentries?.toString()??"—",highlight:e=>{if(!e?.num_subentries)return!1;const i=Math.max(...a.filter(Boolean).map(n=>n.num_subentries||0));return e.num_subentries===i&&i>0}});return t.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:"20px"},children:[t.jsxs("div",{children:[t.jsx("div",{style:{fontFamily:"var(--font-display)",fontSize:"22px",fontWeight:700,marginBottom:"8px"},children:"Account Comparison"}),t.jsx("p",{style:{fontSize:"13px",color:"var(--text-muted)",lineHeight:1.6,margin:0},children:"Compare key metrics across multiple Stellar accounts side by side."})]}),t.jsxs("div",{className:"card",style:{padding:"20px",background:"var(--bg-elevated)",border:"1px solid var(--border)",borderRadius:"var(--radius-md)"},children:[t.jsxs("div",{style:{display:"flex",gap:"10px",flexWrap:"wrap",alignItems:"flex-end"},children:[t.jsxs("div",{style:{flex:1,minWidth:"200px",display:"flex",flexDirection:"column",gap:"4px"},children:[t.jsx("label",{style:{fontSize:"12px",color:"var(--text-muted)",fontWeight:500},children:"Stellar Address"}),t.jsx("input",{type:"text",value:o,onChange:e=>y(e.target.value),placeholder:"GABCDEF1234...",onKeyDown:e=>{e.key==="Enter"&&j()},style:{padding:"10px 12px",background:"var(--bg-canvas)",border:"1px solid var(--border)",borderRadius:"var(--radius-sm)",color:"var(--text-primary)",fontSize:"13px",fontFamily:"var(--font-mono)",outline:"none",transition:"var(--transition)"}})]}),t.jsx("button",{onClick:j,disabled:!o.trim()||!h(o.trim()),style:{padding:"10px 18px",background:o.trim()&&h(o.trim())?"var(--cyan)":"var(--bg-elevated)",color:o.trim()&&h(o.trim())?"white":"var(--text-muted)",border:`1px solid ${o.trim()&&h(o.trim())?"var(--cyan)":"var(--border)"}`,borderRadius:"var(--radius-sm)",fontSize:"13px",fontWeight:600,cursor:o.trim()&&h(o.trim())?"pointer":"not-allowed",transition:"var(--transition)",whiteSpace:"nowrap"},children:"+ Add Account"})]}),p.length>0&&t.jsx("div",{style:{marginTop:"16px",display:"flex",flexDirection:"column",gap:"8px"},children:p.map((e,i)=>t.jsxs("div",{style:{display:"flex",gap:"8px",alignItems:"center"},children:[t.jsx("span",{style:{width:"22px",height:"22px",borderRadius:"50%",background:"var(--cyan)",color:"white",display:"flex",alignItems:"center",justifyContent:"center",fontSize:"11px",fontWeight:700,flexShrink:0},children:i+1}),t.jsx("input",{type:"text",value:e.address,onChange:n=>C(i,n),style:{flex:1,padding:"8px 10px",background:"var(--bg-canvas)",border:"1px solid var(--border)",borderRadius:"var(--radius-sm)",color:"var(--text-primary)",fontSize:"12px",fontFamily:"var(--font-mono)",outline:"none",minWidth:0}}),t.jsx("span",{style:{fontSize:"11px",color:"var(--text-muted)",fontFamily:"var(--font-mono)"},children:a[i]?w(a[i]?.id||"",6):"—"}),t.jsx("button",{onClick:()=>z(i),style:{padding:"4px 10px",background:"transparent",color:"var(--red)",border:"1px solid var(--red)",borderRadius:"var(--radius-sm)",fontSize:"12px",cursor:"pointer",transition:"var(--transition)",opacity:.7},children:"✕"})]},e.id))})]}),r&&t.jsx("div",{style:{textAlign:"center",padding:"40px",color:"var(--text-muted)"},children:"Loading account data..."}),!r&&p.length===0&&t.jsxs("div",{style:{textAlign:"center",padding:"60px 20px",color:"var(--text-muted)"},children:[t.jsx("div",{style:{fontSize:"36px",marginBottom:"12px",opacity:.4},children:"⚖️"}),t.jsx("div",{style:{fontSize:"14px"},children:"Add two or more accounts to compare"}),t.jsx("div",{style:{fontSize:"12px",marginTop:"6px"},children:"Compare balances, thresholds, signers, and more."})]}),!r&&p.length>0&&t.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:"16px"},children:[t.jsxs("div",{style:{display:"grid",gridTemplateColumns:"repeat(auto-fit, minmax(250px, 1fr))",gap:"12px"},children:[A,k,W]}),t.jsxs("div",{className:"card",style:{background:"var(--bg-elevated)",border:"1px solid var(--border)",borderRadius:"var(--radius-md)",overflow:"hidden"},children:[t.jsx("div",{style:{padding:"14px",borderBottom:"1px solid var(--border)",fontSize:"14px",fontWeight:600,color:"var(--text-primary)"},children:"Detailed Comparison"}),t.jsx("div",{style:{overflowX:"auto"},children:S.rows.length>0?S.rows.map((e,i)=>t.jsx(B,{label:e.label,values:e.values,highlight:e.highlight},i)):t.jsx("div",{style:{padding:"30px",textAlign:"center",color:"var(--text-muted)",fontSize:"13px"},children:"No comparison data available."})})]})]})]})}export{q as default}; +//# sourceMappingURL=AccountComparison-DlSxH1IA.js.map diff --git a/dist/assets/AccountComparison-DlSxH1IA.js.map b/dist/assets/AccountComparison-DlSxH1IA.js.map new file mode 100644 index 00000000..0537215b --- /dev/null +++ b/dist/assets/AccountComparison-DlSxH1IA.js.map @@ -0,0 +1 @@ +{"version":3,"file":"AccountComparison-DlSxH1IA.js","sources":["../../src/components/dashboard/AccountComparison.tsx"],"sourcesContent":["import React, { useState, useEffect, useMemo, type ChangeEvent, type ReactNode, type ReactElement } from 'react';\r\nimport { useStore } from '../../lib/store';\r\nimport { shortAddress } from '../../lib/stellar';\r\nimport CopyableValue from './CopyableValue';\r\nimport { fetchAccountDetails, type AccountDetails } from '../../lib/stellar';\r\nimport { isPublicKey } from '../../lib/stellar';\r\nimport Card from './Card';\r\nimport type { ComparisonSlot } from '../../lib/store';\r\n\r\ninterface ComparisonRowProps {\r\n label: string\r\n values: ReactNode[]\r\n highlight?: number | null\r\n}\r\n\r\ninterface DiffBadgeProps {\r\n text: string\r\n variant: 'positive' | 'negative' | 'neutral'\r\n}\r\n\r\ninterface MetricCardProps {\r\n title: string\r\n accounts: (AccountDetails | null)[]\r\n format: (val: AccountDetails | null) => ReactNode\r\n highlight?: (val: AccountDetails | null) => boolean\r\n}\r\n\r\ninterface AnalysisRow {\r\n label: string\r\n values: ReactNode[]\r\n highlight?: number | null\r\n}\r\n\r\ninterface ComparisonData {\r\n rows: AnalysisRow[]\r\n}\r\n\r\nconst DiffBadge = ({ text, variant }: DiffBadgeProps) => {\r\n const colors: Record = {\r\n positive: { bg: 'var(--green-glow-sm)', border: 'var(--green)', color: 'var(--green)' },\r\n negative: { bg: 'var(--red-glow-sm)', border: 'var(--red)', color: 'var(--red)' },\r\n neutral: { bg: 'var(--bg-elevated)', border: 'var(--border)', color: 'var(--text-muted)' },\r\n };\r\n\r\n return (\r\n \r\n {text}\r\n \r\n );\r\n};\r\n\r\nconst ComparisonRow = ({ label, values, highlight }: ComparisonRowProps) => (\r\n
\r\n
{label}
\r\n {values.map((val: ReactNode, i: number) => (\r\n
\r\n {val ?? }\r\n
\r\n ))}\r\n
\r\n);\r\n\r\nconst MetricCard = ({ title, accounts, format, highlight }: MetricCardProps) => {\r\n const values = accounts.map((a, i) => ({\r\n value: format(a),\r\n isHighlight: highlight ? highlight(a) : false\r\n }));\r\n\r\n return (\r\n
\r\n
\r\n {title}\r\n
\r\n
\r\n {values.map((v, i) => (\r\n
\r\n {v.value}\r\n
\r\n ))}\r\n
\r\n
\r\n );\r\n};\r\n\r\nfunction buildComparison(accounts: (AccountDetails | null)[]): ComparisonData {\r\n if (!accounts.length || accounts.every(a => a === null)) {\r\n return { rows: [] };\r\n }\r\n\r\n const rows: AnalysisRow[] = [];\r\n\r\n const balances = accounts.map(a => a?.balances?.reduce((sum: number, b: { balance?: string }) =>\r\n sum + parseFloat(b.balance || '0'), 0) ?? null);\r\n rows.push({\r\n label: 'Total Balance (XLM)',\r\n values: balances.map(b => b !== null ? b.toLocaleString(undefined, { maximumFractionDigits: 2 }) : '—'),\r\n highlight: balances.indexOf(Math.max(...balances.filter((b): b is number => b !== null)))\r\n });\r\n\r\n const homeDomains = accounts.map(a => a?.home_domain || null);\r\n rows.push({\r\n label: 'Home Domain',\r\n values: homeDomains.map(d => d || '—'),\r\n });\r\n\r\n const hasThresholds = accounts.map(a => (a?.thresholds?.low_weight && a?.thresholds?.med_weight && a?.thresholds?.high_weight) ? true : false);\r\n rows.push({\r\n label: 'Thresholds Set',\r\n values: hasThresholds.map(t => t ? '✓' : '✗'),\r\n });\r\n\r\n const signerCounts = accounts.map(a => (a?.signers?.length ?? 0));\r\n rows.push({\r\n label: 'Signers',\r\n values: signerCounts.map(c => c.toString()),\r\n highlight: signerCounts.indexOf(Math.max(...signerCounts))\r\n });\r\n\r\n const seqNums = accounts.map(a => a?.sequence ? BigInt(a.sequence) : null);\r\n rows.push({\r\n label: 'Sequence',\r\n values: seqNums.map(s => s !== null ? `${(Number(s) & 0xFFFFFFFFFFFFFFFF).toString(16).padStart(16, '0').substring(0, 8)}…` : '—'),\r\n });\r\n\r\n return { rows };\r\n}\r\n\r\nexport default function AccountComparison() {\r\n const { comparisonSlots, addComparisonSlot, removeComparisonSlot, updateComparisonSlot, network } = useStore();\r\n const [accounts, setAccounts] = useState<(AccountDetails | null)[]>([]);\r\n const [isLoading, setIsLoading] = useState(false);\r\n const [inputValue, setInputValue] = useState('');\r\n\r\n const currentSlots = comparisonSlots || [];\r\n\r\n useEffect(() => {\r\n if (currentSlots.length === 0) {\r\n setAccounts([]);\r\n return;\r\n }\r\n\r\n let cancelled = false;\r\n\r\n async function loadAccounts() {\r\n setIsLoading(true);\r\n const results: (AccountDetails | null)[] = [];\r\n\r\n for (const slot of currentSlots) {\r\n if (cancelled) break;\r\n try {\r\n const details = await fetchAccountDetails(slot.address);\r\n results.push(details);\r\n } catch {\r\n results.push(null);\r\n }\r\n }\r\n\r\n if (!cancelled) {\r\n setAccounts(results);\r\n setIsLoading(false);\r\n }\r\n }\r\n\r\n loadAccounts();\r\n\r\n return () => { cancelled = true; };\r\n }, [currentSlots.map((s: ComparisonSlot) => s.address).join(',')]);\r\n\r\n const comparison = useMemo(() => buildComparison(accounts), [accounts]);\r\n\r\n const handleAddAccount = () => {\r\n const address = inputValue.trim();\r\n if (!address || !isPublicKey(address)) return;\r\n addComparisonSlot({ id: `slot-${Date.now()}`, address, label: shortAddress(address, 6) });\r\n setInputValue('');\r\n };\r\n\r\n const handleAccountChange = (index: number, e: ChangeEvent) => {\r\n const slot = currentSlots[index];\r\n if (slot) {\r\n updateComparisonSlot(slot.id, { ...slot, address: e.target.value });\r\n }\r\n };\r\n\r\n const handleRemoveAccount = (index: number) => {\r\n const slot = currentSlots[index];\r\n if (slot) removeComparisonSlot(slot.id);\r\n };\r\n\r\n const allLoaded = accounts.length > 0 && accounts.every(a => a !== null);\r\n\r\n const netWorthCard = (\r\n {\r\n if (!a) return '—';\r\n const total = a.balances?.reduce((s, b) => s + parseFloat(b.balance || '0'), 0) || 0;\r\n return `${total.toLocaleString(undefined, { maximumFractionDigits: 2 })} XLM`;\r\n }}\r\n highlight={(a) => {\r\n if (!a) return false;\r\n const total = a.balances?.reduce((s, b) => s + parseFloat(b.balance || '0'), 0) || 0;\r\n const max = Math.max(...accounts.filter(Boolean).map(acc =>\r\n acc!.balances?.reduce((s, b) => s + parseFloat(b.balance || '0'), 0) || 0\r\n ));\r\n return total === max && max > 0;\r\n }}\r\n />\r\n );\r\n\r\n const signerCard = (\r\n a?.signers?.length?.toString() ?? '—'}\r\n highlight={(a) => {\r\n if (!a?.signers) return false;\r\n const max = Math.max(...accounts.filter(Boolean).map(acc => acc!.signers?.length || 0));\r\n return a.signers.length === max && max > 0;\r\n }}\r\n />\r\n );\r\n\r\n const subEntryCard = (\r\n a?.num_subentries?.toString() ?? '—'}\r\n highlight={(a) => {\r\n if (!a?.num_subentries) return false;\r\n const max = Math.max(...accounts.filter(Boolean).map(acc => acc!.num_subentries || 0));\r\n return a.num_subentries === max && max > 0;\r\n }}\r\n />\r\n );\r\n\r\n return (\r\n
\r\n
\r\n
\r\n Account Comparison\r\n
\r\n

\r\n Compare key metrics across multiple Stellar accounts side by side.\r\n

\r\n
\r\n\r\n
\r\n
\r\n
\r\n \r\n ) => setInputValue(e.target.value)}\r\n placeholder=\"GABCDEF1234...\"\r\n onKeyDown={(e: React.KeyboardEvent) => { if (e.key === 'Enter') handleAddAccount(); }}\r\n style={{\r\n padding: '10px 12px',\r\n background: 'var(--bg-canvas)',\r\n border: '1px solid var(--border)',\r\n borderRadius: 'var(--radius-sm)',\r\n color: 'var(--text-primary)',\r\n fontSize: '13px',\r\n fontFamily: 'var(--font-mono)',\r\n outline: 'none',\r\n transition: 'var(--transition)',\r\n }}\r\n />\r\n
\r\n \r\n + Add Account\r\n \r\n
\r\n\r\n {currentSlots.length > 0 && (\r\n
\r\n {currentSlots.map((slot: ComparisonSlot, index: number) => (\r\n
\r\n \r\n {index + 1}\r\n \r\n ) => handleAccountChange(index, e)}\r\n style={{\r\n flex: 1,\r\n padding: '8px 10px',\r\n background: 'var(--bg-canvas)',\r\n border: '1px solid var(--border)',\r\n borderRadius: 'var(--radius-sm)',\r\n color: 'var(--text-primary)',\r\n fontSize: '12px',\r\n fontFamily: 'var(--font-mono)',\r\n outline: 'none',\r\n minWidth: 0,\r\n }}\r\n />\r\n \r\n {accounts[index] ? shortAddress(accounts[index]?.id || '', 6) : '—'}\r\n \r\n handleRemoveAccount(index)}\r\n style={{\r\n padding: '4px 10px',\r\n background: 'transparent',\r\n color: 'var(--red)',\r\n border: '1px solid var(--red)',\r\n borderRadius: 'var(--radius-sm)',\r\n fontSize: '12px',\r\n cursor: 'pointer',\r\n transition: 'var(--transition)',\r\n opacity: 0.7,\r\n }}\r\n >\r\n ✕\r\n \r\n
\r\n ))}\r\n
\r\n )}\r\n
\r\n\r\n {isLoading && (\r\n
\r\n Loading account data...\r\n
\r\n )}\r\n\r\n {!isLoading && currentSlots.length === 0 && (\r\n
\r\n
⚖️
\r\n
Add two or more accounts to compare
\r\n
\r\n Compare balances, thresholds, signers, and more.\r\n
\r\n
\r\n )}\r\n\r\n {!isLoading && currentSlots.length > 0 && (\r\n
\r\n
\r\n {netWorthCard}\r\n {signerCard}\r\n {subEntryCard}\r\n
\r\n\r\n
\r\n
\r\n Detailed Comparison\r\n
\r\n
\r\n {comparison.rows.length > 0 ? (\r\n comparison.rows.map((row: AnalysisRow, i: number) => (\r\n \r\n ))\r\n ) : (\r\n
\r\n No comparison data available.\r\n
\r\n )}\r\n
\r\n
\r\n
\r\n )}\r\n
\r\n );\r\n}\r\n"],"names":["ComparisonRow","label","values","highlight","jsxs","jsx","val","i","MetricCard","title","accounts","format","v","buildComparison","a","rows","balances","sum","b","homeDomains","d","hasThresholds","t","signerCounts","c","seqNums","s","AccountComparison","comparisonSlots","addComparisonSlot","removeComparisonSlot","updateComparisonSlot","network","useStore","setAccounts","useState","isLoading","setIsLoading","inputValue","setInputValue","currentSlots","useEffect","cancelled","loadAccounts","results","slot","details","fetchAccountDetails","comparison","useMemo","handleAddAccount","address","isPublicKey","shortAddress","handleAccountChange","index","e","handleRemoveAccount","netWorthCard","total","max","acc","signerCard","subEntryCard","row"],"mappings":"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"} \ No newline at end of file diff --git a/dist/assets/AddressLabelBadge-BTvgU-lx.js b/dist/assets/AddressLabelBadge-BTvgU-lx.js new file mode 100644 index 00000000..134f1a54 --- /dev/null +++ b/dist/assets/AddressLabelBadge-BTvgU-lx.js @@ -0,0 +1,2 @@ +import{r as s,j as f}from"./react-vendor-C-OVADYf.js";import{g as k,s as C}from"./deployment-q_dUxQhv.js";import{n as E}from"./charts-D9P2NM_R.js";import{aa as j,m as I}from"./icons-vendor-C7uAdRPq.js";const S="address-labels-v2",$=[{value:"personal",label:"Personal",color:"#06b6d4"},{value:"exchange",label:"Exchange",color:"#f59e0b"},{value:"defi",label:"DeFi",color:"#8b5cf6"},{value:"nft",label:"NFT",color:"#ec4899"},{value:"custodial",label:"Custodial",color:"#6366f1"},{value:"contract",label:"Contract",color:"#14b8a6"},{value:"other",label:"Other",color:"#6b7280"}];let l=null,x=new Set;function m(){x.forEach(e=>{try{e(l||[])}catch{}})}function L(e,t){return{address:e,label:t.label||e.slice(0,8),tags:t.tags||[],category:t.category||"other",color:t.color||void 0,favorite:!!t.favorite,notes:t.notes||"",network:t.network||"all",createdAt:t.createdAt||new Date().toISOString(),updatedAt:new Date().toISOString()}}async function g(){if(l)return l;try{const e=await k(S);l=Array.isArray(e)?e:[]}catch{l=[]}return l}async function h(){try{await C(S,l||[])}catch{}}async function O(e,t){const a=await g(),n=a.findIndex(c=>c.address===e);return n>=0?a[n]={...a[n],...L(e,t),updatedAt:new Date().toISOString()}:a.push(L(e,t)),l=a,await h(),m(),l}async function R(e,t){const a=await g(),n=a.findIndex(c=>c.address===e);return n<0||(a[n]={...a[n],...t,updatedAt:new Date().toISOString()},l=a,await h(),m()),l}async function D(e){return l=(await g()).filter(a=>a.address!==e),await h(),m(),l}async function F(e){return(await g()).find(a=>a.address===e)||null}async function v(){return g()}async function T(e){const t=await g(),a=e.toLowerCase();return t.filter(n=>n.label.toLowerCase().includes(a)||n.address.toLowerCase().includes(a)||n.tags.some(c=>c.toLowerCase().includes(a))||n.notes.toLowerCase().includes(a))}function V(e){return x.add(e),()=>x.delete(e)}function z(){const[e,t]=s.useState([]),[a,n]=s.useState(!0),[c,b]=s.useState(""),u=s.useRef(!0);s.useEffect(()=>{u.current=!0,v().then(d=>{u.current&&(t(d),n(!1))});const r=V(d=>{u.current&&t(d)});return()=>{u.current=!1,r()}},[]);const y=s.useCallback(async r=>F(r),[]),o=s.useCallback(async(r,d)=>{await O(r,d)},[]),p=s.useCallback(async(r,d)=>{await R(r,d)},[]),i=s.useCallback(async r=>{await D(r)},[]),A=s.useCallback(async r=>(b(r),r.trim()?T(r):await v()),[]),w={};return e.forEach(r=>{w[r.address]=r}),{labels:e,labelMap:w,loading:a,searchQuery:c,setSearchQuery:b,getLabel:y,addLabel:o,updateLabel:p,removeLabel:i,searchLabels:A}}function M(e){const t=$.find(a=>a.value===e);return t?t.color:"#6b7280"}function G({address:e,showAddLabel:t=!0}){const{labelMap:a,addLabel:n}=z(),[c,b]=s.useState(!1),[u,y]=s.useState(""),o=a[e];if(!o)return!t||!e||!E(e)?null:c?f.jsx("span",{style:{display:"inline-flex",alignItems:"center",gap:"3px",marginLeft:"4px",verticalAlign:"middle"},children:f.jsx("input",{value:u,onChange:i=>y(i.target.value),placeholder:"Label",style:{width:"70px",padding:"1px 4px",fontSize:"10px",fontFamily:"var(--font-mono)",background:"var(--bg-card)",border:"1px solid var(--cyan-dim)",borderRadius:"3px",color:"var(--text-primary)",outline:"none"},onKeyDown:async i=>{i.key==="Enter"&&u.trim()&&(await n(e,{label:u.trim()}),y(""),b(!1)),i.key==="Escape"&&b(!1)},onBlur:()=>{u.trim()||b(!1)},autoFocus:!0})}):f.jsx("button",{onClick:()=>b(!0),title:"Add label",style:{display:"inline-flex",alignItems:"center",justifyContent:"center",border:"none",background:"none",color:"var(--text-muted)",cursor:"pointer",padding:"1px 3px",marginLeft:"2px",opacity:.35,verticalAlign:"middle",transition:"var(--transition)"},onMouseEnter:i=>{i.currentTarget.style.opacity="1"},onMouseLeave:i=>{i.currentTarget.style.opacity="0.35"},children:f.jsx(j,{size:9})});const p=o.color||M(o.category);return f.jsxs("span",{style:{display:"inline-flex",alignItems:"center",gap:"3px",padding:"1px 5px 1px 3px",fontSize:"10px",fontFamily:"var(--font-mono)",background:`${p}18`,border:`1px solid ${p}45`,borderRadius:"4px",color:p,verticalAlign:"middle",marginLeft:"4px",whiteSpace:"nowrap",transition:"var(--transition)",cursor:"default"},title:[o.label,o.category!=="other"?`(${o.category})`:"",o.tags.length?`[${o.tags.join(", ")}]`:""].filter(Boolean).join(" "),children:[f.jsx("span",{style:{width:"6px",height:"6px",borderRadius:"50%",background:p,display:"inline-block",flexShrink:0}}),f.jsx("span",{style:{maxWidth:"80px",overflow:"hidden",textOverflow:"ellipsis"},children:o.label}),o.favorite&&f.jsx(I,{size:7,fill:p,style:{flexShrink:0}})]})}export{G as A,z as u}; +//# sourceMappingURL=AddressLabelBadge-BTvgU-lx.js.map diff --git a/dist/assets/AddressLabelBadge-BTvgU-lx.js.map b/dist/assets/AddressLabelBadge-BTvgU-lx.js.map new file mode 100644 index 00000000..be6b1157 --- /dev/null +++ b/dist/assets/AddressLabelBadge-BTvgU-lx.js.map @@ -0,0 +1 @@ +{"version":3,"file":"AddressLabelBadge-BTvgU-lx.js","sources":["../../src/lib/addressLabels.js","../../src/hooks/useAddressLabels.js","../../src/components/addressLabels/AddressLabelBadge.tsx"],"sourcesContent":["import { getStoredValue, setStoredValue } from './storage'\r\n\r\n// ─── Constants ─────────────────────────────────────────────────────────────────\r\n\r\nconst STORAGE_KEY = 'address-labels-v2'\r\n\r\nexport const CATEGORIES = [\r\n { value: 'personal', label: 'Personal', color: '#06b6d4' },\r\n { value: 'exchange', label: 'Exchange', color: '#f59e0b' },\r\n { value: 'defi', label: 'DeFi', color: '#8b5cf6' },\r\n { value: 'nft', label: 'NFT', color: '#ec4899' },\r\n { value: 'custodial', label: 'Custodial', color: '#6366f1' },\r\n { value: 'contract', label: 'Contract', color: '#14b8a6' },\r\n { value: 'other', label: 'Other', color: '#6b7280' },\r\n]\r\n\r\nexport const LABEL_COLORS = [\r\n { value: '#06b6d4', label: 'Cyan' },\r\n { value: '#22c55e', label: 'Green' },\r\n { value: '#f59e0b', label: 'Amber' },\r\n { value: '#ef4444', label: 'Red' },\r\n { value: '#8b5cf6', label: 'Purple' },\r\n { value: '#ec4899', label: 'Pink' },\r\n { value: '#6366f1', label: 'Indigo' },\r\n { value: '#14b8a6', label: 'Teal' },\r\n { value: '#6b7280', label: 'Gray' },\r\n]\r\n\r\nexport const DEFAULT_TAGS = [\r\n 'hot-wallet', 'cold-storage', 'multisig', 'personal',\r\n 'business', 'trading', 'liquidity', 'validator',\r\n]\r\n\r\n// ─── Types (JSDoc) ─────────────────────────────────────────────────────────────\r\n/*\r\n * @typedef {Object} LabelEntry\r\n * @property {string} address - Stellar public key (G...)\r\n * @property {string} label - Display name\r\n * @property {string[]} tags - Arbitrary tags\r\n * @property {string} category - One of CATEGORIES values\r\n * @property {string} color - Hex color from LABEL_COLORS\r\n * @property {boolean} favorite - Starred for quick access\r\n * @property {string} notes - Optional notes\r\n * @property {string} network - Network context\r\n * @property {string} createdAt - ISO timestamp\r\n * @property {string} updatedAt - ISO timestamp\r\n */\r\n\r\n// ─── In-memory cache ───────────────────────────────────────────────────────────\r\n\r\nlet _cache = null\r\nlet _listeners = new Set()\r\n\r\nfunction notifyListeners() {\r\n _listeners.forEach((fn) => {\r\n try { fn(_cache || []) } catch { /* ignore */ }\r\n })\r\n}\r\n\r\nfunction makeEntry(address, data) {\r\n return {\r\n address,\r\n label: data.label || address.slice(0, 8),\r\n tags: data.tags || [],\r\n category: data.category || 'other',\r\n color: data.color || undefined,\r\n favorite: !!data.favorite,\r\n notes: data.notes || '',\r\n network: data.network || 'all',\r\n createdAt: data.createdAt || new Date().toISOString(),\r\n updatedAt: new Date().toISOString(),\r\n }\r\n}\r\n\r\n// ─── Persistence ───────────────────────────────────────────────────────────────\r\n\r\nasync function loadAll() {\r\n if (_cache) return _cache\r\n try {\r\n const stored = await getStoredValue(STORAGE_KEY)\r\n _cache = Array.isArray(stored) ? stored : []\r\n } catch {\r\n _cache = []\r\n }\r\n return _cache\r\n}\r\n\r\nasync function persistAll() {\r\n try {\r\n await setStoredValue(STORAGE_KEY, _cache || [])\r\n } catch { /* ignore */ }\r\n}\r\n\r\n// ─── CRUD ──────────────────────────────────────────────────────────────────────\r\n\r\nexport async function addLabel(address, data) {\r\n const list = await loadAll()\r\n const idx = list.findIndex((e) => e.address === address)\r\n if (idx >= 0) {\r\n list[idx] = { ...list[idx], ...makeEntry(address, data), updatedAt: new Date().toISOString() }\r\n } else {\r\n list.push(makeEntry(address, data))\r\n }\r\n _cache = list\r\n await persistAll()\r\n notifyListeners()\r\n return _cache\r\n}\r\n\r\nexport async function updateLabel(address, data) {\r\n const list = await loadAll()\r\n const idx = list.findIndex((e) => e.address === address)\r\n if (idx < 0) return _cache\r\n list[idx] = { ...list[idx], ...data, updatedAt: new Date().toISOString() }\r\n _cache = list\r\n await persistAll()\r\n notifyListeners()\r\n return _cache\r\n}\r\n\r\nexport async function removeLabel(address) {\r\n const list = await loadAll()\r\n _cache = list.filter((e) => e.address !== address)\r\n await persistAll()\r\n notifyListeners()\r\n return _cache\r\n}\r\n\r\nexport async function getLabel(address) {\r\n const list = await loadAll()\r\n return list.find((e) => e.address === address) || null\r\n}\r\n\r\nexport async function getAllLabels() {\r\n return loadAll()\r\n}\r\n\r\nexport async function getLabelsByTag(tag) {\r\n const list = await loadAll()\r\n return list.filter((e) => e.tags.includes(tag))\r\n}\r\n\r\nexport async function getLabelsByCategory(category) {\r\n const list = await loadAll()\r\n return list.filter((e) => e.category === category)\r\n}\r\n\r\nexport async function getFavoriteLabels() {\r\n const list = await loadAll()\r\n return list.filter((e) => e.favorite)\r\n}\r\n\r\nexport async function searchLabels(query) {\r\n const list = await loadAll()\r\n const q = query.toLowerCase()\r\n return list.filter(\r\n (e) =>\r\n e.label.toLowerCase().includes(q) ||\r\n e.address.toLowerCase().includes(q) ||\r\n e.tags.some((t) => t.toLowerCase().includes(q)) ||\r\n e.notes.toLowerCase().includes(q)\r\n )\r\n}\r\n\r\nexport async function getAllTags() {\r\n const list = await loadAll()\r\n const tags = new Set()\r\n list.forEach((e) => e.tags.forEach((t) => tags.add(t)))\r\n return Array.from(tags).sort()\r\n}\r\n\r\nexport async function bulkImport(labels) {\r\n const list = await loadAll()\r\n labels.forEach((entry) => {\r\n const idx = list.findIndex((e) => e.address === entry.address)\r\n const newEntry = makeEntry(entry.address, entry)\r\n if (idx >= 0) {\r\n list[idx] = { ...list[idx], ...newEntry }\r\n } else {\r\n list.push(newEntry)\r\n }\r\n })\r\n _cache = list\r\n await persistAll()\r\n notifyListeners()\r\n return _cache\r\n}\r\n\r\n// ─── React Hook ────────────────────────────────────────────────────────────────\r\n\r\nexport function subscribe(fn) {\r\n _listeners.add(fn)\r\n return () => _listeners.delete(fn)\r\n}\r\n\r\nexport function getCachedLabels() {\r\n return _cache || []\r\n}\r\n\r\nexport default {\r\n addLabel,\r\n updateLabel,\r\n removeLabel,\r\n getLabel,\r\n getAllLabels,\r\n getLabelsByTag,\r\n getLabelsByCategory,\r\n getFavoriteLabels,\r\n searchLabels,\r\n getAllTags,\r\n bulkImport,\r\n subscribe,\r\n getCachedLabels,\r\n CATEGORIES,\r\n LABEL_COLORS,\r\n DEFAULT_TAGS,\r\n}\r\n","import { useState, useEffect, useCallback, useRef } from 'react'\r\nimport {\r\n addLabel as addLabelApi,\r\n updateLabel as updateLabelApi,\r\n removeLabel as removeLabelApi,\r\n getLabel as getLabelApi,\r\n getAllLabels,\r\n searchLabels as searchLabelsApi,\r\n subscribe,\r\n} from '../lib/addressLabels'\r\n\r\nexport function useAddressLabels() {\r\n const [labels, setLabels] = useState([])\r\n const [loading, setLoading] = useState(true)\r\n const [searchQuery, setSearchQuery] = useState('')\r\n const mountedRef = useRef(true)\r\n\r\n useEffect(() => {\r\n mountedRef.current = true\r\n getAllLabels().then((all) => {\r\n if (mountedRef.current) {\r\n setLabels(all)\r\n setLoading(false)\r\n }\r\n })\r\n\r\n const unsub = subscribe((updated) => {\r\n if (mountedRef.current) setLabels(updated)\r\n })\r\n\r\n return () => {\r\n mountedRef.current = false\r\n unsub()\r\n }\r\n }, [])\r\n\r\n const getLabel = useCallback(async (address) => {\r\n return getLabelApi(address)\r\n }, [])\r\n\r\n const addLabel = useCallback(async (address, data) => {\r\n await addLabelApi(address, data)\r\n }, [])\r\n\r\n const updateLabel = useCallback(async (address, data) => {\r\n await updateLabelApi(address, data)\r\n }, [])\r\n\r\n const removeLabel = useCallback(async (address) => {\r\n await removeLabelApi(address)\r\n }, [])\r\n\r\n const searchLabels = useCallback(async (query) => {\r\n setSearchQuery(query)\r\n if (!query.trim()) {\r\n const all = await getAllLabels()\r\n return all\r\n }\r\n return searchLabelsApi(query)\r\n }, [])\r\n\r\n const labelMap = {}\r\n labels.forEach((l) => { labelMap[l.address] = l })\r\n\r\n return {\r\n labels,\r\n labelMap,\r\n loading,\r\n searchQuery,\r\n setSearchQuery,\r\n getLabel,\r\n addLabel,\r\n updateLabel,\r\n removeLabel,\r\n searchLabels,\r\n }\r\n}\r\n\r\nexport default useAddressLabels\r\n","import React, { useState } from 'react'\r\nimport { Star, Plus } from 'lucide-react'\r\nimport { useAddressLabels } from '../../hooks/useAddressLabels'\r\nimport { CATEGORIES } from '../../lib/addressLabels'\r\nimport { isValidPublicKey } from '../../lib/stellar'\r\n\r\ninterface Category {\r\n value: string;\r\n color: string;\r\n}\r\n\r\nfunction categoryColor(cat: string): string {\r\n const found = (CATEGORIES as Category[]).find((c) => c.value === cat)\r\n return found ? found.color : '#6b7280'\r\n}\r\n\r\ninterface AddressLabelBadgeProps {\r\n address: string;\r\n showAddLabel?: boolean;\r\n}\r\n\r\nexport default function AddressLabelBadge({ address, showAddLabel = true }: AddressLabelBadgeProps) {\r\n const { labelMap, addLabel } = useAddressLabels()\r\n const [adding, setAdding] = useState(false)\r\n const [inputValue, setInputValue] = useState('')\r\n\r\n const entry = labelMap[address]\r\n\r\n if (!entry) {\r\n if (!showAddLabel || !address || !isValidPublicKey(address)) return null\r\n\r\n if (adding) {\r\n return (\r\n \r\n setInputValue(e.target.value)}\r\n placeholder=\"Label\"\r\n style={{\r\n width: '70px',\r\n padding: '1px 4px',\r\n fontSize: '10px',\r\n fontFamily: 'var(--font-mono)',\r\n background: 'var(--bg-card)',\r\n border: '1px solid var(--cyan-dim)',\r\n borderRadius: '3px',\r\n color: 'var(--text-primary)',\r\n outline: 'none',\r\n }}\r\n onKeyDown={async (e) => {\r\n if (e.key === 'Enter' && inputValue.trim()) {\r\n await addLabel(address, { label: inputValue.trim() })\r\n setInputValue('')\r\n setAdding(false)\r\n }\r\n if (e.key === 'Escape') setAdding(false)\r\n }}\r\n onBlur={() => {\r\n if (!inputValue.trim()) setAdding(false)\r\n }}\r\n autoFocus\r\n />\r\n \r\n )\r\n }\r\n\r\n return (\r\n setAdding(true)}\r\n title=\"Add label\"\r\n style={{\r\n display: 'inline-flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n border: 'none',\r\n background: 'none',\r\n color: 'var(--text-muted)',\r\n cursor: 'pointer',\r\n padding: '1px 3px',\r\n marginLeft: '2px',\r\n opacity: 0.35,\r\n verticalAlign: 'middle',\r\n transition: 'var(--transition)',\r\n }}\r\n onMouseEnter={(e) => { (e.currentTarget as HTMLButtonElement).style.opacity = '1' }}\r\n onMouseLeave={(e) => { (e.currentTarget as HTMLButtonElement).style.opacity = '0.35' }}\r\n >\r\n \r\n \r\n )\r\n }\r\n\r\n const dotColor = entry.color || categoryColor(entry.category)\r\n\r\n return (\r\n \r\n \r\n \r\n {entry.label}\r\n \r\n {entry.favorite && }\r\n \r\n )\r\n}\r\n"],"names":["STORAGE_KEY","CATEGORIES","_cache","_listeners","notifyListeners","fn","makeEntry","address","data","loadAll","stored","getStoredValue","persistAll","setStoredValue","addLabel","list","idx","e","updateLabel","removeLabel","getLabel","getAllLabels","searchLabels","query","q","t","subscribe","useAddressLabels","labels","setLabels","useState","loading","setLoading","searchQuery","setSearchQuery","mountedRef","useRef","useEffect","all","unsub","updated","useCallback","getLabelApi","addLabelApi","updateLabelApi","removeLabelApi","searchLabelsApi","labelMap","l","categoryColor","cat","found","c","AddressLabelBadge","showAddLabel","adding","setAdding","inputValue","setInputValue","entry","isValidPublicKey","jsx","Plus","dotColor","jsxs","Star"],"mappings":"0MAIA,MAAMA,EAAc,oBAEPC,EAAa,CACxB,CAAE,MAAO,WAAc,MAAO,WAAc,MAAO,SAAS,EAC5D,CAAE,MAAO,WAAc,MAAO,WAAc,MAAO,SAAS,EAC5D,CAAE,MAAO,OAAc,MAAO,OAAe,MAAO,SAAS,EAC7D,CAAE,MAAO,MAAc,MAAO,MAAe,MAAO,SAAS,EAC7D,CAAE,MAAO,YAAc,MAAO,YAAe,MAAO,SAAS,EAC7D,CAAE,MAAO,WAAc,MAAO,WAAe,MAAO,SAAS,EAC7D,CAAE,MAAO,QAAc,MAAO,QAAe,MAAO,SAAS,CAC/D,EAoCA,IAAIC,EAAS,KACTC,EAAa,IAAI,IAErB,SAASC,GAAkB,CACzBD,EAAW,QAASE,GAAO,CACzB,GAAI,CAAEA,EAAGH,GAAU,CAAA,CAAE,CAAE,MAAQ,CAAe,CAChD,CAAC,CACH,CAEA,SAASI,EAAUC,EAASC,EAAM,CAChC,MAAO,CACL,QAAAD,EACA,MAAOC,EAAK,OAASD,EAAQ,MAAM,EAAG,CAAC,EACvC,KAAMC,EAAK,MAAQ,CAAA,EACnB,SAAUA,EAAK,UAAY,QAC3B,MAAOA,EAAK,OAAS,OACrB,SAAU,CAAC,CAACA,EAAK,SACjB,MAAOA,EAAK,OAAS,GACrB,QAASA,EAAK,SAAW,MACzB,UAAWA,EAAK,WAAa,IAAI,KAAI,EAAG,YAAW,EACnD,UAAW,IAAI,KAAI,EAAG,YAAW,CACrC,CACA,CAIA,eAAeC,GAAU,CACvB,GAAIP,EAAQ,OAAOA,EACnB,GAAI,CACF,MAAMQ,EAAS,MAAMC,EAAeX,CAAW,EAC/CE,EAAS,MAAM,QAAQQ,CAAM,EAAIA,EAAS,CAAA,CAC5C,MAAQ,CACNR,EAAS,CAAA,CACX,CACA,OAAOA,CACT,CAEA,eAAeU,GAAa,CAC1B,GAAI,CACF,MAAMC,EAAeb,EAAaE,GAAU,EAAE,CAChD,MAAQ,CAAe,CACzB,CAIO,eAAeY,EAASP,EAASC,EAAM,CAC5C,MAAMO,EAAO,MAAMN,EAAO,EACpBO,EAAMD,EAAK,UAAWE,GAAMA,EAAE,UAAYV,CAAO,EACvD,OAAIS,GAAO,EACTD,EAAKC,CAAG,EAAI,CAAE,GAAGD,EAAKC,CAAG,EAAG,GAAGV,EAAUC,EAASC,CAAI,EAAG,UAAW,IAAI,KAAI,EAAG,YAAW,CAAE,EAE5FO,EAAK,KAAKT,EAAUC,EAASC,CAAI,CAAC,EAEpCN,EAASa,EACT,MAAMH,EAAU,EAChBR,EAAe,EACRF,CACT,CAEO,eAAegB,EAAYX,EAASC,EAAM,CAC/C,MAAMO,EAAO,MAAMN,EAAO,EACpBO,EAAMD,EAAK,UAAWE,GAAMA,EAAE,UAAYV,CAAO,EACvD,OAAIS,EAAM,IACVD,EAAKC,CAAG,EAAI,CAAE,GAAGD,EAAKC,CAAG,EAAG,GAAGR,EAAM,UAAW,IAAI,KAAI,EAAG,YAAW,CAAE,EACxEN,EAASa,EACT,MAAMH,EAAU,EAChBR,EAAe,GACRF,CACT,CAEO,eAAeiB,EAAYZ,EAAS,CAEzC,OAAAL,GADa,MAAMO,EAAO,GACZ,OAAQQ,GAAMA,EAAE,UAAYV,CAAO,EACjD,MAAMK,EAAU,EAChBR,EAAe,EACRF,CACT,CAEO,eAAekB,EAASb,EAAS,CAEtC,OADa,MAAME,EAAO,GACd,KAAMQ,GAAMA,EAAE,UAAYV,CAAO,GAAK,IACpD,CAEO,eAAec,GAAe,CACnC,OAAOZ,EAAO,CAChB,CAiBO,eAAea,EAAaC,EAAO,CACxC,MAAMR,EAAO,MAAMN,EAAO,EACpBe,EAAID,EAAM,YAAW,EAC3B,OAAOR,EAAK,OACTE,GACCA,EAAE,MAAM,cAAc,SAASO,CAAC,GAChCP,EAAE,QAAQ,cAAc,SAASO,CAAC,GAClCP,EAAE,KAAK,KAAMQ,GAAMA,EAAE,YAAW,EAAG,SAASD,CAAC,CAAC,GAC9CP,EAAE,MAAM,cAAc,SAASO,CAAC,CACtC,CACA,CA4BO,SAASE,EAAUrB,EAAI,CAC5B,OAAAF,EAAW,IAAIE,CAAE,EACV,IAAMF,EAAW,OAAOE,CAAE,CACnC,CCtLO,SAASsB,GAAmB,CACjC,KAAM,CAACC,EAAQC,CAAS,EAAIC,EAAAA,SAAS,CAAA,CAAE,EACjC,CAACC,EAASC,CAAU,EAAIF,EAAAA,SAAS,EAAI,EACrC,CAACG,EAAaC,CAAc,EAAIJ,EAAAA,SAAS,EAAE,EAC3CK,EAAaC,EAAAA,OAAO,EAAI,EAE9BC,EAAAA,UAAU,IAAM,CACdF,EAAW,QAAU,GACrBd,EAAY,EAAG,KAAMiB,GAAQ,CACvBH,EAAW,UACbN,EAAUS,CAAG,EACbN,EAAW,EAAK,EAEpB,CAAC,EAED,MAAMO,EAAQb,EAAWc,GAAY,CAC/BL,EAAW,SAASN,EAAUW,CAAO,CAC3C,CAAC,EAED,MAAO,IAAM,CACXL,EAAW,QAAU,GACrBI,EAAK,CACP,CACF,EAAG,CAAA,CAAE,EAEL,MAAMnB,EAAWqB,cAAY,MAAOlC,GAC3BmC,EAAYnC,CAAO,EACzB,CAAA,CAAE,EAECO,EAAW2B,EAAAA,YAAY,MAAOlC,EAASC,IAAS,CACpD,MAAMmC,EAAYpC,EAASC,CAAI,CACjC,EAAG,CAAA,CAAE,EAECU,EAAcuB,EAAAA,YAAY,MAAOlC,EAASC,IAAS,CACvD,MAAMoC,EAAerC,EAASC,CAAI,CACpC,EAAG,CAAA,CAAE,EAECW,EAAcsB,cAAY,MAAOlC,GAAY,CACjD,MAAMsC,EAAetC,CAAO,CAC9B,EAAG,CAAA,CAAE,EAECe,EAAemB,cAAY,MAAOlB,IACtCW,EAAeX,CAAK,EACfA,EAAM,OAIJuB,EAAgBvB,CAAK,EAHd,MAAMF,EAAY,GAI/B,CAAA,CAAE,EAEC0B,EAAW,CAAA,EACjB,OAAAnB,EAAO,QAASoB,GAAM,CAAED,EAASC,EAAE,OAAO,EAAIA,CAAE,CAAC,EAE1C,CACL,OAAApB,EACA,SAAAmB,EACA,QAAAhB,EACA,YAAAE,EACA,eAAAC,EACJ,SAAId,EACJ,SAAIN,EACJ,YAAII,EACJ,YAAIC,EACJ,aAAIG,CACJ,CACA,CCjEA,SAAS2B,EAAcC,EAAqB,CAC1C,MAAMC,EAASlD,EAA0B,KAAMmD,GAAMA,EAAE,QAAUF,CAAG,EACpE,OAAOC,EAAQA,EAAM,MAAQ,SAC/B,CAOA,SAAwBE,EAAkB,CAAE,QAAA9C,EAAS,aAAA+C,EAAe,IAAgC,CAClG,KAAM,CAAE,SAAAP,EAAU,SAAAjC,CAAA,EAAaa,EAAA,EACzB,CAAC4B,EAAQC,CAAS,EAAI1B,EAAAA,SAAS,EAAK,EACpC,CAAC2B,EAAYC,CAAa,EAAI5B,EAAAA,SAAS,EAAE,EAEzC6B,EAAQZ,EAASxC,CAAO,EAE9B,GAAI,CAACoD,EACH,MAAI,CAACL,GAAgB,CAAC/C,GAAW,CAACqD,EAAiBrD,CAAO,EAAU,KAEhEgD,EAEAM,EAAAA,IAAC,OAAA,CAAK,MAAO,CAAE,QAAS,cAAe,WAAY,SAAU,IAAK,MAAO,WAAY,MAAO,cAAe,UACzG,SAAAA,EAAAA,IAAC,QAAA,CACC,MAAOJ,EACP,SAAWxC,GAAMyC,EAAczC,EAAE,OAAO,KAAK,EAC7C,YAAY,QACZ,MAAO,CACL,MAAO,OACP,QAAS,UACT,SAAU,OACV,WAAY,mBACZ,WAAY,iBACZ,OAAQ,4BACR,aAAc,MACd,MAAO,sBACP,QAAS,MAAA,EAEX,UAAW,MAAOA,GAAM,CAClBA,EAAE,MAAQ,SAAWwC,EAAW,SAClC,MAAM3C,EAASP,EAAS,CAAE,MAAOkD,EAAW,KAAA,EAAQ,EACpDC,EAAc,EAAE,EAChBF,EAAU,EAAK,GAEbvC,EAAE,MAAQ,UAAUuC,EAAU,EAAK,CACzC,EACA,OAAQ,IAAM,CACPC,EAAW,UAAkB,EAAK,CACzC,EACA,UAAS,EAAA,CAAA,EAEb,EAKFI,EAAAA,IAAC,SAAA,CACC,QAAS,IAAML,EAAU,EAAI,EAC7B,MAAM,YACN,MAAO,CACL,QAAS,cACT,WAAY,SACZ,eAAgB,SAChB,OAAQ,OACR,WAAY,OACZ,MAAO,oBACP,OAAQ,UACR,QAAS,UACT,WAAY,MACZ,QAAS,IACT,cAAe,SACf,WAAY,mBAAA,EAEd,aAAevC,GAAM,CAAGA,EAAE,cAAoC,MAAM,QAAU,GAAI,EAClF,aAAeA,GAAM,CAAGA,EAAE,cAAoC,MAAM,QAAU,MAAO,EAErF,SAAA4C,EAAAA,IAACC,EAAA,CAAK,KAAM,CAAA,CAAG,CAAA,CAAA,EAKrB,MAAMC,EAAWJ,EAAM,OAASV,EAAcU,EAAM,QAAQ,EAE5D,OACEK,EAAAA,KAAC,OAAA,CACC,MAAO,CACL,QAAS,cACT,WAAY,SACZ,IAAK,MACL,QAAS,kBACT,SAAU,OACV,WAAY,mBACZ,WAAY,GAAGD,CAAQ,KACvB,OAAQ,aAAaA,CAAQ,KAC7B,aAAc,MACd,MAAOA,EACP,cAAe,SACf,WAAY,MACZ,WAAY,SACZ,WAAY,oBACZ,OAAQ,SAAA,EAEV,MAAO,CAACJ,EAAM,MAAOA,EAAM,WAAa,QAAU,IAAIA,EAAM,QAAQ,IAAM,GAAIA,EAAM,KAAK,OAAS,IAAIA,EAAM,KAAK,KAAK,IAAI,CAAC,IAAM,EAAE,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,EAE7J,SAAA,CAAAE,EAAAA,IAAC,OAAA,CAAK,MAAO,CAAE,MAAO,MAAO,OAAQ,MAAO,aAAc,MAAO,WAAYE,EAAU,QAAS,eAAgB,WAAY,GAAK,EACjIF,EAAAA,IAAC,OAAA,CAAK,MAAO,CAAE,SAAU,OAAQ,SAAU,SAAU,aAAc,UAAA,EAChE,SAAAF,EAAM,KAAA,CACT,EACCA,EAAM,UAAYE,EAAAA,IAACI,EAAA,CAAK,KAAM,EAAG,KAAMF,EAAU,MAAO,CAAE,WAAY,CAAA,CAAE,CAAG,CAAA,CAAA,CAAA,CAGlF"} \ No newline at end of file diff --git a/dist/assets/AddressLabelBadge-DrPlZQOF.js b/dist/assets/AddressLabelBadge-DrPlZQOF.js deleted file mode 100644 index edc10c37..00000000 --- a/dist/assets/AddressLabelBadge-DrPlZQOF.js +++ /dev/null @@ -1,2 +0,0 @@ -import{r as s,j as f}from"./react-vendor-CsepHXsi.js";import{g as k,s as C}from"./deployment-BPDW632H.js";import{n as E}from"./charts-OWQBHTRD.js";import{Y as j,i as I}from"./icons-vendor-BqasJArU.js";const S="address-labels-v2",$=[{value:"personal",label:"Personal",color:"#06b6d4"},{value:"exchange",label:"Exchange",color:"#f59e0b"},{value:"defi",label:"DeFi",color:"#8b5cf6"},{value:"nft",label:"NFT",color:"#ec4899"},{value:"custodial",label:"Custodial",color:"#6366f1"},{value:"contract",label:"Contract",color:"#14b8a6"},{value:"other",label:"Other",color:"#6b7280"}];let l=null,x=new Set;function m(){x.forEach(e=>{try{e(l||[])}catch{}})}function L(e,t){return{address:e,label:t.label||e.slice(0,8),tags:t.tags||[],category:t.category||"other",color:t.color||void 0,favorite:!!t.favorite,notes:t.notes||"",network:t.network||"all",createdAt:t.createdAt||new Date().toISOString(),updatedAt:new Date().toISOString()}}async function g(){if(l)return l;try{const e=await k(S);l=Array.isArray(e)?e:[]}catch{l=[]}return l}async function h(){try{await C(S,l||[])}catch{}}async function O(e,t){const a=await g(),n=a.findIndex(c=>c.address===e);return n>=0?a[n]={...a[n],...L(e,t),updatedAt:new Date().toISOString()}:a.push(L(e,t)),l=a,await h(),m(),l}async function R(e,t){const a=await g(),n=a.findIndex(c=>c.address===e);return n<0||(a[n]={...a[n],...t,updatedAt:new Date().toISOString()},l=a,await h(),m()),l}async function D(e){return l=(await g()).filter(a=>a.address!==e),await h(),m(),l}async function F(e){return(await g()).find(a=>a.address===e)||null}async function v(){return g()}async function T(e){const t=await g(),a=e.toLowerCase();return t.filter(n=>n.label.toLowerCase().includes(a)||n.address.toLowerCase().includes(a)||n.tags.some(c=>c.toLowerCase().includes(a))||n.notes.toLowerCase().includes(a))}function V(e){return x.add(e),()=>x.delete(e)}function z(){const[e,t]=s.useState([]),[a,n]=s.useState(!0),[c,b]=s.useState(""),u=s.useRef(!0);s.useEffect(()=>{u.current=!0,v().then(d=>{u.current&&(t(d),n(!1))});const r=V(d=>{u.current&&t(d)});return()=>{u.current=!1,r()}},[]);const y=s.useCallback(async r=>F(r),[]),o=s.useCallback(async(r,d)=>{await O(r,d)},[]),p=s.useCallback(async(r,d)=>{await R(r,d)},[]),i=s.useCallback(async r=>{await D(r)},[]),A=s.useCallback(async r=>(b(r),r.trim()?T(r):await v()),[]),w={};return e.forEach(r=>{w[r.address]=r}),{labels:e,labelMap:w,loading:a,searchQuery:c,setSearchQuery:b,getLabel:y,addLabel:o,updateLabel:p,removeLabel:i,searchLabels:A}}function M(e){const t=$.find(a=>a.value===e);return t?t.color:"#6b7280"}function G({address:e,showAddLabel:t=!0}){const{labelMap:a,addLabel:n}=z(),[c,b]=s.useState(!1),[u,y]=s.useState(""),o=a[e];if(!o)return!t||!e||!E(e)?null:c?f.jsx("span",{style:{display:"inline-flex",alignItems:"center",gap:"3px",marginLeft:"4px",verticalAlign:"middle"},children:f.jsx("input",{value:u,onChange:i=>y(i.target.value),placeholder:"Label",style:{width:"70px",padding:"1px 4px",fontSize:"10px",fontFamily:"var(--font-mono)",background:"var(--bg-card)",border:"1px solid var(--cyan-dim)",borderRadius:"3px",color:"var(--text-primary)",outline:"none"},onKeyDown:async i=>{i.key==="Enter"&&u.trim()&&(await n(e,{label:u.trim()}),y(""),b(!1)),i.key==="Escape"&&b(!1)},onBlur:()=>{u.trim()||b(!1)},autoFocus:!0})}):f.jsx("button",{onClick:()=>b(!0),title:"Add label",style:{display:"inline-flex",alignItems:"center",justifyContent:"center",border:"none",background:"none",color:"var(--text-muted)",cursor:"pointer",padding:"1px 3px",marginLeft:"2px",opacity:.35,verticalAlign:"middle",transition:"var(--transition)"},onMouseEnter:i=>{i.currentTarget.style.opacity="1"},onMouseLeave:i=>{i.currentTarget.style.opacity="0.35"},children:f.jsx(j,{size:9})});const p=o.color||M(o.category);return f.jsxs("span",{style:{display:"inline-flex",alignItems:"center",gap:"3px",padding:"1px 5px 1px 3px",fontSize:"10px",fontFamily:"var(--font-mono)",background:`${p}18`,border:`1px solid ${p}45`,borderRadius:"4px",color:p,verticalAlign:"middle",marginLeft:"4px",whiteSpace:"nowrap",transition:"var(--transition)",cursor:"default"},title:[o.label,o.category!=="other"?`(${o.category})`:"",o.tags.length?`[${o.tags.join(", ")}]`:""].filter(Boolean).join(" "),children:[f.jsx("span",{style:{width:"6px",height:"6px",borderRadius:"50%",background:p,display:"inline-block",flexShrink:0}}),f.jsx("span",{style:{maxWidth:"80px",overflow:"hidden",textOverflow:"ellipsis"},children:o.label}),o.favorite&&f.jsx(I,{size:7,fill:p,style:{flexShrink:0}})]})}export{G as A,z as u}; -//# sourceMappingURL=AddressLabelBadge-DrPlZQOF.js.map diff --git a/dist/assets/AddressLabelBadge-DrPlZQOF.js.map b/dist/assets/AddressLabelBadge-DrPlZQOF.js.map deleted file mode 100644 index 90cd822c..00000000 --- a/dist/assets/AddressLabelBadge-DrPlZQOF.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"AddressLabelBadge-DrPlZQOF.js","sources":["../../src/lib/addressLabels.js","../../src/hooks/useAddressLabels.js","../../src/components/addressLabels/AddressLabelBadge.tsx"],"sourcesContent":["import { getStoredValue, setStoredValue } from './storage'\n\n// ─── Constants ─────────────────────────────────────────────────────────────────\n\nconst STORAGE_KEY = 'address-labels-v2'\n\nexport const CATEGORIES = [\n { value: 'personal', label: 'Personal', color: '#06b6d4' },\n { value: 'exchange', label: 'Exchange', color: '#f59e0b' },\n { value: 'defi', label: 'DeFi', color: '#8b5cf6' },\n { value: 'nft', label: 'NFT', color: '#ec4899' },\n { value: 'custodial', label: 'Custodial', color: '#6366f1' },\n { value: 'contract', label: 'Contract', color: '#14b8a6' },\n { value: 'other', label: 'Other', color: '#6b7280' },\n]\n\nexport const LABEL_COLORS = [\n { value: '#06b6d4', label: 'Cyan' },\n { value: '#22c55e', label: 'Green' },\n { value: '#f59e0b', label: 'Amber' },\n { value: '#ef4444', label: 'Red' },\n { value: '#8b5cf6', label: 'Purple' },\n { value: '#ec4899', label: 'Pink' },\n { value: '#6366f1', label: 'Indigo' },\n { value: '#14b8a6', label: 'Teal' },\n { value: '#6b7280', label: 'Gray' },\n]\n\nexport const DEFAULT_TAGS = [\n 'hot-wallet', 'cold-storage', 'multisig', 'personal',\n 'business', 'trading', 'liquidity', 'validator',\n]\n\n// ─── Types (JSDoc) ─────────────────────────────────────────────────────────────\n/*\n * @typedef {Object} LabelEntry\n * @property {string} address - Stellar public key (G...)\n * @property {string} label - Display name\n * @property {string[]} tags - Arbitrary tags\n * @property {string} category - One of CATEGORIES values\n * @property {string} color - Hex color from LABEL_COLORS\n * @property {boolean} favorite - Starred for quick access\n * @property {string} notes - Optional notes\n * @property {string} network - Network context\n * @property {string} createdAt - ISO timestamp\n * @property {string} updatedAt - ISO timestamp\n */\n\n// ─── In-memory cache ───────────────────────────────────────────────────────────\n\nlet _cache = null\nlet _listeners = new Set()\n\nfunction notifyListeners() {\n _listeners.forEach((fn) => {\n try { fn(_cache || []) } catch { /* ignore */ }\n })\n}\n\nfunction makeEntry(address, data) {\n return {\n address,\n label: data.label || address.slice(0, 8),\n tags: data.tags || [],\n category: data.category || 'other',\n color: data.color || undefined,\n favorite: !!data.favorite,\n notes: data.notes || '',\n network: data.network || 'all',\n createdAt: data.createdAt || new Date().toISOString(),\n updatedAt: new Date().toISOString(),\n }\n}\n\n// ─── Persistence ───────────────────────────────────────────────────────────────\n\nasync function loadAll() {\n if (_cache) return _cache\n try {\n const stored = await getStoredValue(STORAGE_KEY)\n _cache = Array.isArray(stored) ? stored : []\n } catch {\n _cache = []\n }\n return _cache\n}\n\nasync function persistAll() {\n try {\n await setStoredValue(STORAGE_KEY, _cache || [])\n } catch { /* ignore */ }\n}\n\n// ─── CRUD ──────────────────────────────────────────────────────────────────────\n\nexport async function addLabel(address, data) {\n const list = await loadAll()\n const idx = list.findIndex((e) => e.address === address)\n if (idx >= 0) {\n list[idx] = { ...list[idx], ...makeEntry(address, data), updatedAt: new Date().toISOString() }\n } else {\n list.push(makeEntry(address, data))\n }\n _cache = list\n await persistAll()\n notifyListeners()\n return _cache\n}\n\nexport async function updateLabel(address, data) {\n const list = await loadAll()\n const idx = list.findIndex((e) => e.address === address)\n if (idx < 0) return _cache\n list[idx] = { ...list[idx], ...data, updatedAt: new Date().toISOString() }\n _cache = list\n await persistAll()\n notifyListeners()\n return _cache\n}\n\nexport async function removeLabel(address) {\n const list = await loadAll()\n _cache = list.filter((e) => e.address !== address)\n await persistAll()\n notifyListeners()\n return _cache\n}\n\nexport async function getLabel(address) {\n const list = await loadAll()\n return list.find((e) => e.address === address) || null\n}\n\nexport async function getAllLabels() {\n return loadAll()\n}\n\nexport async function getLabelsByTag(tag) {\n const list = await loadAll()\n return list.filter((e) => e.tags.includes(tag))\n}\n\nexport async function getLabelsByCategory(category) {\n const list = await loadAll()\n return list.filter((e) => e.category === category)\n}\n\nexport async function getFavoriteLabels() {\n const list = await loadAll()\n return list.filter((e) => e.favorite)\n}\n\nexport async function searchLabels(query) {\n const list = await loadAll()\n const q = query.toLowerCase()\n return list.filter(\n (e) =>\n e.label.toLowerCase().includes(q) ||\n e.address.toLowerCase().includes(q) ||\n e.tags.some((t) => t.toLowerCase().includes(q)) ||\n e.notes.toLowerCase().includes(q)\n )\n}\n\nexport async function getAllTags() {\n const list = await loadAll()\n const tags = new Set()\n list.forEach((e) => e.tags.forEach((t) => tags.add(t)))\n return Array.from(tags).sort()\n}\n\nexport async function bulkImport(labels) {\n const list = await loadAll()\n labels.forEach((entry) => {\n const idx = list.findIndex((e) => e.address === entry.address)\n const newEntry = makeEntry(entry.address, entry)\n if (idx >= 0) {\n list[idx] = { ...list[idx], ...newEntry }\n } else {\n list.push(newEntry)\n }\n })\n _cache = list\n await persistAll()\n notifyListeners()\n return _cache\n}\n\n// ─── React Hook ────────────────────────────────────────────────────────────────\n\nexport function subscribe(fn) {\n _listeners.add(fn)\n return () => _listeners.delete(fn)\n}\n\nexport function getCachedLabels() {\n return _cache || []\n}\n\nexport default {\n addLabel,\n updateLabel,\n removeLabel,\n getLabel,\n getAllLabels,\n getLabelsByTag,\n getLabelsByCategory,\n getFavoriteLabels,\n searchLabels,\n getAllTags,\n bulkImport,\n subscribe,\n getCachedLabels,\n CATEGORIES,\n LABEL_COLORS,\n DEFAULT_TAGS,\n}\n","import { useState, useEffect, useCallback, useRef } from 'react'\nimport {\n addLabel as addLabelApi,\n updateLabel as updateLabelApi,\n removeLabel as removeLabelApi,\n getLabel as getLabelApi,\n getAllLabels,\n searchLabels as searchLabelsApi,\n subscribe,\n} from '../lib/addressLabels'\n\nexport function useAddressLabels() {\n const [labels, setLabels] = useState([])\n const [loading, setLoading] = useState(true)\n const [searchQuery, setSearchQuery] = useState('')\n const mountedRef = useRef(true)\n\n useEffect(() => {\n mountedRef.current = true\n getAllLabels().then((all) => {\n if (mountedRef.current) {\n setLabels(all)\n setLoading(false)\n }\n })\n\n const unsub = subscribe((updated) => {\n if (mountedRef.current) setLabels(updated)\n })\n\n return () => {\n mountedRef.current = false\n unsub()\n }\n }, [])\n\n const getLabel = useCallback(async (address) => {\n return getLabelApi(address)\n }, [])\n\n const addLabel = useCallback(async (address, data) => {\n await addLabelApi(address, data)\n }, [])\n\n const updateLabel = useCallback(async (address, data) => {\n await updateLabelApi(address, data)\n }, [])\n\n const removeLabel = useCallback(async (address) => {\n await removeLabelApi(address)\n }, [])\n\n const searchLabels = useCallback(async (query) => {\n setSearchQuery(query)\n if (!query.trim()) {\n const all = await getAllLabels()\n return all\n }\n return searchLabelsApi(query)\n }, [])\n\n const labelMap = {}\n labels.forEach((l) => { labelMap[l.address] = l })\n\n return {\n labels,\n labelMap,\n loading,\n searchQuery,\n setSearchQuery,\n getLabel,\n addLabel,\n updateLabel,\n removeLabel,\n searchLabels,\n }\n}\n\nexport default useAddressLabels\n","import React, { useState } from 'react'\nimport { Star, Plus } from 'lucide-react'\nimport { useAddressLabels } from '../../hooks/useAddressLabels'\nimport { CATEGORIES } from '../../lib/addressLabels'\nimport { isValidPublicKey } from '../../lib/stellar'\n\ninterface Category {\n value: string;\n color: string;\n}\n\nfunction categoryColor(cat: string): string {\n const found = (CATEGORIES as Category[]).find((c) => c.value === cat)\n return found ? found.color : '#6b7280'\n}\n\ninterface AddressLabelBadgeProps {\n address: string;\n showAddLabel?: boolean;\n}\n\nexport default function AddressLabelBadge({ address, showAddLabel = true }: AddressLabelBadgeProps) {\n const { labelMap, addLabel } = useAddressLabels()\n const [adding, setAdding] = useState(false)\n const [inputValue, setInputValue] = useState('')\n\n const entry = labelMap[address]\n\n if (!entry) {\n if (!showAddLabel || !address || !isValidPublicKey(address)) return null\n\n if (adding) {\n return (\n \n setInputValue(e.target.value)}\n placeholder=\"Label\"\n style={{\n width: '70px',\n padding: '1px 4px',\n fontSize: '10px',\n fontFamily: 'var(--font-mono)',\n background: 'var(--bg-card)',\n border: '1px solid var(--cyan-dim)',\n borderRadius: '3px',\n color: 'var(--text-primary)',\n outline: 'none',\n }}\n onKeyDown={async (e) => {\n if (e.key === 'Enter' && inputValue.trim()) {\n await addLabel(address, { label: inputValue.trim() })\n setInputValue('')\n setAdding(false)\n }\n if (e.key === 'Escape') setAdding(false)\n }}\n onBlur={() => {\n if (!inputValue.trim()) setAdding(false)\n }}\n autoFocus\n />\n \n )\n }\n\n return (\n setAdding(true)}\n title=\"Add label\"\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n border: 'none',\n background: 'none',\n color: 'var(--text-muted)',\n cursor: 'pointer',\n padding: '1px 3px',\n marginLeft: '2px',\n opacity: 0.35,\n verticalAlign: 'middle',\n transition: 'var(--transition)',\n }}\n onMouseEnter={(e) => { (e.currentTarget as HTMLButtonElement).style.opacity = '1' }}\n onMouseLeave={(e) => { (e.currentTarget as HTMLButtonElement).style.opacity = '0.35' }}\n >\n \n \n )\n }\n\n const dotColor = entry.color || categoryColor(entry.category)\n\n return (\n \n \n \n {entry.label}\n \n {entry.favorite && }\n \n )\n}\n"],"names":["STORAGE_KEY","CATEGORIES","_cache","_listeners","notifyListeners","fn","makeEntry","address","data","loadAll","stored","getStoredValue","persistAll","setStoredValue","addLabel","list","idx","e","updateLabel","removeLabel","getLabel","getAllLabels","searchLabels","query","q","t","subscribe","useAddressLabels","labels","setLabels","useState","loading","setLoading","searchQuery","setSearchQuery","mountedRef","useRef","useEffect","all","unsub","updated","useCallback","getLabelApi","addLabelApi","updateLabelApi","removeLabelApi","searchLabelsApi","labelMap","l","categoryColor","cat","found","c","AddressLabelBadge","showAddLabel","adding","setAdding","inputValue","setInputValue","entry","isValidPublicKey","jsx","Plus","dotColor","jsxs","Star"],"mappings":"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"} \ No newline at end of file diff --git a/dist/assets/AdvancedSearch-DvI37z7f.js b/dist/assets/AdvancedSearch-DvI37z7f.js deleted file mode 100644 index b5e55893..00000000 --- a/dist/assets/AdvancedSearch-DvI37z7f.js +++ /dev/null @@ -1,2 +0,0 @@ -import{r as h,j as s}from"./react-vendor-CsepHXsi.js";import{a5 as I}from"./charts-OWQBHTRD.js";import{I as H,ay as be,ap as Ce,R as V,az as Te,aA as we,aB as Re,av as te,a0 as se,X as Z,aC as Ae,aD as Fe,A as re,ad as ze,aE as ae,am as ne,u as ke,a9 as ie,S as Ie,e as _e,D as De}from"./icons-vendor-BqasJArU.js";import{f as Oe}from"./date-vendor-boStncAG.js";import"./vendor-Du79euYq.js";import"./deployment-BPDW632H.js";import"./stellar-sdk-or8ZbYCb.js";import"./charts-vendor-BIh5SzZ7.js";const y={history:"stellar-advanced-search-history-v1",saved:"stellar-advanced-search-saved-v1",alerts:"stellar-advanced-search-alerts-v1",folders:"stellar-advanced-search-folders-v1"};function He(){try{return typeof localStorage<"u"?localStorage:null}catch{return null}}function _(o,e,t=[]){if(!o)return[...t];try{const r=JSON.parse(o.getItem(e)||"null");return Array.isArray(r)?r:[...t]}catch{return[...t]}}function S(o,e,t){if(o)try{o.setItem(e,JSON.stringify(t))}catch{}}function B(o){return Array.isArray(o)?`[${o.map(B).join(",")}]`:o&&typeof o=="object"?`{${Object.keys(o).sort().map(e=>`${JSON.stringify(e)}:${B(o[e])}`).join(",")}}`:JSON.stringify(o)}function D(o){return`${o}-${Date.now()}-${Math.random().toString(36).slice(2,8)}`}function Le(o){const e=encodeURIComponent(JSON.stringify(o));return typeof btoa=="function"?btoa(e):e}function Me(o){const e=typeof atob=="function"?atob(o):o;return JSON.parse(decodeURIComponent(e))}class Ee{constructor(e={}){this.storage=e.storage||He(),this.searchHistory=_(this.storage,y.history),this.savedSearches=_(this.storage,y.saved),this.searchAlerts=_(this.storage,y.alerts),this.savedQueryFolders=_(this.storage,y.folders,[{id:"general",name:"General",createdAt:new Date().toISOString()}]),this.resultCache=new Map,this.cacheTtlMs=e.cacheTtlMs||60*1e3,this.indexedData=new Map,this.searchIndex=new Map,this.filters={dateRange:{start:null,end:null},assetType:null,operationType:null,amountRange:{min:null,max:null},addressFilter:null,memoFilter:null,statusFilter:null,networkFilter:null},this.sortOptions={field:"timestamp",direction:"desc"}}indexData(e,t){if(!Array.isArray(t))return;const r=t.map(n=>this.createSearchableItem(e,n));this.indexedData.set(e,r),r.forEach(n=>{this.extractSearchTerms(n).forEach(d=>{this.searchIndex.has(d)||this.searchIndex.set(d,new Set),this.searchIndex.get(d).add(n.id)})})}createSearchableItem(e,t){const r={id:`${e}_${t.id||t.hash||t.address}`,type:e,data:t,timestamp:this.extractTimestamp(t),amount:this.extractAmount(t),asset:this.extractAsset(t),operationType:this.extractOperationType(t),address:this.extractAddress(t),memo:this.extractMemo(t),status:this.extractStatus(t),network:t.network||"unknown"};switch(e){case"transactions":r.transactionHash=t.hash,r.fee=t.fee,r.operationCount=t.operation_count;break;case"operations":r.operationId=t.id,r.transactionHash=t.transaction_hash,r.sourceAccount=t.source_account;break;case"contracts":r.contractId=t.contract_id||t.id,r.contractType=t.type;break;case"accounts":r.accountId=t.account_id||t.address,r.balance=t.balance,r.sequence=t.sequence;break}return r}extractSearchTerms(e){const t=new Set;return t.add(e.type.toLowerCase()),t.add(e.operationType?.toLowerCase()||""),t.add(e.asset?.toLowerCase()||""),t.add(e.status?.toLowerCase()||""),t.add(e.network?.toLowerCase()||""),e.address&&t.add(e.address.toLowerCase()),e.transactionHash&&t.add(e.transactionHash.toLowerCase()),e.contractId&&t.add(e.contractId.toLowerCase()),e.accountId&&t.add(e.accountId.toLowerCase()),e.memo&&(t.add(e.memo.toLowerCase()),e.memo.toLowerCase().split(/\s+/).forEach(r=>{r.length>2&&t.add(r)})),e.amount&&(t.add(e.amount.toString()),t.add(parseFloat(e.amount).toFixed(2))),this.extractDataSpecificTerms(e.data,t),Array.from(t).filter(r=>r.length>0)}extractDataSpecificTerms(e,t){const r=(n,l="")=>{Object.entries(n).forEach(([d,u])=>{const p=l?`${l}.${d}`:d;typeof u=="string"&&u.length>0?(t.add(u.toLowerCase()),u.toLowerCase().split(/\s+/).forEach(v=>{v.length>2&&t.add(v)})):typeof u=="number"?t.add(u.toString()):typeof u=="object"&&u!==null&&r(u,p)})};r(e)}extractTimestamp(e){return e.created_at?new Date(e.created_at).getTime():e.timestamp?new Date(e.timestamp).getTime():e.time?new Date(e.time).getTime():Date.now()}extractAmount(e){return e.amount?parseFloat(e.amount):e.starting_balance?parseFloat(e.starting_balance):e.amount_in?parseFloat(e.amount_in):e.amount_out?parseFloat(e.amount_out):null}extractAsset(e){return e.asset_code?e.asset_code:e.asset_type==="native"?"XLM":e.asset_code&&e.asset_issuer?`${e.asset_code}:${e.asset_issuer}`:null}extractOperationType(e){return e.type?e.type:e.operation_type?this.getOperationTypeName(e.operation_type):null}getOperationTypeName(e){return{0:"payment",1:"create_account",2:"manage_offer",3:"set_options",4:"change_trust",5:"allow_trust",6:"account_merge",7:"inflation",8:"manage_data",9:"bump_sequence",10:"create_claimable_balance",11:"claim_claimable_balance",12:"begin_sponsoring_future_reserves",13:"end_sponsoring_future_reserves",14:"revoke_sponsorship"}[e]||"unknown"}extractAddress(e){return e.account_id?e.account_id:e.source_account?e.source_account:e.destination_account?e.destination_account:e.address?e.address:null}extractMemo(e){if(e.memo)return e.memo;if(e.memo_type&&e.memo_value){if(e.memo_type==="text")return e.memo_value;if(e.memo_type==="id")return e.memo_value.toString()}return null}extractStatus(e){return e.status?e.status:e.successful!==void 0?e.successful?"success":"failed":e.result_successful!==void 0?e.result_successful?"success":"failed":null}search(e){const t=Date.now();try{const r=this.optimizeQuery(e);r.filters&&(this.filters={...this.filters,...r.filters}),r.sort&&(this.sortOptions={...this.sortOptions,...r.sort});const n=this.buildQueryPlan(r),l=this.createQueryKey({...r,filters:this.filters,sort:this.sortOptions}),d=r.cache!==!1?this.getCachedResults(l):null;if(d){const b={...d,query:r,cached:!0,searchTime:Date.now()-t,queryPlan:n};return this.addToSearchHistory(r,{resultCount:d.total,searchTime:b.searchTime,cached:!0}),b}let u=[];this.indexedData.forEach((b,L)=>{(!r.types||r.types.includes(L))&&u.push(...b)}),r.text&&r.text.trim()&&(u=this.applyTextSearch(u,r.text.trim())),u=this.applyFilters(u),u=this.applySorting(u);const p=this.applyPagination(u,r.page,r.limit),v=Date.now()-t,T={query:r,results:p.items,total:p.total,page:p.page,limit:p.limit,searchTime:v,cached:!1,cacheKey:l,queryPlan:n,filters:{...this.filters},sort:{...this.sortOptions},aggregations:this.calculateAggregations(u)};return this.setCachedResults(l,T),this.addToSearchHistory(r,{resultCount:T.total,searchTime:v,cached:!1}),T}catch(r){throw new Error(`Search failed: ${r.message}`)}}applyTextSearch(e,t){const r=t.toLowerCase().split(/\s+/).filter(n=>n.length>0);return r.length===0?e:e.filter(n=>r.every(l=>this.itemContainsTerm(n,l)))}itemContainsTerm(e,t){if(e.type?.toLowerCase().includes(t)||e.operationType?.toLowerCase().includes(t)||e.asset?.toLowerCase().includes(t)||e.status?.toLowerCase().includes(t)||e.address?.toLowerCase().includes(t)||e.memo?.toLowerCase().includes(t)||e.transactionHash?.toLowerCase().includes(t)||e.contractId?.toLowerCase().includes(t)||e.accountId?.toLowerCase().includes(t)||e.amount?.toString().includes(t))return!0;const r=this.searchIndex.get(t.toLowerCase());return!!(r&&r.has(e.id))}applyFilters(e){return e.filter(t=>!(this.filters.dateRange.start&&t.timestampthis.filters.dateRange.end||this.filters.assetType&&t.asset!==this.filters.assetType||this.filters.operationType&&t.operationType!==this.filters.operationType||this.filters.amountRange.min!==null&&(!t.amount||t.amountthis.filters.amountRange.max)||this.filters.addressFilter&&!t.address?.includes(this.filters.addressFilter)||this.filters.memoFilter&&!t.memo?.toLowerCase().includes(this.filters.memoFilter.toLowerCase())||this.filters.statusFilter&&t.status!==this.filters.statusFilter||this.filters.networkFilter&&t.network!==this.filters.networkFilter))}applySorting(e){const{field:t,direction:r}=this.sortOptions;return e.sort((n,l)=>{let d=n[t],u=l[t];d==null&&(d=""),u==null&&(u="");let p=0;return typeof d=="number"&&typeof u=="number"?p=d-u:p=String(d).localeCompare(String(u)),r==="asc"?p:-p})}applyPagination(e,t=1,r=20){const n=(t-1)*r,l=n+r;return{items:e.slice(n,l),total:e.length,page:t,limit:r,totalPages:Math.ceil(e.length/r)}}calculateAggregations(e){const t={typeCounts:{},operationTypeCounts:{},assetCounts:{},statusCounts:{},totalAmount:0,averageAmount:0,dateRange:{earliest:null,latest:null}};e.forEach(n=>{t.typeCounts[n.type]=(t.typeCounts[n.type]||0)+1,n.operationType&&(t.operationTypeCounts[n.operationType]=(t.operationTypeCounts[n.operationType]||0)+1),n.asset&&(t.assetCounts[n.asset]=(t.assetCounts[n.asset]||0)+1),n.status&&(t.statusCounts[n.status]=(t.statusCounts[n.status]||0)+1),n.amount&&(t.totalAmount+=n.amount),n.timestamp&&((!t.dateRange.earliest||n.timestampt.dateRange.latest)&&(t.dateRange.latest=n.timestamp))});const r=e.filter(n=>n.amount!==null).length;return t.averageAmount=r>0?t.totalAmount/r:0,t}optimizeQuery(e={}){const t=(e.text||"").trim(),r=Array.isArray(e.types)&&e.types.length?Array.from(new Set(e.types)).sort():null;return{...e,text:t,types:r,page:Math.max(Number(e.page)||1,1),limit:Math.min(Math.max(Number(e.limit)||20,1),100)}}createQueryKey(e){return B({text:e.text||"",types:e.types||null,filters:e.filters||{},sort:e.sort||{},page:e.page||1,limit:e.limit||20})}setCachedResults(e,t){this.resultCache.set(e,{expiresAt:Date.now()+this.cacheTtlMs,result:t})}getCachedResults(e){const t=this.resultCache.get(e);return t?t.expiresAt<=Date.now()?(this.resultCache.delete(e),null):t.result:null}clearResultCache(){this.resultCache.clear()}buildQueryPlan(e){const t=(e.text||"").toLowerCase().split(/\s+/).filter(Boolean),r=t.filter(l=>this.searchIndex.has(l)),n=Object.values(e.filters||{}).filter(l=>l&&typeof l=="object"?Object.values(l).some(d=>d!==null&&d!==""):l!==null&&l!=="").length;return{textTerms:t,indexedTerms:r,filterCount:n,usesIndex:r.length>0,cacheTtlMs:this.cacheTtlMs,indexedTypes:e.types||Array.from(this.indexedData.keys())}}addToSearchHistory(e,t={}){const r={id:D("history"),timestamp:new Date().toISOString(),query:{...e},resultCount:t.resultCount||0,searchTime:t.searchTime||0,cached:!!t.cached};this.searchHistory.unshift(r),this.searchHistory.length>50&&(this.searchHistory=this.searchHistory.slice(0,50)),S(this.storage,y.history,this.searchHistory)}saveSearch(e,t,r={}){const n=r.folder||"General";this.createSavedSearchFolder(n);const l={id:D("saved"),name:e,query:{...t},folder:n,tags:r.tags||[],description:r.description||"",sharedWith:[],shareToken:null,createdAt:new Date().toISOString(),updatedAt:new Date().toISOString(),usageCount:0};return this.savedSearches.push(l),S(this.storage,y.saved,this.savedSearches),l}getSavedSearches(e={}){return[...this.savedSearches].filter(t=>!e.folder||t.folder===e.folder).sort((t,r)=>r.usageCount-t.usageCount||new Date(r.updatedAt||r.createdAt).getTime()-new Date(t.updatedAt||t.createdAt).getTime())}loadSavedSearch(e){const t=this.savedSearches.find(r=>r.id===e);return t?(t.usageCount+=1,t.updatedAt=new Date().toISOString(),S(this.storage,y.saved,this.savedSearches),t):null}deleteSavedSearch(e){this.savedSearches=this.savedSearches.filter(t=>t.id!==e),S(this.storage,y.saved,this.savedSearches)}createSavedSearchFolder(e){const t=(e||"General").trim()||"General",r=this.savedQueryFolders.find(l=>l.name.toLowerCase()===t.toLowerCase());if(r)return r;const n={id:D("folder"),name:t,createdAt:new Date().toISOString()};return this.savedQueryFolders.push(n),S(this.storage,y.folders,this.savedQueryFolders),n}getSavedSearchFolders(){return this.savedQueryFolders.map(e=>({...e,count:this.savedSearches.filter(t=>t.folder===e.name).length}))}shareSearch(e,t={}){const r=this.savedSearches.find(n=>n.id===e);if(!r)throw new Error("Saved search not found");return r.sharedWith=Array.from(new Set([...r.sharedWith||[],...t.users||[]])),r.shareToken=r.shareToken||Le({id:r.id,name:r.name,query:r.query,folder:r.folder}),r.updatedAt=new Date().toISOString(),S(this.storage,y.saved,this.savedSearches),r.shareToken}importSharedSearch(e,t={}){const r=Me(e);return this.saveSearch(t.name||r.name,r.query,{folder:t.folder||r.folder||"Shared",tags:["shared"]})}createSearchAlert(e){const t={id:D("alert"),savedSearchId:e.savedSearchId||null,name:e.name||"Search alert",query:e.query||this.savedSearches.find(r=>r.id===e.savedSearchId)?.query||{},cron:e.cron||"0 * * * *",channels:e.channels||["in-app"],threshold:Number(e.threshold||1),enabled:e.enabled!==!1,lastRunAt:null,nextRunAt:this.getNextAlertRun(e.cron||"0 * * * *"),createdAt:new Date().toISOString()};return this.searchAlerts.push(t),S(this.storage,y.alerts,this.searchAlerts),t}getSearchAlerts(){return[...this.searchAlerts].sort((e,t)=>new Date(e.nextRunAt).getTime()-new Date(t.nextRunAt).getTime())}getNextAlertRun(e,t=new Date){const[r="0",n="*"]=e.trim().split(/\s+/),l=new Date(t);return l.setSeconds(0,0),l.setMinutes(l.getMinutes()+1),r!=="*"&&l.setMinutes(Number(r.replace("*/",""))||0),n!=="*"&&l.setHours(Number(n.replace("*/",""))||l.getHours()),l.getTime()<=t.getTime()&&l.setHours(l.getHours()+1),l.toISOString()}evaluateSearchAlerts(e=new Date){return this.searchAlerts.filter(t=>t.enabled&&new Date(t.nextRunAt).getTime()<=e.getTime()).map(t=>{const r=this.search({...t.query,cache:!1});return t.lastRunAt=e.toISOString(),t.nextRunAt=this.getNextAlertRun(t.cron,e),S(this.storage,y.alerts,this.searchAlerts),{alert:t,resultCount:r.total,triggered:r.total>=t.threshold}})}getSearchHistory(){return[...this.searchHistory]}getFrequentSearches(e=5){const t=new Map;return this.searchHistory.forEach(r=>{const n=r.query?.text||JSON.stringify(r.query?.filters||{});t.set(n,(t.get(n)||0)+1)}),Array.from(t.entries()).map(([r,n])=>({query:r,count:n})).sort((r,n)=>n.count-r.count).slice(0,e)}getSearchAnalytics(){const e=this.getSearchHistory(),t=e.reduce((r,n)=>r+(n.searchTime||0),0);return{totalSearches:e.length,cachedSearches:e.filter(r=>r.cached).length,averageSearchTime:e.length?t/e.length:0,savedSearches:this.savedSearches.length,folders:this.savedQueryFolders.length,alerts:this.searchAlerts.length,frequentSearches:this.getFrequentSearches(),cacheEntries:this.resultCache.size}}getSuggestions(e){if(!e||e.length<2)return[];const t=new Set,r=e.toLowerCase();return this.searchIndex.forEach((d,u)=>{u.includes(r)&&t.add(u)}),["payment","create_account","manage_offer","set_options","change_trust"].forEach(d=>{d.includes(r)&&t.add(d)}),["XLM","USDC","BTC","ETH","USDT"].forEach(d=>{d.toLowerCase().includes(r)&&t.add(d)}),Array.from(t).slice(0,10)}clearHistory(){this.searchHistory=[]}resetFilters(){this.filters={dateRange:{start:null,end:null},assetType:null,operationType:null,amountRange:{min:null,max:null},addressFilter:null,memoFilter:null,statusFilter:null,networkFilter:null}}getFilters(){return{...this.filters}}getStatistics(){return{indexedItems:Array.from(this.indexedData.values()).reduce((e,t)=>e+t.length,0),indexedTypes:Array.from(this.indexedData.keys()),searchTerms:this.searchIndex.size,searchHistory:this.searchHistory.length,savedSearches:this.savedSearches.length}}}const m=new Ee;function Ke(){const[o,e]=h.useState(""),[t,r]=h.useState(null),[n,l]=h.useState(!1),[d,u]=h.useState(!1),[p,v]=h.useState(!1),[T,b]=h.useState([]),[L,oe]=h.useState([]),[w,le]=h.useState(null),[de,ce]=h.useState([]),[N,q]=h.useState([]),[ue,M]=h.useState(!1),[R,P]=h.useState(["transactions","operations","contracts","accounts"]),[F,$]=h.useState("General"),[z,he]=h.useState(!1),[U,pe]=h.useState("0 * * * *"),[Q,xe]=h.useState(""),[c,f]=h.useState({dateRange:{start:"",end:""},assetType:"",operationType:"",amountRange:{min:"",max:""},addressFilter:"",memoFilter:"",statusFilter:"",networkFilter:""}),[W,ge]=h.useState({field:"timestamp",direction:"desc"}),[G,J]=h.useState({page:1,limit:20});h.useEffect(()=>{A()},[]),h.useEffect(()=>{if(o.length>1){const a=m.getSuggestions(o);q(a),M(!0)}else q([]),M(!1)},[o]);const A=()=>{b(m.getSavedSearches()),oe(m.getSavedSearchFolders()),ce(m.getSearchHistory()),le(m.getSearchAnalytics())},k=async()=>{if(!(!o.trim()&&!X())){l(!0);try{const a={text:o.trim(),types:R,filters:K(),sort:W,page:G.page,limit:G.limit},i=m.search(a);r(i),I.logUserAction("Performed advanced search",{query:o.trim(),types:R,resultCount:i.total,searchTime:i.searchTime}),A()}catch(a){I.logError(a,{operation:"advancedSearch",query:o}),console.error("Search failed:",a)}finally{l(!1)}}},K=()=>{const a={};return c.dateRange.start&&(a.dateRange={...a.dateRange,start:new Date(c.dateRange.start).getTime()}),c.dateRange.end&&(a.dateRange={...a.dateRange,end:new Date(c.dateRange.end).getTime()}),c.assetType&&(a.assetType=c.assetType),c.operationType&&(a.operationType=c.operationType),c.addressFilter&&(a.addressFilter=c.addressFilter),c.memoFilter&&(a.memoFilter=c.memoFilter),c.statusFilter&&(a.statusFilter=c.statusFilter),c.networkFilter&&(a.networkFilter=c.networkFilter),c.amountRange.min&&(a.amountRange={...a.amountRange,min:parseFloat(c.amountRange.min)}),c.amountRange.max&&(a.amountRange={...a.amountRange,max:parseFloat(c.amountRange.max)}),a},X=()=>Object.values(c).some(a=>typeof a=="object"&&a!==null?Object.values(a).some(i=>i!==""):a!==""),Y=()=>{f({dateRange:{start:"",end:""},assetType:"",operationType:"",amountRange:{min:"",max:""},addressFilter:"",memoFilter:"",statusFilter:"",networkFilter:""}),m.resetFilters()},fe=()=>{const a=prompt("Enter a name for this search:");if(a){const i={text:o.trim(),types:R,filters:K(),sort:W},x=m.saveSearch(a,i,{folder:F});z&&m.createSearchAlert({savedSearchId:x.id,name:`${a} alert`,cron:U,channels:["in-app"]}),A(),I.logUserAction("Saved search",{name:a,query:i})}},ye=a=>{const i=m.loadSavedSearch(a.id)||a;e(i.query.text||""),P(i.query.types||["transactions","operations"]),Y(),i.query.filters&&f({...c,...i.query.filters}),i.query.sort&&ge(i.query.sort),v(!1),A(),k()},me=(a,i)=>{a.stopPropagation();const x=m.shareSearch(i.id);xe(x),A()},ve=()=>{if(!t)return;const a=JSON.stringify(t,null,2),i=new Blob([a],{type:"application/json"}),x=URL.createObjectURL(i),E=document.createElement("a");E.href=x,E.download=`stellar-search-results-${Date.now()}.json`,E.click(),URL.revokeObjectURL(x),I.logUserAction("Exported search results",{resultCount:t.total})},Se=a=>{e(a),M(!1)},je=a=>{P(i=>i.includes(a)?i.filter(x=>x!==a):[...i,a])};return s.jsxs("div",{className:"animate-in",style:{display:"flex",flexDirection:"column",gap:"24px"},children:[s.jsxs("div",{children:[s.jsxs("div",{style:{fontFamily:"var(--font-display)",fontSize:"22px",fontWeight:700,display:"flex",alignItems:"center",gap:"10px"},children:[s.jsx(H,{size:22,style:{color:"var(--cyan)"}}),"Advanced Search"]}),s.jsx("div",{style:{fontSize:"13px",color:"var(--text-muted)",marginTop:"4px"},children:"Global search across transactions, operations, contracts, and accounts"})]}),s.jsxs("div",{style:{background:"var(--bg-card)",border:"1px solid var(--border)",borderRadius:"var(--radius-lg)",padding:"20px"},children:[s.jsxs("div",{style:{position:"relative",marginBottom:"16px"},children:[s.jsx(H,{size:16,style:{position:"absolute",left:"12px",top:"50%",transform:"translateY(-50%)",color:"var(--text-muted)"}}),s.jsx("input",{type:"text",value:o,onChange:a=>e(a.target.value),onKeyPress:a=>a.key==="Enter"&&k(),placeholder:"Search transactions, operations, contracts, accounts...",style:{...g,paddingLeft:"40px",paddingRight:"120px",fontSize:"14px"}}),s.jsxs("div",{style:{position:"absolute",right:"8px",top:"50%",transform:"translateY(-50%)",display:"flex",gap:"4px"},children:[s.jsx("button",{onClick:()=>v(!p),style:{...C,title:"Search History"},children:s.jsx(be,{size:14})}),s.jsx("button",{onClick:fe,style:{...C,title:"Save Search"},children:s.jsx(Ce,{size:14})}),s.jsx("button",{onClick:k,disabled:n,style:{...C,background:"var(--cyan)",color:"white",title:"Search"},children:n?s.jsx(V,{size:14,className:"animate-spin"}):s.jsx(H,{size:14})})]}),ue&&N.length>0&&s.jsx("div",{style:{position:"absolute",top:"100%",left:0,right:0,background:"var(--bg-elevated)",border:"1px solid var(--border)",borderTop:"none",borderRadius:"0 0 var(--radius-md) var(--radius-md)",maxHeight:"200px",overflowY:"auto",zIndex:10},children:N.map((a,i)=>s.jsx("div",{onClick:()=>Se(a),style:{padding:"8px 12px",cursor:"pointer",fontSize:"13px",color:"var(--text-primary)",borderBottom:"1px solid var(--border)"},onMouseEnter:x=>x.target.style.background="var(--bg-card)",onMouseLeave:x=>x.target.style.background="transparent",children:a},i))})]}),s.jsxs("div",{style:{marginBottom:"16px"},children:[s.jsx("div",{style:{fontSize:"12px",color:"var(--text-muted)",marginBottom:"8px"},children:"Search in:"}),s.jsx("div",{style:{display:"flex",gap:"8px",flexWrap:"wrap"},children:["transactions","operations","contracts","accounts"].map(a=>s.jsx("button",{onClick:()=>je(a),style:{...Ne,background:R.includes(a)?"var(--cyan)":"var(--bg-elevated)",color:R.includes(a)?"white":"var(--text-primary)"},children:a},a))})]}),s.jsxs("div",{style:{display:"grid",gridTemplateColumns:"repeat(auto-fit, minmax(180px, 1fr))",gap:"10px",marginBottom:"16px"},children:[s.jsxs("label",{style:{display:"flex",flexDirection:"column",gap:"6px",fontSize:"12px",color:"var(--text-muted)"},children:[s.jsxs("span",{style:{display:"inline-flex",alignItems:"center",gap:"5px"},children:[s.jsx(Te,{size:12})," Save folder"]}),s.jsx("input",{value:F,onChange:a=>$(a.target.value),style:{...g,fontSize:"12px"}})]}),s.jsxs("label",{style:{display:"flex",flexDirection:"column",gap:"6px",fontSize:"12px",color:"var(--text-muted)"},children:[s.jsxs("span",{style:{display:"inline-flex",alignItems:"center",gap:"5px"},children:[s.jsx(we,{size:12})," Alert schedule"]}),s.jsx("input",{value:U,onChange:a=>pe(a.target.value),disabled:!z,style:{...g,fontSize:"12px",opacity:z?1:.55}})]}),s.jsxs("label",{style:{display:"flex",alignItems:"center",gap:"8px",fontSize:"12px",color:"var(--text-secondary)",alignSelf:"end",minHeight:"34px"},children:[s.jsx("input",{type:"checkbox",checked:z,onChange:a=>he(a.target.checked)}),"Create alert when saved"]})]}),s.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center"},children:[s.jsxs("button",{onClick:()=>u(!d),style:{display:"inline-flex",alignItems:"center",gap:"6px",padding:"8px 12px",background:"var(--bg-elevated)",border:"1px solid var(--border)",borderRadius:"var(--radius-md)",color:"var(--text-primary)",fontSize:"12px",cursor:"pointer"},children:[s.jsx(Re,{size:14}),d?"Hide Filters":"Show Filters",d?s.jsx(te,{size:14}):s.jsx(se,{size:14})]}),X()&&s.jsxs("button",{onClick:Y,style:{display:"inline-flex",alignItems:"center",gap:"6px",padding:"8px 12px",background:"rgba(239, 68, 68, 0.1)",border:"1px solid var(--red)",borderRadius:"var(--radius-md)",color:"var(--red)",fontSize:"12px",cursor:"pointer"},children:[s.jsx(Z,{size:14}),"Clear Filters"]})]}),d&&s.jsx("div",{style:{marginTop:"16px",padding:"16px",background:"var(--bg-elevated)",borderRadius:"var(--radius-md)",border:"1px solid var(--border)"},children:s.jsxs("div",{style:{display:"grid",gridTemplateColumns:"repeat(auto-fit, minmax(200px, 1fr))",gap:"16px"},children:[s.jsxs("div",{children:[s.jsxs("label",{style:j,children:[s.jsx(Ae,{size:12,style:{marginRight:"4px"}}),"Date Range"]}),s.jsxs("div",{style:{display:"flex",gap:"8px"},children:[s.jsx("input",{type:"date",value:c.dateRange.start,onChange:a=>f(i=>({...i,dateRange:{...i.dateRange,start:a.target.value}})),style:{...g,fontSize:"12px"}}),s.jsx("input",{type:"date",value:c.dateRange.end,onChange:a=>f(i=>({...i,dateRange:{...i.dateRange,end:a.target.value}})),style:{...g,fontSize:"12px"}})]})]}),s.jsxs("div",{children:[s.jsxs("label",{style:j,children:[s.jsx(Fe,{size:12,style:{marginRight:"4px"}}),"Asset Type"]}),s.jsxs("select",{value:c.assetType,onChange:a=>f(i=>({...i,assetType:a.target.value})),style:{...g,fontSize:"12px"},children:[s.jsx("option",{value:"",children:"All Assets"}),s.jsx("option",{value:"XLM",children:"XLM"}),s.jsx("option",{value:"USDC",children:"USDC"}),s.jsx("option",{value:"BTC",children:"BTC"}),s.jsx("option",{value:"ETH",children:"ETH"}),s.jsx("option",{value:"USDT",children:"USDT"})]})]}),s.jsxs("div",{children:[s.jsxs("label",{style:j,children:[s.jsx(re,{size:12,style:{marginRight:"4px"}}),"Operation Type"]}),s.jsxs("select",{value:c.operationType,onChange:a=>f(i=>({...i,operationType:a.target.value})),style:{...g,fontSize:"12px"},children:[s.jsx("option",{value:"",children:"All Operations"}),s.jsx("option",{value:"payment",children:"Payment"}),s.jsx("option",{value:"create_account",children:"Create Account"}),s.jsx("option",{value:"manage_offer",children:"Manage Offer"}),s.jsx("option",{value:"set_options",children:"Set Options"}),s.jsx("option",{value:"change_trust",children:"Change Trust"})]})]}),s.jsxs("div",{children:[s.jsxs("label",{style:j,children:[s.jsx(ze,{size:12,style:{marginRight:"4px"}}),"Amount Range"]}),s.jsxs("div",{style:{display:"flex",gap:"8px"},children:[s.jsx("input",{type:"number",placeholder:"Min",value:c.amountRange.min,onChange:a=>f(i=>({...i,amountRange:{...i.amountRange,min:a.target.value}})),style:{...g,fontSize:"12px"}}),s.jsx("input",{type:"number",placeholder:"Max",value:c.amountRange.max,onChange:a=>f(i=>({...i,amountRange:{...i.amountRange,max:a.target.value}})),style:{...g,fontSize:"12px"}})]})]}),s.jsxs("div",{children:[s.jsxs("label",{style:j,children:[s.jsx(ae,{size:12,style:{marginRight:"4px"}}),"Address Filter"]}),s.jsx("input",{type:"text",placeholder:"Account address...",value:c.addressFilter,onChange:a=>f(i=>({...i,addressFilter:a.target.value})),style:{...g,fontSize:"12px"}})]}),s.jsxs("div",{children:[s.jsxs("label",{style:j,children:[s.jsx(ne,{size:12,style:{marginRight:"4px"}}),"Memo Filter"]}),s.jsx("input",{type:"text",placeholder:"Memo text...",value:c.memoFilter,onChange:a=>f(i=>({...i,memoFilter:a.target.value})),style:{...g,fontSize:"12px"}})]}),s.jsxs("div",{children:[s.jsxs("label",{style:j,children:[s.jsx(ke,{size:12,style:{marginRight:"4px"}}),"Status"]}),s.jsxs("select",{value:c.statusFilter,onChange:a=>f(i=>({...i,statusFilter:a.target.value})),style:{...g,fontSize:"12px"},children:[s.jsx("option",{value:"",children:"All Status"}),s.jsx("option",{value:"success",children:"Success"}),s.jsx("option",{value:"failed",children:"Failed"}),s.jsx("option",{value:"pending",children:"Pending"})]})]}),s.jsxs("div",{children:[s.jsxs("label",{style:j,children:[s.jsx(ie,{size:12,style:{marginRight:"4px"}}),"Network"]}),s.jsxs("select",{value:c.networkFilter,onChange:a=>f(i=>({...i,networkFilter:a.target.value})),style:{...g,fontSize:"12px"},children:[s.jsx("option",{value:"",children:"All Networks"}),s.jsx("option",{value:"mainnet",children:"Mainnet"}),s.jsx("option",{value:"testnet",children:"Testnet"}),s.jsx("option",{value:"futurenet",children:"Futurenet"})]})]})]})})]}),p&&s.jsxs("div",{style:{background:"var(--bg-card)",border:"1px solid var(--border)",borderRadius:"var(--radius-lg)",padding:"16px"},children:[s.jsxs("div",{style:{fontSize:"14px",fontWeight:600,marginBottom:"12px",display:"flex",justifyContent:"space-between",alignItems:"center"},children:[s.jsx("span",{children:"Search History & Saved Searches"}),s.jsx("button",{onClick:()=>v(!1),style:C,children:s.jsx(Z,{size:14})})]}),w&&s.jsxs("div",{style:{display:"flex",gap:"8px",flexWrap:"wrap",marginBottom:"12px"},children:[s.jsx(AnalyticsChip,{label:"Searches",value:w.totalSearches}),s.jsx(AnalyticsChip,{label:"Cache hits",value:w.cachedSearches}),s.jsx(AnalyticsChip,{label:"Saved",value:w.savedSearches}),s.jsx(AnalyticsChip,{label:"Alerts",value:w.alerts})]}),s.jsxs("div",{style:{display:"grid",gridTemplateColumns:"repeat(auto-fit, minmax(300px, 1fr))",gap:"16px"},children:[s.jsxs("div",{children:[s.jsx("div",{style:{fontSize:"12px",color:"var(--text-muted)",marginBottom:"8px"},children:"Folders"}),s.jsx("div",{style:{display:"flex",flexDirection:"column",gap:"8px"},children:L.map(a=>s.jsxs("button",{onClick:()=>{$(a.name),b(m.getSavedSearches({folder:a.name}))},style:{padding:"8px 12px",background:F===a.name?"var(--cyan-glow)":"var(--bg-elevated)",border:`1px solid ${F===a.name?"var(--cyan-dim)":"var(--border)"}`,borderRadius:"var(--radius-md)",cursor:"pointer",fontSize:"12px",color:"var(--text-primary)",display:"flex",justifyContent:"space-between"},children:[s.jsx("span",{children:a.name}),s.jsx("span",{style:{color:"var(--text-muted)"},children:a.count})]},a.id))})]}),s.jsxs("div",{children:[s.jsx("div",{style:{fontSize:"12px",color:"var(--text-muted)",marginBottom:"8px"},children:"Recent Searches"}),s.jsx("div",{style:{display:"flex",flexDirection:"column",gap:"8px"},children:de.slice(0,5).map((a,i)=>s.jsxs("div",{onClick:()=>{e(a.query.text||""),v(!1)},style:{padding:"8px 12px",background:"var(--bg-elevated)",border:"1px solid var(--border)",borderRadius:"var(--radius-md)",cursor:"pointer",fontSize:"12px"},children:[s.jsx("div",{style:{fontWeight:500},children:a.query.text||"Empty search"}),s.jsxs("div",{style:{color:"var(--text-muted)",fontSize:"11px"},children:[Oe(new Date(a.timestamp),"MMM dd, HH:mm")," / ",a.resultCount||0," results / ",a.cached?"cached":`${a.searchTime||0}ms`]})]},i))})]}),s.jsxs("div",{children:[s.jsx("div",{style:{fontSize:"12px",color:"var(--text-muted)",marginBottom:"8px"},children:"Saved Searches"}),s.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:"8px"},children:[T.slice(0,5).map((a,i)=>s.jsxs("div",{onClick:()=>ye(a),style:{padding:"8px 12px",background:"var(--bg-elevated)",border:"1px solid var(--border)",borderRadius:"var(--radius-md)",cursor:"pointer",fontSize:"12px"},children:[s.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",gap:"8px"},children:[s.jsx("div",{style:{fontWeight:500},children:a.name}),s.jsx("button",{onClick:x=>me(x,a),style:{...C,width:"26px",height:"26px"},title:"Share query",children:s.jsx(Ie,{size:12})})]}),s.jsxs("div",{style:{color:"var(--text-muted)",fontSize:"11px"},children:[a.folder||"General"," / ",a.query.text||"No query"," / used ",a.usageCount||0,"x"]})]},i)),Q&&s.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"8px",padding:"8px 12px",background:"var(--bg-elevated)",border:"1px solid var(--border)",borderRadius:"var(--radius-md)",fontSize:"11px",color:"var(--text-muted)"},children:[s.jsx(_e,{size:12}),s.jsx("span",{style:{overflowWrap:"anywhere"},children:Q})]})]})]})]})]}),t&&s.jsxs("div",{style:{background:"var(--bg-card)",border:"1px solid var(--border)",borderRadius:"var(--radius-lg)",overflow:"hidden"},children:[s.jsxs("div",{style:{padding:"16px 20px",borderBottom:"1px solid var(--border)",display:"flex",justifyContent:"space-between",alignItems:"center"},children:[s.jsxs("div",{children:[s.jsxs("div",{style:{fontSize:"14px",fontWeight:600},children:[t.total," results found"]}),s.jsxs("div",{style:{fontSize:"12px",color:"var(--text-muted)"},children:["Search completed in ",t.searchTime,"ms",t.cached?" from cache":""]}),t.queryPlan&&s.jsxs("div",{style:{fontSize:"11px",color:"var(--text-muted)",marginTop:"4px"},children:[t.queryPlan.usesIndex?"Index-assisted":"Scan"," / ",t.queryPlan.filterCount," filters / cache TTL ",Math.round(t.queryPlan.cacheTtlMs/1e3),"s"]})]}),s.jsxs("div",{style:{display:"flex",gap:"8px"},children:[s.jsx("button",{onClick:ve,style:C,title:"Export Results",children:s.jsx(De,{size:14})}),s.jsx("button",{onClick:k,style:C,title:"Refresh",children:s.jsx(V,{size:14})})]})]}),t.results.length===0?s.jsx("div",{style:{padding:"48px",textAlign:"center",color:"var(--text-muted)"},children:"No results found for your search criteria."}):s.jsxs("div",{children:[t.aggregations&&s.jsxs("div",{style:{padding:"16px 20px",borderBottom:"1px solid var(--border)"},children:[s.jsx("div",{style:{fontSize:"12px",color:"var(--text-muted)",marginBottom:"8px"},children:"Results Overview"}),s.jsxs("div",{style:{display:"flex",gap:"16px",flexWrap:"wrap"},children:[s.jsx(O,{label:"Types",data:t.aggregations.typeCounts}),s.jsx(O,{label:"Operations",data:t.aggregations.operationTypeCounts}),s.jsx(O,{label:"Assets",data:t.aggregations.assetCounts}),s.jsx(O,{label:"Status",data:t.aggregations.statusCounts})]})]}),s.jsx("div",{children:t.results.map((a,i)=>s.jsx(Be,{result:a},a.id))}),t.totalPages>1&&s.jsxs("div",{style:{padding:"16px 20px",borderTop:"1px solid var(--border)",display:"flex",justifyContent:"center",alignItems:"center",gap:"8px"},children:[s.jsx("button",{onClick:()=>J(a=>({...a,page:Math.max(1,a.page-1)})),disabled:t.page===1,style:ee,children:"Previous"}),s.jsxs("span",{style:{fontSize:"12px",color:"var(--text-muted)"},children:["Page ",t.page," of ",t.totalPages]}),s.jsx("button",{onClick:()=>J(a=>({...a,page:Math.min(t.totalPages,a.page+1)})),disabled:t.page===t.totalPages,style:ee,children:"Next"})]})]})]})]})}function Be({result:o}){const[e,t]=h.useState(!1),r=l=>({transactions:s.jsx(ae,{size:14}),operations:s.jsx(re,{size:14}),contracts:s.jsx(ne,{size:14}),accounts:s.jsx(ie,{size:14})})[l]||s.jsx(H,{size:14}),n=l=>({transactions:"var(--blue)",operations:"var(--green)",contracts:"var(--purple)",accounts:"var(--orange)"})[l]||"var(--text-secondary)";return s.jsxs("div",{style:{borderBottom:"1px solid var(--border)"},children:[s.jsx("div",{style:{padding:"16px 20px",cursor:"pointer",transition:"var(--transition)"},onClick:()=>t(!e),children:s.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"flex-start"},children:[s.jsxs("div",{style:{display:"flex",alignItems:"flex-start",gap:"12px",flex:1},children:[s.jsx("div",{style:{color:n(o.type),marginTop:"2px"},children:r(o.type)}),s.jsxs("div",{style:{flex:1},children:[s.jsxs("div",{style:{fontSize:"14px",fontWeight:600,color:"var(--text-primary)",marginBottom:"4px"},children:[o.type.charAt(0).toUpperCase()+o.type.slice(1),o.operationType&&` • ${o.operationType}`]}),s.jsxs("div",{style:{fontSize:"12px",color:"var(--text-muted)",marginBottom:"8px"},children:[o.address&&s.jsxs("span",{children:["Address: ",o.address.substring(0,16),"... "]}),o.asset&&s.jsxs("span",{children:["Asset: ",o.asset," "]}),o.amount&&s.jsxs("span",{children:["Amount: ",o.amount," "]}),o.status&&s.jsxs("span",{children:["Status: ",o.status]})]}),s.jsx("div",{style:{fontSize:"11px",color:"var(--text-muted)"},children:new Date(o.timestamp).toLocaleString()})]})]}),s.jsx("div",{style:{color:"var(--text-muted)"},children:e?s.jsx(te,{size:16}):s.jsx(se,{size:16})})]})}),e&&s.jsx("div",{style:{padding:"0 20px 16px",background:"var(--bg-elevated)"},children:s.jsx("pre",{style:{margin:0,fontSize:"11px",color:"var(--text-secondary)",whiteSpace:"pre-wrap",wordBreak:"break-all",maxHeight:"300px",overflowY:"auto"},children:JSON.stringify(o.data,null,2)})})]})}function O({label:o,data:e}){const t=Object.entries(e).slice(0,3);return s.jsxs("div",{style:{padding:"4px 8px",background:"var(--bg-elevated)",border:"1px solid var(--border)",borderRadius:"999px",fontSize:"11px"},children:[s.jsxs("span",{style:{color:"var(--text-muted)"},children:[o,":"]}),t.map(([r,n],l)=>s.jsxs("span",{style:{marginLeft:"4px"},children:[r," (",n,")",l3&&"..."]})}const g={width:"100%",padding:"8px 12px",background:"var(--bg-elevated)",border:"1px solid var(--border)",borderRadius:"var(--radius-md)",color:"var(--text-primary)",fontSize:"13px",fontFamily:"var(--font-mono)",outline:"none"},j={fontSize:"12px",color:"var(--text-muted)",textTransform:"uppercase",letterSpacing:"0.5px",display:"flex",alignItems:"center",marginBottom:"6px"},Ne={padding:"4px 12px",background:"var(--bg-elevated)",border:"1px solid var(--border)",borderRadius:"999px",fontSize:"12px",cursor:"pointer",transition:"var(--transition)"},C={display:"flex",alignItems:"center",justifyContent:"center",width:"32px",height:"32px",background:"var(--bg-elevated)",border:"1px solid var(--border)",borderRadius:"var(--radius-md)",color:"var(--text-primary)",cursor:"pointer",transition:"var(--transition)"},ee={padding:"6px 12px",background:"var(--bg-elevated)",border:"1px solid var(--border)",borderRadius:"var(--radius-md)",color:"var(--text-primary)",fontSize:"12px",cursor:"pointer",transition:"var(--transition)"};export{Ke as default}; -//# sourceMappingURL=AdvancedSearch-DvI37z7f.js.map diff --git a/dist/assets/AdvancedSearch-DvI37z7f.js.map b/dist/assets/AdvancedSearch-DvI37z7f.js.map deleted file mode 100644 index 94352e74..00000000 --- a/dist/assets/AdvancedSearch-DvI37z7f.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"AdvancedSearch-DvI37z7f.js","sources":["../../src/lib/advancedSearch.js","../../src/components/dashboard/AdvancedSearch.tsx"],"sourcesContent":["/**\n * Advanced Search and Filtering System\n * Global search functionality across transactions, operations, and contracts\n */\n\nconst STORAGE_KEYS = {\n history: 'stellar-advanced-search-history-v1',\n saved: 'stellar-advanced-search-saved-v1',\n alerts: 'stellar-advanced-search-alerts-v1',\n folders: 'stellar-advanced-search-folders-v1',\n};\n\nfunction getBrowserStorage() {\n try {\n return typeof localStorage !== 'undefined' ? localStorage : null;\n } catch {\n return null;\n }\n}\n\nfunction readStoredArray(storage, key, fallback = []) {\n if (!storage) return [...fallback];\n try {\n const parsed = JSON.parse(storage.getItem(key) || 'null');\n return Array.isArray(parsed) ? parsed : [...fallback];\n } catch {\n return [...fallback];\n }\n}\n\nfunction writeStoredArray(storage, key, value) {\n if (!storage) return;\n try {\n storage.setItem(key, JSON.stringify(value));\n } catch {\n // Persistence is best-effort because private browsing can reject writes.\n }\n}\n\nfunction stableStringify(value) {\n if (Array.isArray(value)) {\n return `[${value.map(stableStringify).join(',')}]`;\n }\n if (value && typeof value === 'object') {\n return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${stableStringify(value[key])}`).join(',')}}`;\n }\n return JSON.stringify(value);\n}\n\nfunction makeId(prefix) {\n return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n}\n\nfunction encodeSharePayload(payload) {\n const serialized = encodeURIComponent(JSON.stringify(payload));\n if (typeof btoa === 'function') return btoa(serialized);\n return serialized;\n}\n\nfunction decodeSharePayload(token) {\n const serialized = typeof atob === 'function' ? atob(token) : token;\n return JSON.parse(decodeURIComponent(serialized));\n}\n\nclass AdvancedSearchService {\n constructor(options = {}) {\n this.storage = options.storage || getBrowserStorage();\n this.searchHistory = readStoredArray(this.storage, STORAGE_KEYS.history);\n this.savedSearches = readStoredArray(this.storage, STORAGE_KEYS.saved);\n this.searchAlerts = readStoredArray(this.storage, STORAGE_KEYS.alerts);\n this.savedQueryFolders = readStoredArray(this.storage, STORAGE_KEYS.folders, [{ id: 'general', name: 'General', createdAt: new Date().toISOString() }]);\n this.resultCache = new Map();\n this.cacheTtlMs = options.cacheTtlMs || 60 * 1000;\n this.indexedData = new Map();\n this.searchIndex = new Map();\n this.filters = {\n dateRange: { start: null, end: null },\n assetType: null,\n operationType: null,\n amountRange: { min: null, max: null },\n addressFilter: null,\n memoFilter: null,\n statusFilter: null,\n networkFilter: null\n };\n this.sortOptions = {\n field: 'timestamp',\n direction: 'desc'\n };\n }\n\n /**\n * Index data for fast searching\n * @param {string} type - Data type (transactions, operations, contracts, accounts)\n * @param {array} data - Array of data objects\n */\n indexData(type, data) {\n if (!Array.isArray(data)) return;\n\n const indexed = data.map(item => this.createSearchableItem(type, item));\n this.indexedData.set(type, indexed);\n \n // Build search index\n indexed.forEach(item => {\n const terms = this.extractSearchTerms(item);\n terms.forEach(term => {\n if (!this.searchIndex.has(term)) {\n this.searchIndex.set(term, new Set());\n }\n this.searchIndex.get(term).add(item.id);\n });\n });\n }\n\n /**\n * Create searchable item from raw data\n * @param {string} type - Data type\n * @param {object} item - Raw data item\n * @returns {object} Searchable item\n */\n createSearchableItem(type, item) {\n const baseItem = {\n id: `${type}_${item.id || item.hash || item.address}`,\n type,\n data: item,\n timestamp: this.extractTimestamp(item),\n amount: this.extractAmount(item),\n asset: this.extractAsset(item),\n operationType: this.extractOperationType(item),\n address: this.extractAddress(item),\n memo: this.extractMemo(item),\n status: this.extractStatus(item),\n network: item.network || 'unknown'\n };\n\n // Add type-specific fields\n switch (type) {\n case 'transactions':\n baseItem.transactionHash = item.hash;\n baseItem.fee = item.fee;\n baseItem.operationCount = item.operation_count;\n break;\n case 'operations':\n baseItem.operationId = item.id;\n baseItem.transactionHash = item.transaction_hash;\n baseItem.sourceAccount = item.source_account;\n break;\n case 'contracts':\n baseItem.contractId = item.contract_id || item.id;\n baseItem.contractType = item.type;\n break;\n case 'accounts':\n baseItem.accountId = item.account_id || item.address;\n baseItem.balance = item.balance;\n baseItem.sequence = item.sequence;\n break;\n }\n\n return baseItem;\n }\n\n /**\n * Extract search terms from item\n * @param {object} item - Searchable item\n * @returns {array} Array of search terms\n */\n extractSearchTerms(item) {\n const terms = new Set();\n\n // Add basic fields\n terms.add(item.type.toLowerCase());\n terms.add(item.operationType?.toLowerCase() || '');\n terms.add(item.asset?.toLowerCase() || '');\n terms.add(item.status?.toLowerCase() || '');\n terms.add(item.network?.toLowerCase() || '');\n\n // Add addresses and hashes\n if (item.address) terms.add(item.address.toLowerCase());\n if (item.transactionHash) terms.add(item.transactionHash.toLowerCase());\n if (item.contractId) terms.add(item.contractId.toLowerCase());\n if (item.accountId) terms.add(item.accountId.toLowerCase());\n\n // Add memo text\n if (item.memo) {\n terms.add(item.memo.toLowerCase());\n // Split memo into words\n item.memo.toLowerCase().split(/\\s+/).forEach(word => {\n if (word.length > 2) terms.add(word);\n });\n }\n\n // Add amount variations\n if (item.amount) {\n terms.add(item.amount.toString());\n terms.add(parseFloat(item.amount).toFixed(2));\n }\n\n // Add data-specific terms\n this.extractDataSpecificTerms(item.data, terms);\n\n return Array.from(terms).filter(term => term.length > 0);\n }\n\n /**\n * Extract data-specific search terms\n * @param {object} data - Raw data object\n * @param {Set} terms - Terms set to add to\n */\n extractDataSpecificTerms(data, terms) {\n // Recursively extract string values from nested objects\n const extractStrings = (obj, prefix = '') => {\n Object.entries(obj).forEach(([key, value]) => {\n const fullKey = prefix ? `${prefix}.${key}` : key;\n \n if (typeof value === 'string' && value.length > 0) {\n terms.add(value.toLowerCase());\n // Split into words\n value.toLowerCase().split(/\\s+/).forEach(word => {\n if (word.length > 2) terms.add(word);\n });\n } else if (typeof value === 'number') {\n terms.add(value.toString());\n } else if (typeof value === 'object' && value !== null) {\n extractStrings(value, fullKey);\n }\n });\n };\n\n extractStrings(data);\n }\n\n /**\n * Extract timestamp from item\n * @param {object} item - Raw data item\n * @returns {number} Timestamp\n */\n extractTimestamp(item) {\n if (item.created_at) return new Date(item.created_at).getTime();\n if (item.timestamp) return new Date(item.timestamp).getTime();\n if (item.time) return new Date(item.time).getTime();\n return Date.now();\n }\n\n /**\n * Extract amount from item\n * @param {object} item - Raw data item\n * @returns {number|null} Amount\n */\n extractAmount(item) {\n if (item.amount) return parseFloat(item.amount);\n if (item.starting_balance) return parseFloat(item.starting_balance);\n if (item.amount_in) return parseFloat(item.amount_in);\n if (item.amount_out) return parseFloat(item.amount_out);\n return null;\n }\n\n /**\n * Extract asset from item\n * @param {object} item - Raw data item\n * @returns {string|null} Asset code\n */\n extractAsset(item) {\n if (item.asset_code) return item.asset_code;\n if (item.asset_type === 'native') return 'XLM';\n if (item.asset_code && item.asset_issuer) return `${item.asset_code}:${item.asset_issuer}`;\n return null;\n }\n\n /**\n * Extract operation type from item\n * @param {object} item - Raw data item\n * @returns {string|null} Operation type\n */\n extractOperationType(item) {\n if (item.type) return item.type;\n if (item.operation_type) return this.getOperationTypeName(item.operation_type);\n return null;\n }\n\n /**\n * Get operation type name from code\n * @param {number} code - Operation type code\n * @returns {string} Operation type name\n */\n getOperationTypeName(code) {\n const types = {\n 0: 'payment',\n 1: 'create_account',\n 2: 'manage_offer',\n 3: 'set_options',\n 4: 'change_trust',\n 5: 'allow_trust',\n 6: 'account_merge',\n 7: 'inflation',\n 8: 'manage_data',\n 9: 'bump_sequence',\n 10: 'create_claimable_balance',\n 11: 'claim_claimable_balance',\n 12: 'begin_sponsoring_future_reserves',\n 13: 'end_sponsoring_future_reserves',\n 14: 'revoke_sponsorship'\n };\n return types[code] || 'unknown';\n }\n\n /**\n * Extract address from item\n * @param {object} item - Raw data item\n * @returns {string|null} Address\n */\n extractAddress(item) {\n if (item.account_id) return item.account_id;\n if (item.source_account) return item.source_account;\n if (item.destination_account) return item.destination_account;\n if (item.address) return item.address;\n return null;\n }\n\n /**\n * Extract memo from item\n * @param {object} item - Raw data item\n * @returns {string|null} Memo text\n */\n extractMemo(item) {\n if (item.memo) return item.memo;\n if (item.memo_type && item.memo_value) {\n if (item.memo_type === 'text') return item.memo_value;\n if (item.memo_type === 'id') return item.memo_value.toString();\n }\n return null;\n }\n\n /**\n * Extract status from item\n * @param {object} item - Raw data item\n * @returns {string|null} Status\n */\n extractStatus(item) {\n if (item.status) return item.status;\n if (item.successful !== undefined) return item.successful ? 'success' : 'failed';\n if (item.result_successful !== undefined) return item.result_successful ? 'success' : 'failed';\n return null;\n }\n\n /**\n * Perform global search\n * @param {object} query - Search query object\n * @returns {object} Search results\n */\n search(query) {\n const startTime = Date.now();\n \n try {\n const optimizedQuery = this.optimizeQuery(query);\n\n // Update filters if provided\n if (optimizedQuery.filters) {\n this.filters = { ...this.filters, ...optimizedQuery.filters };\n }\n\n // Update sort options if provided\n if (optimizedQuery.sort) {\n this.sortOptions = { ...this.sortOptions, ...optimizedQuery.sort };\n }\n\n const queryPlan = this.buildQueryPlan(optimizedQuery);\n const cacheKey = this.createQueryKey({ ...optimizedQuery, filters: this.filters, sort: this.sortOptions });\n const cached = optimizedQuery.cache !== false ? this.getCachedResults(cacheKey) : null;\n if (cached) {\n const cachedResult = {\n ...cached,\n query: optimizedQuery,\n cached: true,\n searchTime: Date.now() - startTime,\n queryPlan,\n };\n this.addToSearchHistory(optimizedQuery, {\n resultCount: cached.total,\n searchTime: cachedResult.searchTime,\n cached: true,\n });\n return cachedResult;\n }\n\n // Get all indexed data\n let results = [];\n this.indexedData.forEach((items, type) => {\n if (!optimizedQuery.types || optimizedQuery.types.includes(type)) {\n results.push(...items);\n }\n });\n\n // Apply text search\n if (optimizedQuery.text && optimizedQuery.text.trim()) {\n results = this.applyTextSearch(results, optimizedQuery.text.trim());\n }\n\n // Apply filters\n results = this.applyFilters(results);\n\n // Apply sorting\n results = this.applySorting(results);\n\n // Apply pagination\n const paginatedResults = this.applyPagination(results, optimizedQuery.page, optimizedQuery.limit);\n\n const searchTime = Date.now() - startTime;\n\n const response = {\n query: optimizedQuery,\n results: paginatedResults.items,\n total: paginatedResults.total,\n page: paginatedResults.page,\n limit: paginatedResults.limit,\n searchTime,\n cached: false,\n cacheKey,\n queryPlan,\n filters: { ...this.filters },\n sort: { ...this.sortOptions },\n aggregations: this.calculateAggregations(results)\n };\n\n this.setCachedResults(cacheKey, response);\n this.addToSearchHistory(optimizedQuery, {\n resultCount: response.total,\n searchTime,\n cached: false,\n });\n\n return response;\n\n } catch (error) {\n throw new Error(`Search failed: ${error.message}`);\n }\n }\n\n /**\n * Apply text search to results\n * @param {array} results - Results array\n * @param {string} searchText - Search text\n * @returns {array} Filtered results\n */\n applyTextSearch(results, searchText) {\n const searchTerms = searchText.toLowerCase().split(/\\s+/).filter(term => term.length > 0);\n \n if (searchTerms.length === 0) return results;\n\n return results.filter(item => {\n return searchTerms.every(term => {\n // Check if any search term matches the item\n return this.itemContainsTerm(item, term);\n });\n });\n }\n\n /**\n * Check if item contains search term\n * @param {object} item - Searchable item\n * @param {string} term - Search term\n * @returns {boolean} True if item contains term\n */\n itemContainsTerm(item, term) {\n // Check basic fields\n if (item.type?.toLowerCase().includes(term)) return true;\n if (item.operationType?.toLowerCase().includes(term)) return true;\n if (item.asset?.toLowerCase().includes(term)) return true;\n if (item.status?.toLowerCase().includes(term)) return true;\n if (item.address?.toLowerCase().includes(term)) return true;\n if (item.memo?.toLowerCase().includes(term)) return true;\n\n // Check hashes and IDs\n if (item.transactionHash?.toLowerCase().includes(term)) return true;\n if (item.contractId?.toLowerCase().includes(term)) return true;\n if (item.accountId?.toLowerCase().includes(term)) return true;\n\n // Check numeric values\n if (item.amount?.toString().includes(term)) return true;\n\n // Check search index for exact matches\n const indexedItems = this.searchIndex.get(term.toLowerCase());\n if (indexedItems && indexedItems.has(item.id)) return true;\n\n return false;\n }\n\n /**\n * Apply filters to results\n * @param {array} results - Results array\n * @returns {array} Filtered results\n */\n applyFilters(results) {\n return results.filter(item => {\n // Date range filter\n if (this.filters.dateRange.start && item.timestamp < this.filters.dateRange.start) {\n return false;\n }\n if (this.filters.dateRange.end && item.timestamp > this.filters.dateRange.end) {\n return false;\n }\n\n // Asset type filter\n if (this.filters.assetType && item.asset !== this.filters.assetType) {\n return false;\n }\n\n // Operation type filter\n if (this.filters.operationType && item.operationType !== this.filters.operationType) {\n return false;\n }\n\n // Amount range filter\n if (this.filters.amountRange.min !== null && (!item.amount || item.amount < this.filters.amountRange.min)) {\n return false;\n }\n if (this.filters.amountRange.max !== null && (!item.amount || item.amount > this.filters.amountRange.max)) {\n return false;\n }\n\n // Address filter\n if (this.filters.addressFilter && !item.address?.includes(this.filters.addressFilter)) {\n return false;\n }\n\n // Memo filter\n if (this.filters.memoFilter && !item.memo?.toLowerCase().includes(this.filters.memoFilter.toLowerCase())) {\n return false;\n }\n\n // Status filter\n if (this.filters.statusFilter && item.status !== this.filters.statusFilter) {\n return false;\n }\n\n // Network filter\n if (this.filters.networkFilter && item.network !== this.filters.networkFilter) {\n return false;\n }\n\n return true;\n });\n }\n\n /**\n * Apply sorting to results\n * @param {array} results - Results array\n * @returns {array} Sorted results\n */\n applySorting(results) {\n const { field, direction } = this.sortOptions;\n \n return results.sort((a, b) => {\n let aValue = a[field];\n let bValue = b[field];\n\n // Handle null/undefined values\n if (aValue === null || aValue === undefined) aValue = '';\n if (bValue === null || bValue === undefined) bValue = '';\n\n // Compare based on type\n let comparison = 0;\n if (typeof aValue === 'number' && typeof bValue === 'number') {\n comparison = aValue - bValue;\n } else {\n comparison = String(aValue).localeCompare(String(bValue));\n }\n\n return direction === 'asc' ? comparison : -comparison;\n });\n }\n\n /**\n * Apply pagination to results\n * @param {array} results - Results array\n * @param {number} page - Page number (1-based)\n * @param {number} limit - Page size\n * @returns {object} Paginated results\n */\n applyPagination(results, page = 1, limit = 20) {\n const startIndex = (page - 1) * limit;\n const endIndex = startIndex + limit;\n \n return {\n items: results.slice(startIndex, endIndex),\n total: results.length,\n page,\n limit,\n totalPages: Math.ceil(results.length / limit)\n };\n }\n\n /**\n * Calculate aggregations for results\n * @param {array} results - Results array\n * @returns {object} Aggregations\n */\n calculateAggregations(results) {\n const aggregations = {\n typeCounts: {},\n operationTypeCounts: {},\n assetCounts: {},\n statusCounts: {},\n totalAmount: 0,\n averageAmount: 0,\n dateRange: { earliest: null, latest: null }\n };\n\n results.forEach(item => {\n // Type counts\n aggregations.typeCounts[item.type] = (aggregations.typeCounts[item.type] || 0) + 1;\n\n // Operation type counts\n if (item.operationType) {\n aggregations.operationTypeCounts[item.operationType] = \n (aggregations.operationTypeCounts[item.operationType] || 0) + 1;\n }\n\n // Asset counts\n if (item.asset) {\n aggregations.assetCounts[item.asset] = (aggregations.assetCounts[item.asset] || 0) + 1;\n }\n\n // Status counts\n if (item.status) {\n aggregations.statusCounts[item.status] = (aggregations.statusCounts[item.status] || 0) + 1;\n }\n\n // Amount aggregations\n if (item.amount) {\n aggregations.totalAmount += item.amount;\n }\n\n // Date range\n if (item.timestamp) {\n if (!aggregations.dateRange.earliest || item.timestamp < aggregations.dateRange.earliest) {\n aggregations.dateRange.earliest = item.timestamp;\n }\n if (!aggregations.dateRange.latest || item.timestamp > aggregations.dateRange.latest) {\n aggregations.dateRange.latest = item.timestamp;\n }\n }\n });\n\n // Calculate average amount\n const amountCount = results.filter(item => item.amount !== null).length;\n aggregations.averageAmount = amountCount > 0 ? aggregations.totalAmount / amountCount : 0;\n\n return aggregations;\n }\n\n /**\n * Normalize query fields before execution.\n * @param {object} query - Search query\n * @returns {object} Optimized query\n */\n optimizeQuery(query = {}) {\n const text = (query.text || '').trim();\n const types = Array.isArray(query.types) && query.types.length\n ? Array.from(new Set(query.types)).sort()\n : null;\n\n return {\n ...query,\n text,\n types,\n page: Math.max(Number(query.page) || 1, 1),\n limit: Math.min(Math.max(Number(query.limit) || 20, 1), 100),\n };\n }\n\n /**\n * Build a stable cache key for the effective query.\n * @param {object} query - Search query\n * @returns {string} Cache key\n */\n createQueryKey(query) {\n return stableStringify({\n text: query.text || '',\n types: query.types || null,\n filters: query.filters || {},\n sort: query.sort || {},\n page: query.page || 1,\n limit: query.limit || 20,\n });\n }\n\n /**\n * Store a result in the in-memory cache.\n * @param {string} key - Cache key\n * @param {object} result - Search response\n */\n setCachedResults(key, result) {\n this.resultCache.set(key, {\n expiresAt: Date.now() + this.cacheTtlMs,\n result,\n });\n }\n\n /**\n * Read a result from the in-memory cache.\n * @param {string} key - Cache key\n * @returns {object|null} Cached response\n */\n getCachedResults(key) {\n const entry = this.resultCache.get(key);\n if (!entry) return null;\n if (entry.expiresAt <= Date.now()) {\n this.resultCache.delete(key);\n return null;\n }\n return entry.result;\n }\n\n clearResultCache() {\n this.resultCache.clear();\n }\n\n /**\n * Produce a lightweight plan for index/caching observability.\n * @param {object} query - Optimized query\n * @returns {object} Query plan summary\n */\n buildQueryPlan(query) {\n const terms = (query.text || '').toLowerCase().split(/\\s+/).filter(Boolean);\n const indexedTerms = terms.filter((term) => this.searchIndex.has(term));\n const filterCount = Object.values(query.filters || {}).filter((value) => {\n if (value && typeof value === 'object') {\n return Object.values(value).some((nested) => nested !== null && nested !== '');\n }\n return value !== null && value !== '';\n }).length;\n\n return {\n textTerms: terms,\n indexedTerms,\n filterCount,\n usesIndex: indexedTerms.length > 0,\n cacheTtlMs: this.cacheTtlMs,\n indexedTypes: query.types || Array.from(this.indexedData.keys()),\n };\n }\n\n /**\n * Add search to history\n * @param {object} query - Search query\n */\n addToSearchHistory(query, meta = {}) {\n const historyEntry = {\n id: makeId('history'),\n timestamp: new Date().toISOString(),\n query: { ...query },\n resultCount: meta.resultCount || 0,\n searchTime: meta.searchTime || 0,\n cached: Boolean(meta.cached)\n };\n\n this.searchHistory.unshift(historyEntry);\n \n // Keep only last 50 searches\n if (this.searchHistory.length > 50) {\n this.searchHistory = this.searchHistory.slice(0, 50);\n }\n\n writeStoredArray(this.storage, STORAGE_KEYS.history, this.searchHistory);\n }\n\n /**\n * Save search for later use\n * @param {string} name - Search name\n * @param {object} query - Search query\n */\n saveSearch(name, query, options = {}) {\n const folder = options.folder || 'General';\n this.createSavedSearchFolder(folder);\n const savedSearch = {\n id: makeId('saved'),\n name,\n query: { ...query },\n folder,\n tags: options.tags || [],\n description: options.description || '',\n sharedWith: [],\n shareToken: null,\n createdAt: new Date().toISOString(),\n updatedAt: new Date().toISOString(),\n usageCount: 0\n };\n\n this.savedSearches.push(savedSearch);\n writeStoredArray(this.storage, STORAGE_KEYS.saved, this.savedSearches);\n return savedSearch;\n }\n\n /**\n * Get saved searches\n * @returns {array} Saved searches\n */\n getSavedSearches(options = {}) {\n return [...this.savedSearches]\n .filter((search) => !options.folder || search.folder === options.folder)\n .sort((a, b) => b.usageCount - a.usageCount || new Date(b.updatedAt || b.createdAt).getTime() - new Date(a.updatedAt || a.createdAt).getTime());\n }\n\n loadSavedSearch(id) {\n const savedSearch = this.savedSearches.find((search) => search.id === id);\n if (!savedSearch) return null;\n savedSearch.usageCount += 1;\n savedSearch.updatedAt = new Date().toISOString();\n writeStoredArray(this.storage, STORAGE_KEYS.saved, this.savedSearches);\n return savedSearch;\n }\n\n deleteSavedSearch(id) {\n this.savedSearches = this.savedSearches.filter((search) => search.id !== id);\n writeStoredArray(this.storage, STORAGE_KEYS.saved, this.savedSearches);\n }\n\n createSavedSearchFolder(name) {\n const normalizedName = (name || 'General').trim() || 'General';\n const existing = this.savedQueryFolders.find((folder) => folder.name.toLowerCase() === normalizedName.toLowerCase());\n if (existing) return existing;\n\n const folder = {\n id: makeId('folder'),\n name: normalizedName,\n createdAt: new Date().toISOString(),\n };\n this.savedQueryFolders.push(folder);\n writeStoredArray(this.storage, STORAGE_KEYS.folders, this.savedQueryFolders);\n return folder;\n }\n\n getSavedSearchFolders() {\n return this.savedQueryFolders.map((folder) => ({\n ...folder,\n count: this.savedSearches.filter((search) => search.folder === folder.name).length,\n }));\n }\n\n shareSearch(id, options = {}) {\n const savedSearch = this.savedSearches.find((search) => search.id === id);\n if (!savedSearch) {\n throw new Error('Saved search not found');\n }\n\n savedSearch.sharedWith = Array.from(new Set([...(savedSearch.sharedWith || []), ...(options.users || [])]));\n savedSearch.shareToken = savedSearch.shareToken || encodeSharePayload({\n id: savedSearch.id,\n name: savedSearch.name,\n query: savedSearch.query,\n folder: savedSearch.folder,\n });\n savedSearch.updatedAt = new Date().toISOString();\n writeStoredArray(this.storage, STORAGE_KEYS.saved, this.savedSearches);\n return savedSearch.shareToken;\n }\n\n importSharedSearch(shareToken, options = {}) {\n const parsed = decodeSharePayload(shareToken);\n return this.saveSearch(options.name || parsed.name, parsed.query, {\n folder: options.folder || parsed.folder || 'Shared',\n tags: ['shared'],\n });\n }\n\n createSearchAlert(input) {\n const alert = {\n id: makeId('alert'),\n savedSearchId: input.savedSearchId || null,\n name: input.name || 'Search alert',\n query: input.query || this.savedSearches.find((search) => search.id === input.savedSearchId)?.query || {},\n cron: input.cron || '0 * * * *',\n channels: input.channels || ['in-app'],\n threshold: Number(input.threshold || 1),\n enabled: input.enabled !== false,\n lastRunAt: null,\n nextRunAt: this.getNextAlertRun(input.cron || '0 * * * *'),\n createdAt: new Date().toISOString(),\n };\n\n this.searchAlerts.push(alert);\n writeStoredArray(this.storage, STORAGE_KEYS.alerts, this.searchAlerts);\n return alert;\n }\n\n getSearchAlerts() {\n return [...this.searchAlerts].sort((a, b) => new Date(a.nextRunAt).getTime() - new Date(b.nextRunAt).getTime());\n }\n\n getNextAlertRun(cronExpression, from = new Date()) {\n const [minute = '0', hour = '*'] = cronExpression.trim().split(/\\s+/);\n const next = new Date(from);\n next.setSeconds(0, 0);\n next.setMinutes(next.getMinutes() + 1);\n if (minute !== '*') next.setMinutes(Number(minute.replace('*/', '')) || 0);\n if (hour !== '*') next.setHours(Number(hour.replace('*/', '')) || next.getHours());\n if (next.getTime() <= from.getTime()) next.setHours(next.getHours() + 1);\n return next.toISOString();\n }\n\n evaluateSearchAlerts(now = new Date()) {\n return this.searchAlerts\n .filter((alert) => alert.enabled && new Date(alert.nextRunAt).getTime() <= now.getTime())\n .map((alert) => {\n const result = this.search({ ...alert.query, cache: false });\n alert.lastRunAt = now.toISOString();\n alert.nextRunAt = this.getNextAlertRun(alert.cron, now);\n writeStoredArray(this.storage, STORAGE_KEYS.alerts, this.searchAlerts);\n return {\n alert,\n resultCount: result.total,\n triggered: result.total >= alert.threshold,\n };\n });\n }\n\n getSearchHistory() {\n return [...this.searchHistory];\n }\n\n getFrequentSearches(limit = 5) {\n const counts = new Map();\n this.searchHistory.forEach((entry) => {\n const key = entry.query?.text || JSON.stringify(entry.query?.filters || {});\n counts.set(key, (counts.get(key) || 0) + 1);\n });\n return Array.from(counts.entries())\n .map(([query, count]) => ({ query, count }))\n .sort((a, b) => b.count - a.count)\n .slice(0, limit);\n }\n\n getSearchAnalytics() {\n const history = this.getSearchHistory();\n const totalSearchTime = history.reduce((sum, entry) => sum + (entry.searchTime || 0), 0);\n return {\n totalSearches: history.length,\n cachedSearches: history.filter((entry) => entry.cached).length,\n averageSearchTime: history.length ? totalSearchTime / history.length : 0,\n savedSearches: this.savedSearches.length,\n folders: this.savedQueryFolders.length,\n alerts: this.searchAlerts.length,\n frequentSearches: this.getFrequentSearches(),\n cacheEntries: this.resultCache.size,\n };\n }\n\n /**\n * Get search suggestions\n * @param {string} partial - Partial search term\n * @returns {array} Suggestions\n */\n getSuggestions(partial) {\n if (!partial || partial.length < 2) return [];\n\n const suggestions = new Set();\n const lowerPartial = partial.toLowerCase();\n\n // Find matching terms from search index\n this.searchIndex.forEach((items, term) => {\n if (term.includes(lowerPartial)) {\n suggestions.add(term);\n }\n });\n\n // Add common operation types\n const operationTypes = ['payment', 'create_account', 'manage_offer', 'set_options', 'change_trust'];\n operationTypes.forEach(type => {\n if (type.includes(lowerPartial)) {\n suggestions.add(type);\n }\n });\n\n // Add common assets\n const commonAssets = ['XLM', 'USDC', 'BTC', 'ETH', 'USDT'];\n commonAssets.forEach(asset => {\n if (asset.toLowerCase().includes(lowerPartial)) {\n suggestions.add(asset);\n }\n });\n\n return Array.from(suggestions).slice(0, 10);\n }\n\n /**\n * Clear search history\n */\n clearHistory() {\n this.searchHistory = [];\n }\n\n /**\n * Reset all filters\n */\n resetFilters() {\n this.filters = {\n dateRange: { start: null, end: null },\n assetType: null,\n operationType: null,\n amountRange: { min: null, max: null },\n addressFilter: null,\n memoFilter: null,\n statusFilter: null,\n networkFilter: null\n };\n }\n\n /**\n * Get current filters\n * @returns {object} Current filters\n */\n getFilters() {\n return { ...this.filters };\n }\n\n /**\n * Get search statistics\n * @returns {object} Search statistics\n */\n getStatistics() {\n return {\n indexedItems: Array.from(this.indexedData.values()).reduce((total, items) => total + items.length, 0),\n indexedTypes: Array.from(this.indexedData.keys()),\n searchTerms: this.searchIndex.size,\n searchHistory: this.searchHistory.length,\n savedSearches: this.savedSearches.length\n };\n }\n}\n\n// Create singleton instance\nconst advancedSearchService = new AdvancedSearchService();\n\nexport default advancedSearchService;\nexport { AdvancedSearchService };\n","import React, { useState, useEffect, useMemo } from 'react';\nimport {\n Search,\n Filter,\n Calendar,\n DollarSign,\n Hash,\n FileText,\n Clock,\n ChevronDown,\n ChevronUp,\n X,\n Save,\n History,\n BarChart3,\n Download,\n RefreshCw,\n SlidersHorizontal,\n Tag,\n Activity,\n Globe,\n CheckCircle,\n AlertCircle,\n Folder,\n Share2,\n BellRing,\n Copy,\n} from 'lucide-react';\nimport advancedSearchService from '../../lib/advancedSearch.js';\nimport auditTrail from '../../lib/auditTrail.js';\nimport { format } from 'date-fns';\n\nexport default function AdvancedSearch() {\n const [searchQuery, setSearchQuery] = useState('');\n const [searchResults, setSearchResults] = useState(null);\n const [loading, setLoading] = useState(false);\n const [showFilters, setShowFilters] = useState(false);\n const [showHistory, setShowHistory] = useState(false);\n const [savedSearches, setSavedSearches] = useState([]);\n const [savedFolders, setSavedFolders] = useState([]);\n const [searchAnalytics, setSearchAnalytics] = useState(null);\n const [searchHistory, setSearchHistory] = useState([]);\n const [suggestions, setSuggestions] = useState([]);\n const [showSuggestions, setShowSuggestions] = useState(false);\n const [selectedTypes, setSelectedTypes] = useState(['transactions', 'operations', 'contracts', 'accounts']);\n const [savedSearchFolder, setSavedSearchFolder] = useState('General');\n const [createAlertOnSave, setCreateAlertOnSave] = useState(false);\n const [alertCron, setAlertCron] = useState('0 * * * *');\n const [shareToken, setShareToken] = useState('');\n \n const [filters, setFilters] = useState({\n dateRange: { start: '', end: '' },\n assetType: '',\n operationType: '',\n amountRange: { min: '', max: '' },\n addressFilter: '',\n memoFilter: '',\n statusFilter: '',\n networkFilter: '',\n });\n\n const [sort, setSort] = useState({\n field: 'timestamp',\n direction: 'desc'\n });\n\n const [pagination, setPagination] = useState({\n page: 1,\n limit: 20\n });\n\n useEffect(() => {\n loadData();\n }, []);\n\n useEffect(() => {\n if (searchQuery.length > 1) {\n const newSuggestions = advancedSearchService.getSuggestions(searchQuery);\n setSuggestions(newSuggestions);\n setShowSuggestions(true);\n } else {\n setSuggestions([]);\n setShowSuggestions(false);\n }\n }, [searchQuery]);\n\n const loadData = () => {\n setSavedSearches(advancedSearchService.getSavedSearches());\n setSavedFolders(advancedSearchService.getSavedSearchFolders());\n setSearchHistory(advancedSearchService.getSearchHistory());\n setSearchAnalytics(advancedSearchService.getSearchAnalytics());\n };\n\n const handleSearch = async () => {\n if (!searchQuery.trim() && !hasActiveFilters()) {\n return;\n }\n\n setLoading(true);\n try {\n const query = {\n text: searchQuery.trim(),\n types: selectedTypes,\n filters: buildFilters(),\n sort,\n page: pagination.page,\n limit: pagination.limit\n };\n\n const results = advancedSearchService.search(query);\n setSearchResults(results);\n\n auditTrail.logUserAction('Performed advanced search', {\n query: searchQuery.trim(),\n types: selectedTypes,\n resultCount: results.total,\n searchTime: results.searchTime\n });\n loadData();\n\n } catch (error) {\n auditTrail.logError(error, { operation: 'advancedSearch', query: searchQuery });\n console.error('Search failed:', error);\n } finally {\n setLoading(false);\n }\n };\n\n const buildFilters = () => {\n const builtFilters = {};\n \n if (filters.dateRange.start) {\n builtFilters.dateRange = { ...builtFilters.dateRange, start: new Date(filters.dateRange.start).getTime() };\n }\n if (filters.dateRange.end) {\n builtFilters.dateRange = { ...builtFilters.dateRange, end: new Date(filters.dateRange.end).getTime() };\n }\n \n if (filters.assetType) builtFilters.assetType = filters.assetType;\n if (filters.operationType) builtFilters.operationType = filters.operationType;\n if (filters.addressFilter) builtFilters.addressFilter = filters.addressFilter;\n if (filters.memoFilter) builtFilters.memoFilter = filters.memoFilter;\n if (filters.statusFilter) builtFilters.statusFilter = filters.statusFilter;\n if (filters.networkFilter) builtFilters.networkFilter = filters.networkFilter;\n \n if (filters.amountRange.min) {\n builtFilters.amountRange = { ...builtFilters.amountRange, min: parseFloat(filters.amountRange.min) };\n }\n if (filters.amountRange.max) {\n builtFilters.amountRange = { ...builtFilters.amountRange, max: parseFloat(filters.amountRange.max) };\n }\n \n return builtFilters;\n };\n\n const hasActiveFilters = () => {\n return Object.values(filters).some(value => {\n if (typeof value === 'object' && value !== null) {\n return Object.values(value).some(v => v !== '');\n }\n return value !== '';\n });\n };\n\n const clearFilters = () => {\n setFilters({\n dateRange: { start: '', end: '' },\n assetType: '',\n operationType: '',\n amountRange: { min: '', max: '' },\n addressFilter: '',\n memoFilter: '',\n statusFilter: '',\n networkFilter: '',\n });\n advancedSearchService.resetFilters();\n };\n\n const saveSearch = () => {\n const name = prompt('Enter a name for this search:');\n if (name) {\n const query = {\n text: searchQuery.trim(),\n types: selectedTypes,\n filters: buildFilters(),\n sort\n };\n const saved = advancedSearchService.saveSearch(name, query, { folder: savedSearchFolder });\n if (createAlertOnSave) {\n advancedSearchService.createSearchAlert({\n savedSearchId: saved.id,\n name: `${name} alert`,\n cron: alertCron,\n channels: ['in-app'],\n });\n }\n loadData();\n \n auditTrail.logUserAction('Saved search', { name, query });\n }\n };\n\n const loadSavedSearch = (savedSearch) => {\n const selectedSearch = advancedSearchService.loadSavedSearch(savedSearch.id) || savedSearch;\n setSearchQuery(selectedSearch.query.text || '');\n setSelectedTypes(selectedSearch.query.types || ['transactions', 'operations']);\n \n // Reset filters and load saved ones\n clearFilters();\n if (selectedSearch.query.filters) {\n setFilters({ ...filters, ...selectedSearch.query.filters });\n }\n \n if (selectedSearch.query.sort) {\n setSort(selectedSearch.query.sort);\n }\n \n setShowHistory(false);\n loadData();\n handleSearch();\n };\n\n const shareSavedSearch = (event, savedSearch) => {\n event.stopPropagation();\n const token = advancedSearchService.shareSearch(savedSearch.id);\n setShareToken(token);\n loadData();\n };\n\n const exportResults = () => {\n if (!searchResults) return;\n \n const data = JSON.stringify(searchResults, null, 2);\n const blob = new Blob([data], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = `stellar-search-results-${Date.now()}.json`;\n a.click();\n URL.revokeObjectURL(url);\n \n auditTrail.logUserAction('Exported search results', { resultCount: searchResults.total });\n };\n\n const handleSuggestionClick = (suggestion) => {\n setSearchQuery(suggestion);\n setShowSuggestions(false);\n };\n\n const handleTypeToggle = (type) => {\n setSelectedTypes(prev => \n prev.includes(type) \n ? prev.filter(t => t !== type)\n : [...prev, type]\n );\n };\n\n return (\n
\n {/* Header */}\n
\n
\n \n Advanced Search\n
\n
\n Global search across transactions, operations, contracts, and accounts\n
\n
\n\n {/* Search Bar */}\n \n {/* Main Search Input */}\n
\n \n setSearchQuery(e.target.value)}\n onKeyPress={(e) => e.key === 'Enter' && handleSearch()}\n placeholder=\"Search transactions, operations, contracts, accounts...\"\n style={{\n ...inputStyle,\n paddingLeft: '40px',\n paddingRight: '120px',\n fontSize: '14px',\n }}\n />\n \n
\n setShowHistory(!showHistory)}\n style={{ ...iconButtonStyle, title: 'Search History' }}\n >\n \n \n \n \n \n \n {loading ? : }\n \n
\n\n {/* Suggestions */}\n {showSuggestions && suggestions.length > 0 && (\n
\n {suggestions.map((suggestion, index) => (\n handleSuggestionClick(suggestion)}\n style={{\n padding: '8px 12px',\n cursor: 'pointer',\n fontSize: '13px',\n color: 'var(--text-primary)',\n borderBottom: '1px solid var(--border)',\n }}\n onMouseEnter={(e) => e.target.style.background = 'var(--bg-card)'}\n onMouseLeave={(e) => e.target.style.background = 'transparent'}\n >\n {suggestion}\n
\n ))}\n
\n )}\n
\n\n {/* Type Selection */}\n
\n
Search in:
\n
\n {['transactions', 'operations', 'contracts', 'accounts'].map(type => (\n handleTypeToggle(type)}\n style={{\n ...chipStyle,\n background: selectedTypes.includes(type) ? 'var(--cyan)' : 'var(--bg-elevated)',\n color: selectedTypes.includes(type) ? 'white' : 'var(--text-primary)',\n }}\n >\n {type}\n \n ))}\n
\n
\n\n {/* Saved Query Options */}\n
\n \n\n \n\n \n
\n\n {/* Filter Toggle */}\n
\n setShowFilters(!showFilters)}\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n gap: '6px',\n padding: '8px 12px',\n background: 'var(--bg-elevated)',\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius-md)',\n color: 'var(--text-primary)',\n fontSize: '12px',\n cursor: 'pointer',\n }}\n >\n \n {showFilters ? 'Hide Filters' : 'Show Filters'}\n {showFilters ? : }\n \n\n {hasActiveFilters() && (\n \n \n Clear Filters\n \n )}\n
\n\n {/* Advanced Filters */}\n {showFilters && (\n
\n
\n {/* Date Range */}\n
\n \n
\n setFilters(prev => ({ \n ...prev, \n dateRange: { ...prev.dateRange, start: e.target.value }\n }))}\n style={{ ...inputStyle, fontSize: '12px' }}\n />\n setFilters(prev => ({ \n ...prev, \n dateRange: { ...prev.dateRange, end: e.target.value }\n }))}\n style={{ ...inputStyle, fontSize: '12px' }}\n />\n
\n
\n\n {/* Asset Type */}\n
\n \n setFilters(prev => ({ ...prev, assetType: e.target.value }))}\n style={{ ...inputStyle, fontSize: '12px' }}\n >\n \n \n \n \n \n \n \n
\n\n {/* Operation Type */}\n
\n \n setFilters(prev => ({ ...prev, operationType: e.target.value }))}\n style={{ ...inputStyle, fontSize: '12px' }}\n >\n \n \n \n \n \n \n \n
\n\n {/* Amount Range */}\n
\n \n
\n setFilters(prev => ({ \n ...prev, \n amountRange: { ...prev.amountRange, min: e.target.value }\n }))}\n style={{ ...inputStyle, fontSize: '12px' }}\n />\n setFilters(prev => ({ \n ...prev, \n amountRange: { ...prev.amountRange, max: e.target.value }\n }))}\n style={{ ...inputStyle, fontSize: '12px' }}\n />\n
\n
\n\n {/* Address Filter */}\n
\n \n setFilters(prev => ({ ...prev, addressFilter: e.target.value }))}\n style={{ ...inputStyle, fontSize: '12px' }}\n />\n
\n\n {/* Memo Filter */}\n
\n \n setFilters(prev => ({ ...prev, memoFilter: e.target.value }))}\n style={{ ...inputStyle, fontSize: '12px' }}\n />\n
\n\n {/* Status Filter */}\n
\n \n setFilters(prev => ({ ...prev, statusFilter: e.target.value }))}\n style={{ ...inputStyle, fontSize: '12px' }}\n >\n \n \n \n \n \n
\n\n {/* Network Filter */}\n
\n \n setFilters(prev => ({ ...prev, networkFilter: e.target.value }))}\n style={{ ...inputStyle, fontSize: '12px' }}\n >\n \n \n \n \n \n
\n
\n
\n )}\n \n\n {/* Search History */}\n {showHistory && (\n \n
\n Search History & Saved Searches\n \n
\n\n {searchAnalytics && (\n
\n \n \n \n \n
\n )}\n\n
\n {/* Folders */}\n
\n
Folders
\n
\n {savedFolders.map((folder) => (\n {\n setSavedSearchFolder(folder.name);\n setSavedSearches(advancedSearchService.getSavedSearches({ folder: folder.name }));\n }}\n style={{\n padding: '8px 12px',\n background: savedSearchFolder === folder.name ? 'var(--cyan-glow)' : 'var(--bg-elevated)',\n border: `1px solid ${savedSearchFolder === folder.name ? 'var(--cyan-dim)' : 'var(--border)'}`,\n borderRadius: 'var(--radius-md)',\n cursor: 'pointer',\n fontSize: '12px',\n color: 'var(--text-primary)',\n display: 'flex',\n justifyContent: 'space-between',\n }}\n >\n {folder.name}\n {folder.count}\n \n ))}\n
\n
\n\n {/* Recent Searches */}\n
\n
Recent Searches
\n
\n {searchHistory.slice(0, 5).map((item, index) => (\n {\n setSearchQuery(item.query.text || '');\n setShowHistory(false);\n }}\n style={{\n padding: '8px 12px',\n background: 'var(--bg-elevated)',\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius-md)',\n cursor: 'pointer',\n fontSize: '12px',\n }}\n >\n
{item.query.text || 'Empty search'}
\n
\n {format(new Date(item.timestamp), 'MMM dd, HH:mm')} / {item.resultCount || 0} results / {item.cached ? 'cached' : `${item.searchTime || 0}ms`}\n
\n
\n ))}\n
\n
\n\n {/* Saved Searches */}\n
\n
Saved Searches
\n
\n {savedSearches.slice(0, 5).map((item, index) => (\n loadSavedSearch(item)}\n style={{\n padding: '8px 12px',\n background: 'var(--bg-elevated)',\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius-md)',\n cursor: 'pointer',\n fontSize: '12px',\n }}\n >\n
\n
{item.name}
\n \n
\n
\n {item.folder || 'General'} / {item.query.text || 'No query'} / used {item.usageCount || 0}x\n
\n
\n ))}\n {shareToken && (\n
\n \n {shareToken}\n
\n )}\n
\n \n \n \n )}\n\n {/* Search Results */}\n {searchResults && (\n \n {/* Results Header */}\n
\n
\n
\n {searchResults.total} results found\n
\n
\n Search completed in {searchResults.searchTime}ms{searchResults.cached ? ' from cache' : ''}\n
\n {searchResults.queryPlan && (\n
\n {searchResults.queryPlan.usesIndex ? 'Index-assisted' : 'Scan'} / {searchResults.queryPlan.filterCount} filters / cache TTL {Math.round(searchResults.queryPlan.cacheTtlMs / 1000)}s\n
\n )}\n
\n \n
\n \n \n \n \n \n \n
\n
\n\n {/* Results Body */}\n {searchResults.results.length === 0 ? (\n
\n No results found for your search criteria.\n
\n ) : (\n
\n {/* Aggregations */}\n {searchResults.aggregations && (\n
\n
Results Overview
\n
\n \n \n \n \n
\n
\n )}\n\n {/* Results List */}\n
\n {searchResults.results.map((result, index) => (\n \n ))}\n
\n\n {/* Pagination */}\n {searchResults.totalPages > 1 && (\n
\n setPagination(prev => ({ ...prev, page: Math.max(1, prev.page - 1) }))}\n disabled={searchResults.page === 1}\n style={paginationButtonStyle}\n >\n Previous\n \n \n \n Page {searchResults.page} of {searchResults.totalPages}\n \n \n setPagination(prev => ({ ...prev, page: Math.min(searchResults.totalPages, prev.page + 1) }))}\n disabled={searchResults.page === searchResults.totalPages}\n style={paginationButtonStyle}\n >\n Next\n \n
\n )}\n
\n )}\n \n )}\n \n );\n}\n\nfunction SearchResultItem({ result }) {\n const [expanded, setExpanded] = useState(false);\n\n const getTypeIcon = (type) => {\n const icons = {\n transactions: ,\n operations: ,\n contracts: ,\n accounts: \n };\n return icons[type] || ;\n };\n\n const getTypeColor = (type) => {\n const colors = {\n transactions: 'var(--blue)',\n operations: 'var(--green)',\n contracts: 'var(--purple)',\n accounts: 'var(--orange)'\n };\n return colors[type] || 'var(--text-secondary)';\n };\n\n return (\n
\n setExpanded(!expanded)}\n >\n
\n
\n
\n {getTypeIcon(result.type)}\n
\n \n
\n
\n {result.type.charAt(0).toUpperCase() + result.type.slice(1)}\n {result.operationType && ` • ${result.operationType}`}\n
\n \n
\n {result.address && Address: {result.address.substring(0, 16)}... }\n {result.asset && Asset: {result.asset} }\n {result.amount && Amount: {result.amount} }\n {result.status && Status: {result.status}}\n
\n \n
\n {new Date(result.timestamp).toLocaleString()}\n
\n
\n
\n \n
\n {expanded ? : }\n
\n
\n
\n \n {expanded && (\n
\n
\n            {JSON.stringify(result.data, null, 2)}\n          
\n
\n )}\n \n );\n}\n\nfunction AggregationChip({ label, data }) {\n const entries = Object.entries(data).slice(0, 3);\n \n return (\n
\n {label}:\n {entries.map(([key, value], index) => (\n \n {key} ({value})\n {index < entries.length - 1 && ', '}\n \n ))}\n {Object.keys(data).length > 3 && '...'}\n
\n );\n}\n\nconst inputStyle = {\n width: '100%',\n padding: '8px 12px',\n background: 'var(--bg-elevated)',\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius-md)',\n color: 'var(--text-primary)',\n fontSize: '13px',\n fontFamily: 'var(--font-mono)',\n outline: 'none',\n};\n\nconst labelStyle = {\n fontSize: '12px',\n color: 'var(--text-muted)',\n textTransform: 'uppercase',\n letterSpacing: '0.5px',\n display: 'flex',\n alignItems: 'center',\n marginBottom: '6px',\n};\n\nconst chipStyle = {\n padding: '4px 12px',\n background: 'var(--bg-elevated)',\n border: '1px solid var(--border)',\n borderRadius: '999px',\n fontSize: '12px',\n cursor: 'pointer',\n transition: 'var(--transition)',\n};\n\nconst iconButtonStyle = {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: '32px',\n height: '32px',\n background: 'var(--bg-elevated)',\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius-md)',\n color: 'var(--text-primary)',\n cursor: 'pointer',\n transition: 'var(--transition)',\n};\n\nconst paginationButtonStyle = {\n padding: '6px 12px',\n background: 'var(--bg-elevated)',\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius-md)',\n color: 'var(--text-primary)',\n fontSize: '12px',\n cursor: 'pointer',\n transition: 'var(--transition)',\n};\n"],"names":["STORAGE_KEYS","getBrowserStorage","readStoredArray","storage","key","fallback","parsed","writeStoredArray","value","stableStringify","makeId","prefix","encodeSharePayload","payload","serialized","decodeSharePayload","token","AdvancedSearchService","options","type","data","indexed","item","term","baseItem","terms","word","extractStrings","obj","fullKey","code","query","startTime","optimizedQuery","queryPlan","cacheKey","cached","cachedResult","results","items","paginatedResults","searchTime","response","error","searchText","searchTerms","indexedItems","field","direction","a","b","aValue","bValue","comparison","page","limit","startIndex","endIndex","aggregations","amountCount","text","types","result","entry","indexedTerms","filterCount","nested","meta","historyEntry","name","folder","savedSearch","search","id","normalizedName","existing","shareToken","input","alert","cronExpression","from","minute","hour","next","now","counts","count","history","totalSearchTime","sum","partial","suggestions","lowerPartial","asset","total","advancedSearchService","AdvancedSearch","searchQuery","setSearchQuery","useState","searchResults","setSearchResults","loading","setLoading","showFilters","setShowFilters","showHistory","setShowHistory","savedSearches","setSavedSearches","savedFolders","setSavedFolders","searchAnalytics","setSearchAnalytics","searchHistory","setSearchHistory","setSuggestions","showSuggestions","setShowSuggestions","selectedTypes","setSelectedTypes","savedSearchFolder","setSavedSearchFolder","createAlertOnSave","setCreateAlertOnSave","alertCron","setAlertCron","setShareToken","filters","setFilters","sort","setSort","pagination","setPagination","useEffect","loadData","newSuggestions","handleSearch","hasActiveFilters","buildFilters","auditTrail","builtFilters","v","clearFilters","saveSearch","saved","loadSavedSearch","selectedSearch","shareSavedSearch","event","exportResults","blob","url","handleSuggestionClick","suggestion","handleTypeToggle","prev","t","jsxs","jsx","Search","e","inputStyle","iconButtonStyle","History","Save","RefreshCw","index","chipStyle","Folder","BellRing","SlidersHorizontal","ChevronUp","ChevronDown","X","labelStyle","Calendar","Tag","Activity","DollarSign","Hash","FileText","CheckCircle","Globe","format","Share2","Copy","Download","AggregationChip","SearchResultItem","paginationButtonStyle","expanded","setExpanded","getTypeIcon","getTypeColor","label","entries"],"mappings":"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"} \ No newline at end of file diff --git a/dist/assets/AdvancedSearch-ELYmfCV_.js b/dist/assets/AdvancedSearch-ELYmfCV_.js new file mode 100644 index 00000000..299b0a64 --- /dev/null +++ b/dist/assets/AdvancedSearch-ELYmfCV_.js @@ -0,0 +1,2 @@ +var Ke=Object.defineProperty;var Ge=(o,e,t)=>e in o?Ke(o,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):o[e]=t;var P=(o,e,t)=>Ge(o,typeof e!="symbol"?e+"":e,t);import{r as h,j as s,R as Xe}from"./react-vendor-C-OVADYf.js";import{ab as ie}from"./charts-D9P2NM_R.js";import{K as pe,s as De,N as Z,R as me,X as ve,C as Me,aj as Ye,ae as Ve,a1 as Je,a2 as Ze,a0 as et,g as tt,aM as st,D as _e,a4 as rt,aC as at,aN as nt,at as ot,aO as it,_ as Le,$ as Ee,aP as lt,aQ as ct,A as Oe,ao as dt,aR as $e,a7 as Be,al as He,S as ut,i as pt}from"./icons-vendor-C7uAdRPq.js";import{f as ht}from"./date-vendor-boStncAG.js";import"./vendor-CdKO02NA.js";import"./deployment-q_dUxQhv.js";import"./stellar-sdk-Cld1ipgo.js";import"./charts-vendor-BYXr-dPO.js";const E={history:"stellar-advanced-search-history-v1",saved:"stellar-advanced-search-saved-v1",alerts:"stellar-advanced-search-alerts-v1",folders:"stellar-advanced-search-folders-v1"};function xt(){try{return typeof localStorage<"u"?localStorage:null}catch{return null}}function le(o,e,t=[]){if(!o)return[...t];try{const r=JSON.parse(o.getItem(e)||"null");return Array.isArray(r)?r:[...t]}catch{return[...t]}}function K(o,e,t){if(o)try{o.setItem(e,JSON.stringify(t))}catch{}}function be(o){return Array.isArray(o)?`[${o.map(be).join(",")}]`:o&&typeof o=="object"?`{${Object.keys(o).sort().map(e=>`${JSON.stringify(e)}:${be(o[e])}`).join(",")}}`:JSON.stringify(o)}function ce(o){return`${o}-${Date.now()}-${Math.random().toString(36).slice(2,8)}`}function ft(o){const e=encodeURIComponent(JSON.stringify(o));return typeof btoa=="function"?btoa(e):e}function gt(o){const e=typeof atob=="function"?atob(o):o;return JSON.parse(decodeURIComponent(e))}class yt{constructor(e={}){this.storage=e.storage||xt(),this.searchHistory=le(this.storage,E.history),this.savedSearches=le(this.storage,E.saved),this.searchAlerts=le(this.storage,E.alerts),this.savedQueryFolders=le(this.storage,E.folders,[{id:"general",name:"General",createdAt:new Date().toISOString()}]),this.resultCache=new Map,this.cacheTtlMs=e.cacheTtlMs||60*1e3,this.indexedData=new Map,this.searchIndex=new Map,this.filters={dateRange:{start:null,end:null},assetType:null,operationType:null,amountRange:{min:null,max:null},addressFilter:null,memoFilter:null,statusFilter:null,networkFilter:null},this.sortOptions={field:"timestamp",direction:"desc"}}indexData(e,t){if(!Array.isArray(t))return;const r=t.map(a=>this.createSearchableItem(e,a));this.indexedData.set(e,r),r.forEach(a=>{this.extractSearchTerms(a).forEach(l=>{this.searchIndex.has(l)||this.searchIndex.set(l,new Set),this.searchIndex.get(l).add(a.id)})})}createSearchableItem(e,t){const r={id:`${e}_${t.id||t.hash||t.address}`,type:e,data:t,timestamp:this.extractTimestamp(t),amount:this.extractAmount(t),asset:this.extractAsset(t),operationType:this.extractOperationType(t),address:this.extractAddress(t),memo:this.extractMemo(t),status:this.extractStatus(t),network:t.network||"unknown"};switch(e){case"transactions":r.transactionHash=t.hash,r.fee=t.fee,r.operationCount=t.operation_count;break;case"operations":r.operationId=t.id,r.transactionHash=t.transaction_hash,r.sourceAccount=t.source_account;break;case"contracts":r.contractId=t.contract_id||t.id,r.contractType=t.type;break;case"accounts":r.accountId=t.account_id||t.address,r.balance=t.balance,r.sequence=t.sequence;break}return r}extractSearchTerms(e){const t=new Set;return t.add(e.type.toLowerCase()),t.add(e.operationType?.toLowerCase()||""),t.add(e.asset?.toLowerCase()||""),t.add(e.status?.toLowerCase()||""),t.add(e.network?.toLowerCase()||""),e.address&&t.add(e.address.toLowerCase()),e.transactionHash&&t.add(e.transactionHash.toLowerCase()),e.contractId&&t.add(e.contractId.toLowerCase()),e.accountId&&t.add(e.accountId.toLowerCase()),e.memo&&(t.add(e.memo.toLowerCase()),e.memo.toLowerCase().split(/\s+/).forEach(r=>{r.length>2&&t.add(r)})),e.amount&&(t.add(e.amount.toString()),t.add(parseFloat(e.amount).toFixed(2))),this.extractDataSpecificTerms(e.data,t),Array.from(t).filter(r=>r.length>0)}extractDataSpecificTerms(e,t){const r=(a,n="")=>{Object.entries(a).forEach(([l,c])=>{const d=n?`${n}.${l}`:l;typeof c=="string"&&c.length>0?(t.add(c.toLowerCase()),c.toLowerCase().split(/\s+/).forEach(p=>{p.length>2&&t.add(p)})):typeof c=="number"?t.add(c.toString()):typeof c=="object"&&c!==null&&r(c,d)})};r(e)}extractTimestamp(e){return e.created_at?new Date(e.created_at).getTime():e.timestamp?new Date(e.timestamp).getTime():e.time?new Date(e.time).getTime():Date.now()}extractAmount(e){return e.amount?parseFloat(e.amount):e.starting_balance?parseFloat(e.starting_balance):e.amount_in?parseFloat(e.amount_in):e.amount_out?parseFloat(e.amount_out):null}extractAsset(e){return e.asset_code?e.asset_code:e.asset_type==="native"?"XLM":e.asset_code&&e.asset_issuer?`${e.asset_code}:${e.asset_issuer}`:null}extractOperationType(e){return e.type?e.type:e.operation_type?this.getOperationTypeName(e.operation_type):null}getOperationTypeName(e){return{0:"payment",1:"create_account",2:"manage_offer",3:"set_options",4:"change_trust",5:"allow_trust",6:"account_merge",7:"inflation",8:"manage_data",9:"bump_sequence",10:"create_claimable_balance",11:"claim_claimable_balance",12:"begin_sponsoring_future_reserves",13:"end_sponsoring_future_reserves",14:"revoke_sponsorship"}[e]||"unknown"}extractAddress(e){return e.account_id?e.account_id:e.source_account?e.source_account:e.destination_account?e.destination_account:e.address?e.address:null}extractMemo(e){if(e.memo)return e.memo;if(e.memo_type&&e.memo_value){if(e.memo_type==="text")return e.memo_value;if(e.memo_type==="id")return e.memo_value.toString()}return null}extractStatus(e){return e.status?e.status:e.successful!==void 0?e.successful?"success":"failed":e.result_successful!==void 0?e.result_successful?"success":"failed":null}search(e){const t=Date.now();try{const r=this.optimizeQuery(e);r.filters&&(this.filters={...this.filters,...r.filters}),r.sort&&(this.sortOptions={...this.sortOptions,...r.sort});const a=this.buildQueryPlan(r),n=this.createQueryKey({...r,filters:this.filters,sort:this.sortOptions}),l=r.cache!==!1?this.getCachedResults(n):null;if(l){const v={...l,query:r,cached:!0,searchTime:Date.now()-t,queryPlan:a};return this.addToSearchHistory(r,{resultCount:l.total,searchTime:v.searchTime,cached:!0}),v}let c=[];this.indexedData.forEach((v,w)=>{(!r.types||r.types.includes(w))&&c.push(...v)}),r.text&&r.text.trim()&&(c=this.applyTextSearch(c,r.text.trim())),c=this.applyFilters(c),c=this.applySorting(c);const d=this.applyPagination(c,r.page,r.limit),p=Date.now()-t,m={query:r,results:d.items,total:d.total,page:d.page,limit:d.limit,searchTime:p,cached:!1,cacheKey:n,queryPlan:a,filters:{...this.filters},sort:{...this.sortOptions},aggregations:this.calculateAggregations(c)};return this.setCachedResults(n,m),this.addToSearchHistory(r,{resultCount:m.total,searchTime:p,cached:!1}),m}catch(r){throw new Error(`Search failed: ${r.message}`)}}applyTextSearch(e,t){const r=t.toLowerCase().split(/\s+/).filter(a=>a.length>0);return r.length===0?e:e.filter(a=>r.every(n=>this.itemContainsTerm(a,n)))}itemContainsTerm(e,t){if(e.type?.toLowerCase().includes(t)||e.operationType?.toLowerCase().includes(t)||e.asset?.toLowerCase().includes(t)||e.status?.toLowerCase().includes(t)||e.address?.toLowerCase().includes(t)||e.memo?.toLowerCase().includes(t)||e.transactionHash?.toLowerCase().includes(t)||e.contractId?.toLowerCase().includes(t)||e.accountId?.toLowerCase().includes(t)||e.amount?.toString().includes(t))return!0;const r=this.searchIndex.get(t.toLowerCase());return!!(r&&r.has(e.id))}applyFilters(e){return e.filter(t=>!(this.filters.dateRange.start&&t.timestampthis.filters.dateRange.end||this.filters.assetType&&t.asset!==this.filters.assetType||this.filters.operationType&&t.operationType!==this.filters.operationType||this.filters.amountRange.min!==null&&(!t.amount||t.amountthis.filters.amountRange.max)||this.filters.addressFilter&&!t.address?.includes(this.filters.addressFilter)||this.filters.memoFilter&&!t.memo?.toLowerCase().includes(this.filters.memoFilter.toLowerCase())||this.filters.statusFilter&&t.status!==this.filters.statusFilter||this.filters.networkFilter&&t.network!==this.filters.networkFilter))}applySorting(e){const{field:t,direction:r}=this.sortOptions;return e.sort((a,n)=>{let l=a[t],c=n[t];l==null&&(l=""),c==null&&(c="");let d=0;return typeof l=="number"&&typeof c=="number"?d=l-c:d=String(l).localeCompare(String(c)),r==="asc"?d:-d})}applyPagination(e,t=1,r=20){const a=(t-1)*r,n=a+r;return{items:e.slice(a,n),total:e.length,page:t,limit:r,totalPages:Math.ceil(e.length/r)}}calculateAggregations(e){const t={typeCounts:{},operationTypeCounts:{},assetCounts:{},statusCounts:{},totalAmount:0,averageAmount:0,dateRange:{earliest:null,latest:null}};e.forEach(a=>{t.typeCounts[a.type]=(t.typeCounts[a.type]||0)+1,a.operationType&&(t.operationTypeCounts[a.operationType]=(t.operationTypeCounts[a.operationType]||0)+1),a.asset&&(t.assetCounts[a.asset]=(t.assetCounts[a.asset]||0)+1),a.status&&(t.statusCounts[a.status]=(t.statusCounts[a.status]||0)+1),a.amount&&(t.totalAmount+=a.amount),a.timestamp&&((!t.dateRange.earliest||a.timestampt.dateRange.latest)&&(t.dateRange.latest=a.timestamp))});const r=e.filter(a=>a.amount!==null).length;return t.averageAmount=r>0?t.totalAmount/r:0,t}optimizeQuery(e={}){const t=(e.text||"").trim(),r=Array.isArray(e.types)&&e.types.length?Array.from(new Set(e.types)).sort():null;return{...e,text:t,types:r,page:Math.max(Number(e.page)||1,1),limit:Math.min(Math.max(Number(e.limit)||20,1),100)}}createQueryKey(e){return be({text:e.text||"",types:e.types||null,filters:e.filters||{},sort:e.sort||{},page:e.page||1,limit:e.limit||20})}setCachedResults(e,t){this.resultCache.set(e,{expiresAt:Date.now()+this.cacheTtlMs,result:t})}getCachedResults(e){const t=this.resultCache.get(e);return t?t.expiresAt<=Date.now()?(this.resultCache.delete(e),null):t.result:null}clearResultCache(){this.resultCache.clear()}buildQueryPlan(e){const t=(e.text||"").toLowerCase().split(/\s+/).filter(Boolean),r=t.filter(n=>this.searchIndex.has(n)),a=Object.values(e.filters||{}).filter(n=>n&&typeof n=="object"?Object.values(n).some(l=>l!==null&&l!==""):n!==null&&n!=="").length;return{textTerms:t,indexedTerms:r,filterCount:a,usesIndex:r.length>0,cacheTtlMs:this.cacheTtlMs,indexedTypes:e.types||Array.from(this.indexedData.keys())}}addToSearchHistory(e,t={}){const r={id:ce("history"),timestamp:new Date().toISOString(),query:{...e},resultCount:t.resultCount||0,searchTime:t.searchTime||0,cached:!!t.cached};this.searchHistory.unshift(r),this.searchHistory.length>50&&(this.searchHistory=this.searchHistory.slice(0,50)),K(this.storage,E.history,this.searchHistory)}saveSearch(e,t,r={}){const a=r.folder||"General";this.createSavedSearchFolder(a);const n={id:ce("saved"),name:e,query:{...t},folder:a,tags:r.tags||[],description:r.description||"",sharedWith:[],shareToken:null,createdAt:new Date().toISOString(),updatedAt:new Date().toISOString(),usageCount:0};return this.savedSearches.push(n),K(this.storage,E.saved,this.savedSearches),n}getSavedSearches(e={}){return[...this.savedSearches].filter(t=>!e.folder||t.folder===e.folder).sort((t,r)=>r.usageCount-t.usageCount||new Date(r.updatedAt||r.createdAt).getTime()-new Date(t.updatedAt||t.createdAt).getTime())}loadSavedSearch(e){const t=this.savedSearches.find(r=>r.id===e);return t?(t.usageCount+=1,t.updatedAt=new Date().toISOString(),K(this.storage,E.saved,this.savedSearches),t):null}deleteSavedSearch(e){this.savedSearches=this.savedSearches.filter(t=>t.id!==e),K(this.storage,E.saved,this.savedSearches)}createSavedSearchFolder(e){const t=(e||"General").trim()||"General",r=this.savedQueryFolders.find(n=>n.name.toLowerCase()===t.toLowerCase());if(r)return r;const a={id:ce("folder"),name:t,createdAt:new Date().toISOString()};return this.savedQueryFolders.push(a),K(this.storage,E.folders,this.savedQueryFolders),a}getSavedSearchFolders(){return this.savedQueryFolders.map(e=>({...e,count:this.savedSearches.filter(t=>t.folder===e.name).length}))}shareSearch(e,t={}){const r=this.savedSearches.find(a=>a.id===e);if(!r)throw new Error("Saved search not found");return r.sharedWith=Array.from(new Set([...r.sharedWith||[],...t.users||[]])),r.shareToken=r.shareToken||ft({id:r.id,name:r.name,query:r.query,folder:r.folder}),r.updatedAt=new Date().toISOString(),K(this.storage,E.saved,this.savedSearches),r.shareToken}importSharedSearch(e,t={}){const r=gt(e);return this.saveSearch(t.name||r.name,r.query,{folder:t.folder||r.folder||"Shared",tags:["shared"]})}createSearchAlert(e){const t={id:ce("alert"),savedSearchId:e.savedSearchId||null,name:e.name||"Search alert",query:e.query||this.savedSearches.find(r=>r.id===e.savedSearchId)?.query||{},cron:e.cron||"0 * * * *",channels:e.channels||["in-app"],threshold:Number(e.threshold||1),enabled:e.enabled!==!1,lastRunAt:null,nextRunAt:this.getNextAlertRun(e.cron||"0 * * * *"),createdAt:new Date().toISOString()};return this.searchAlerts.push(t),K(this.storage,E.alerts,this.searchAlerts),t}getSearchAlerts(){return[...this.searchAlerts].sort((e,t)=>new Date(e.nextRunAt).getTime()-new Date(t.nextRunAt).getTime())}getNextAlertRun(e,t=new Date){const[r="0",a="*"]=e.trim().split(/\s+/),n=new Date(t);return n.setSeconds(0,0),n.setMinutes(n.getMinutes()+1),r!=="*"&&n.setMinutes(Number(r.replace("*/",""))||0),a!=="*"&&n.setHours(Number(a.replace("*/",""))||n.getHours()),n.getTime()<=t.getTime()&&n.setHours(n.getHours()+1),n.toISOString()}evaluateSearchAlerts(e=new Date){return this.searchAlerts.filter(t=>t.enabled&&new Date(t.nextRunAt).getTime()<=e.getTime()).map(t=>{const r=this.search({...t.query,cache:!1});return t.lastRunAt=e.toISOString(),t.nextRunAt=this.getNextAlertRun(t.cron,e),K(this.storage,E.alerts,this.searchAlerts),{alert:t,resultCount:r.total,triggered:r.total>=t.threshold}})}getSearchHistory(){return[...this.searchHistory]}getFrequentSearches(e=5){const t=new Map;return this.searchHistory.forEach(r=>{const a=r.query?.text||JSON.stringify(r.query?.filters||{});t.set(a,(t.get(a)||0)+1)}),Array.from(t.entries()).map(([r,a])=>({query:r,count:a})).sort((r,a)=>a.count-r.count).slice(0,e)}getSearchAnalytics(){const e=this.getSearchHistory(),t=e.reduce((r,a)=>r+(a.searchTime||0),0);return{totalSearches:e.length,cachedSearches:e.filter(r=>r.cached).length,averageSearchTime:e.length?t/e.length:0,savedSearches:this.savedSearches.length,folders:this.savedQueryFolders.length,alerts:this.searchAlerts.length,frequentSearches:this.getFrequentSearches(),cacheEntries:this.resultCache.size}}getSuggestions(e){if(!e||e.length<2)return[];const t=new Set,r=e.toLowerCase();return this.searchIndex.forEach((l,c)=>{c.includes(r)&&t.add(c)}),["payment","create_account","manage_offer","set_options","change_trust"].forEach(l=>{l.includes(r)&&t.add(l)}),["XLM","USDC","BTC","ETH","USDT"].forEach(l=>{l.toLowerCase().includes(r)&&t.add(l)}),Array.from(t).slice(0,10)}clearHistory(){this.searchHistory=[]}resetFilters(){this.filters={dateRange:{start:null,end:null},assetType:null,operationType:null,amountRange:{min:null,max:null},addressFilter:null,memoFilter:null,statusFilter:null,networkFilter:null}}getFilters(){return{...this.filters}}getStatistics(){return{indexedItems:Array.from(this.indexedData.values()).reduce((e,t)=>e+t.length,0),indexedTypes:Array.from(this.indexedData.keys()),searchTerms:this.searchIndex.size,searchHistory:this.searchHistory.length,savedSearches:this.savedSearches.length}}}const I=new yt,he={send:["payment","transfer","transmit","remit","pay"],payment:["send","transfer","remit","pay","disbursement"],transfer:["payment","send","move","shift"],receive:["incoming","received","destination","credited"],account:["wallet","address","publickey","user"],wallet:["account","address","publickey"],address:["account","wallet","publickey","key"],balance:["funds","holdings","amount","total"],xlm:["lumen","lumens","native","stellar"],lumen:["xlm","lumens","native"],native:["xlm","lumen","lumens"],asset:["token","currency","coin","trustline"],token:["asset","currency","coin"],trustline:["trust","asset","token"],transaction:["tx","txn","operation","op","record"],tx:["transaction","txn","op"],operation:["tx","transaction","op","action"],op:["operation","transaction","tx"],create:["createaccount","new","open","genesis"],merge:["accountmerge","close","combine"],offer:["order","trade","dex","sell","buy"],trade:["offer","swap","exchange","dex"],swap:["trade","exchange","offer"],liquidity:["pool","amm","lp","liquiditypool"],contract:["soroban","smart","wasm","program"],soroban:["contract","smart","wasm"],invoke:["call","execute","run","deploy"],success:["successful","completed","confirmed","ok"],failed:["failure","error","rejected","unsuccessful"],pending:["unconfirmed","waiting","queued"],recent:["latest","new","last","newest"],old:["oldest","historic","early","first"],today:["now","current","daily"],mainnet:["main","production","live"],testnet:["test","sandbox","dev"]},ne={};for(const[o,e]of Object.entries(he))for(const t of e)ne[t]||(ne[t]=[]),ne[t].includes(o)||ne[t].push(o);const Re=1.5,ze=.75;function mt(o,e){const t=o.length,r=e.length,a=Array.from({length:t+1},(n,l)=>Array.from({length:r+1},(c,d)=>l===0?d:d===0?l:0));for(let n=1;n<=t;n++)for(let l=1;l<=r;l++)o[n-1]===e[l-1]?a[n][l]=a[n-1][l-1]:a[n][l]=1+Math.min(a[n-1][l-1],a[n][l-1],a[n-1][l]);return a[t][r]}function Y(o){return o.toLowerCase().replace(/[^a-z0-9\s]/g," ").split(/\s+/).filter(e=>e.length>=2)}const vt=new Set(["the","a","an","is","in","it","of","or","at","by","be","as","to","for","on","do","if","no","so","up","we","me","my"]);function V(o){return o.filter(e=>!vt.has(e))}class bt{constructor(){P(this,"docs",[]);P(this,"invertedIndex",new Map);P(this,"idf",new Map);P(this,"df",new Map);P(this,"vocab",[]);P(this,"vocabIndex",new Map);P(this,"avgDocLen",0)}indexDocument(e){const t=V(Y(e.text)),r=this.docs.length,a=new Map;for(const l of t)a.set(l,(a.get(l)??0)+1);for(const l of a.keys())this.vocabIndex.has(l)||(this.vocabIndex.set(l,this.vocab.length),this.vocab.push(l)),this.invertedIndex.has(l)||this.invertedIndex.set(l,[]),this.invertedIndex.get(l).push(r),this.df.set(l,(this.df.get(l)??0)+1);const n={...e,_tokens:t,_tf:a};this.docs.push(n),this._recomputeIdf(),this._recomputeAvgDocLen()}indexDocuments(e){for(const t of e){const r=V(Y(t.text)),a=this.docs.length,n=new Map;for(const c of r)n.set(c,(n.get(c)??0)+1);for(const c of n.keys())this.vocabIndex.has(c)||(this.vocabIndex.set(c,this.vocab.length),this.vocab.push(c)),this.invertedIndex.has(c)||this.invertedIndex.set(c,[]),this.invertedIndex.get(c).push(a),this.df.set(c,(this.df.get(c)??0)+1);const l={...t,_tokens:r,_tf:n};this.docs.push(l)}this._recomputeIdf(),this._recomputeAvgDocLen()}_recomputeIdf(){const e=this.docs.length;if(e!==0)for(const[t,r]of this.df.entries())this.idf.set(t,Math.log((e-r+.5)/(r+.5)+1))}_recomputeAvgDocLen(){if(this.docs.length===0){this.avgDocLen=0;return}const e=this.docs.reduce((t,r)=>t+(r._tokens?.length??0),0);this.avgDocLen=e/this.docs.length}clearIndex(){this.docs=[],this.invertedIndex.clear(),this.idf.clear(),this.df.clear(),this.vocab=[],this.vocabIndex.clear(),this.avgDocLen=0}getIndexSize(){return this.docs.length}expandQuery(e){const t=V(Y(e)),r={},a=new Set(t);for(const n of t){const l=he[n];if(l?.length){for(const d of l)a.add(d);r[n]=l}const c=ne[n];if(c?.length)for(const d of c){a.add(d);const p=he[d]??[];for(const m of p)a.add(m);r[n]=[...r[n]??[],d,...p]}}return{originalTerms:t,expandedTerms:Array.from(a),synonymsUsed:r}}correctTypo(e){if(this.vocab.length===0||e.length<4)return{original:e,corrected:e,wasCorreected:!1};if(this.vocabIndex.has(e))return{original:e,corrected:e,wasCorreected:!1};let t=e,r=1/0;for(const a of this.vocab){if(Math.abs(a.length-e.length)>2)continue;const n=mt(e,a);n{const n=this.correctTypo(a);return t.push(n),n.corrected}),corrections:t}}buildVector(e,t){const r=new Array(this.vocab.length).fill(0),a=new Map;for(const n of e)a.set(n,(a.get(n)??0)+1);for(const[n,l]of a.entries()){const c=this.vocabIndex.get(n);if(c===void 0)continue;const d=this.idf.get(n)??0,p=l*(Re+1)/(l+Re*(1-ze+ze*(t/(this.avgDocLen||1))));r[c]=p*d}return r}dotProduct(e,t){let r=0;for(let a=0;at+r*r,0))}cosineSimilarity(e,t){const r=this.magnitude(e),a=this.magnitude(t);return r===0||a===0?0:this.dotProduct(e,t)/(r*a)}search(e,t={}){const{topK:r=10,minScore:a=.01,expandQuery:n=!0,correctTypos:l=!0,feedbackBoosts:c={}}=t;if(this.docs.length===0)return[];let d=V(Y(e));const p=[];if(l){const{corrected:f,corrections:j}=this.correctQueryTerms(d);d=f,p.push(...j)}let m=d,v=null;if(n&&(v=this.expandQuery(d.join(" ")),m=v.expandedTerms),m.length===0)return[];const w=this.buildVector(m,m.length),y=this.magnitude(w),b=[];for(let f=0;f0),kH.includes(T)),N=this._buildExplanation(k,M,d,v,p.filter(T=>T.wasCorreected),$,O);b.push({document:{id:j.id,text:j.text,metadata:j.metadata},score:k,explanation:N,matchedTerms:M,feedbackBoosted:$})}return b.sort((f,j)=>j.score-f.score),b.slice(0,r)}_buildExplanation(e,t,r,a,n,l,c){const d=[],p=Math.round(e*100);if(p>=80?d.push(`Very high relevance (${p}%)`):p>=50?d.push(`Good relevance (${p}%)`):p>=20?d.push(`Moderate relevance (${p}%)`):d.push(`Low relevance (${p}%)`),t.length>0?d.push(`Matched: ${t.slice(0,5).join(", ")}`):d.push("No direct term matches"),a){const m=Object.entries(a.synonymsUsed).filter(([v])=>r.includes(v)).map(([v,w])=>`${v} → ${w.slice(0,2).join("/")}`).slice(0,2);m.length>0&&d.push(`Synonyms expanded: ${m.join("; ")}`)}if(n.length>0){const m=n.map(v=>`"${v.original}" → "${v.corrected}"`).join(", ");d.push(`Typo corrected: ${m}`)}return l?d.push(`Boosted by your feedback (+${Math.round(c*100)}%)`):c<0&&d.push(`Demoted by your feedback (${Math.round(c*100)}%)`),d.join(" • ")}compareQueries(e,t){const r=V(Y(e)),a=V(Y(t)),n=this.buildVector(r,r.length),l=this.buildVector(a,a.length);return this.cosineSimilarity(n,l)}getSuggestions(e,t=8){const r=e.toLowerCase().trim();if(r.length<2)return[];const a=new Set;for(const n of this.vocab)if(n.startsWith(r)&&n!==r&&a.add(n),a.size>=t)break;for(const[n,l]of Object.entries(he)){n.startsWith(r)&&a.add(n);for(const c of l)c.startsWith(r)&&a.add(c)}return Array.from(a).slice(0,t)}}const Ne="stellar-relevance-feedback-v1";function St(){try{if(typeof localStorage>"u")return new Map;const o=localStorage.getItem(Ne);if(!o)return new Map;const e=JSON.parse(o);return new Map(e.map(t=>[`${t.queryId}::${t.documentId}`,t]))}catch{return new Map}}function ae(o){try{if(typeof localStorage>"u")return;const e=Array.from(o.values());localStorage.setItem(Ne,JSON.stringify(e))}catch{}}function ge(o,e){return`${o}::${e}`}function ye(o){const e=o.thumbsUp*2+o.clicks-o.thumbsDown*2;return Math.tanh(e/5)}class jt{constructor(){P(this,"store");this.store=St()}record(e,t,r){const a=ge(e,t),n=this.store.get(a)??{queryId:e,documentId:t,clicks:0,thumbsUp:0,thumbsDown:0,lastUpdated:0};switch(r){case"click":n.clicks+=1;break;case"thumbsUp":n.thumbsUp+=1,n.thumbsDown=Math.max(0,n.thumbsDown-1);break;case"thumbsDown":n.thumbsDown+=1,n.thumbsUp=Math.max(0,n.thumbsUp-1);break}n.lastUpdated=Date.now(),this.store.set(a,n),ae(this.store)}getRelevanceBoost(e,t){const r=ge(e,t),a=this.store.get(r);return a?ye(a):0}getBoostsForQuery(e){const t={};for(const r of this.store.values())if(r.queryId===e){const a=ye(r);a!==0&&(t[r.documentId]=a)}return t}getEntry(e,t){return this.store.get(ge(e,t))??null}getStats(){let e=0,t=0,r=0;const a=new Map;for(const l of this.store.values()){e+=l.clicks,t+=l.thumbsUp,r+=l.thumbsDown;const c=ye(l),d=a.get(l.documentId)??0;a.set(l.documentId,Math.max(d,c))}const n=Array.from(a.entries()).map(([l,c])=>({documentId:l,boost:c})).sort((l,c)=>c.boost-l.boost).slice(0,10);return{totalEntries:this.store.size,totalClicks:e,totalThumbsUp:t,totalThumbsDown:r,topDocuments:n}}clearDocument(e){for(const t of Array.from(this.store.keys()))t.endsWith(`::${e}`)&&this.store.delete(t);ae(this.store)}clearQuery(e){for(const t of Array.from(this.store.keys()))t.startsWith(`${e}::`)&&this.store.delete(t);ae(this.store)}clearAll(){this.store.clear(),ae(this.store)}pruneOld(e=90){const t=Date.now()-e*864e5;let r=0;for(const[a,n]of Array.from(this.store.entries()))n.lastUpdated0&&ae(this.store),r}}const wt=new jt;function Ae(o){return o.toLowerCase().trim().replace(/\s+/g," ")}function Ct(o,e){const t=e.toLowerCase().split(/\s+/).filter(Boolean);return t.length===0?0:o.filter(r=>t.every(a=>r.text.toLowerCase().includes(a))).length}function kt({documents:o,initialQuery:e="",searchOptions:t={},feedbackStore:r=wt,debounceMs:a=200,enableImprovementMetric:n=!0}){const l=h.useRef(new bt),[c,d]=h.useState(e),[p,m]=h.useState([]),[v,w]=h.useState(!1),[y,b]=h.useState([]),[f,j]=h.useState(null),[H,U]=h.useState(null),[k,O]=h.useState([]),[$,M]=h.useState(0),N=h.useMemo(()=>Ae(c),[c]);h.useEffect(()=>{const R=l.current;R.clearIndex(),o.length>0&&R.indexDocuments(o),M(R.getIndexSize()),c.trim()&&B(c,R)},[o]);const T=h.useRef(null),B=h.useCallback((R,z)=>{const L=R.trim();if(!L){m([]),b([]),j(null),U(null),O([]),w(!1);return}w(!0);const S=Ae(R),F=r.getBoostsForQuery(S),C={topK:20,minScore:.01,expandQuery:!0,correctTypos:!0,applyFeedback:!0,...t,feedbackBoosts:F},ee=z.search(L,C),g=L.toLowerCase().split(/\s+/).filter(Boolean),{corrections:D}=z.correctQueryTerms(g),se=D.filter(X=>X.wasCorreected),fe=z.expandQuery(L);let W=null;if(n&&o.length>0){const X=Ct(o,L),Q=ee.reduce((te,re)=>te+re.score,0);X>0&&Q>0?W=Math.min(1,Q/X):X===0&&ee.length>0?W=1:W=0}const oe=z.getSuggestions(L,8);m(ee),b(se),j(fe),U(W),O(oe),w(!1)},[r,n,o,JSON.stringify(t)]);h.useEffect(()=>(T.current&&clearTimeout(T.current),T.current=setTimeout(()=>{B(c,l.current)},a),()=>{T.current&&clearTimeout(T.current)}),[c,B,a]);const q=h.useCallback((R,z)=>{r.record(N,R,z),B(c,l.current)},[r,N,c,B]);return{query:c,setQuery:d,results:p,loading:v,typoCorrections:y,queryExpansion:f,relevanceImprovement:H,recordFeedback:q,indexSize:$,suggestions:k,queryId:N}}function de(o){return o>=.7?"var(--green, #22c55e)":o>=.4?"var(--cyan, #06b6d4)":o>=.2?"var(--orange, #f97316)":"var(--text-muted, #6b7280)"}function Tt(o){return o>=.7?"Excellent":o>=.4?"Good":o>=.2?"Fair":"Low"}function Ie(o,e){return o.length>e?o.slice(0,e)+"…":o}function Rt({text:o,terms:e}){if(!e.length)return s.jsx(s.Fragment,{children:o});const t=e.filter(Boolean).map(n=>n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")).join("|");if(!t)return s.jsx(s.Fragment,{children:o});const r=new RegExp(`(${t})`,"gi"),a=o.split(r);return s.jsx(s.Fragment,{children:a.map((n,l)=>r.test(n)?s.jsx("mark",{style:{background:"rgba(6, 182, 212, 0.25)",color:"var(--cyan, #06b6d4)",borderRadius:"2px",padding:"0 1px"},children:n},l):s.jsx(Xe.Fragment,{children:n},l))})}function zt({result:o,queryTerms:e,onFeedback:t,onSelect:r}){const[a,n]=h.useState(!1),[l,c]=h.useState(null),{document:d,score:p,explanation:m,matchedTerms:v,feedbackBoosted:w}=o,y=f=>{c(f),t(d.id,f)},b=()=>{t(d.id,"click"),r?.(o)};return s.jsxs("div",{style:{background:"var(--bg-elevated)",border:`1px solid ${w?"var(--cyan, #06b6d4)":"var(--border)"}`,borderRadius:"var(--radius-md)",overflow:"hidden",transition:"border-color 0.2s"},children:[s.jsxs("div",{onClick:b,style:{padding:"12px 16px",cursor:"pointer",display:"flex",alignItems:"flex-start",gap:"12px"},role:"button",tabIndex:0,onKeyDown:f=>f.key==="Enter"&&b(),"aria-label":`Result: ${Ie(d.text,60)}, relevance ${Math.round(p*100)}%`,children:[s.jsxs("div",{style:{flexShrink:0,display:"flex",flexDirection:"column",alignItems:"center",gap:"2px",minWidth:"44px"},children:[s.jsxs("div",{style:{width:"40px",height:"40px",borderRadius:"50%",border:`2px solid ${de(p)}`,display:"flex",alignItems:"center",justifyContent:"center",fontSize:"11px",fontWeight:700,fontFamily:"var(--font-mono)",color:de(p)},title:`Relevance: ${Math.round(p*100)}%`,children:[Math.round(p*100),"%"]}),s.jsx("span",{style:{fontSize:"9px",color:de(p),fontWeight:600},children:Tt(p)})]}),s.jsxs("div",{style:{flex:1,minWidth:0},children:[s.jsx("div",{style:{fontSize:"13px",color:"var(--text-primary)",lineHeight:1.5,marginBottom:"4px"},children:s.jsx(Rt,{text:Ie(d.text,160),terms:v})}),d.metadata&&Object.keys(d.metadata).length>0&&s.jsx("div",{style:{display:"flex",flexWrap:"wrap",gap:"4px",marginBottom:"4px"},children:Object.entries(d.metadata).slice(0,3).map(([f,j])=>s.jsxs("span",{style:{padding:"1px 6px",background:"var(--bg-card)",border:"1px solid var(--border)",borderRadius:"999px",fontSize:"10px",color:"var(--text-muted)",fontFamily:"var(--font-mono)"},children:[f,": ",String(j).slice(0,20)]},f))}),v.length>0&&s.jsx("div",{style:{display:"flex",flexWrap:"wrap",gap:"4px"},children:v.slice(0,6).map(f=>s.jsx("span",{style:{padding:"1px 6px",background:"rgba(6, 182, 212, 0.1)",border:"1px solid rgba(6, 182, 212, 0.3)",borderRadius:"999px",fontSize:"10px",color:"var(--cyan, #06b6d4)"},children:f},f))})]}),s.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:"4px",flexShrink:0},children:[w&&s.jsx("div",{title:"Boosted by your feedback",style:{color:"var(--cyan, #06b6d4)"},children:s.jsx(De,{size:14})}),s.jsx("button",{onClick:f=>{f.stopPropagation(),n(j=>!j)},style:xe,title:a?"Hide explanation":"Why this result?","aria-expanded":a,"aria-label":"Toggle explanation",children:s.jsx(Ve,{size:13})}),s.jsx("button",{onClick:f=>{f.stopPropagation(),y("thumbsUp")},style:{...xe,...l==="thumbsUp"?{background:"rgba(34, 197, 94, 0.2)",borderColor:"var(--green, #22c55e)",color:"var(--green, #22c55e)"}:{}},title:"This result is relevant","aria-label":"Mark as relevant","aria-pressed":l==="thumbsUp",children:s.jsx(Je,{size:13})}),s.jsx("button",{onClick:f=>{f.stopPropagation(),y("thumbsDown")},style:{...xe,...l==="thumbsDown"?{background:"rgba(239, 68, 68, 0.2)",borderColor:"var(--red, #ef4444)",color:"var(--red, #ef4444)"}:{}},title:"This result is not relevant","aria-label":"Mark as not relevant","aria-pressed":l==="thumbsDown",children:s.jsx(Ze,{size:13})})]})]}),s.jsx("div",{style:{height:"3px",background:"var(--border)"},children:s.jsx("div",{style:{height:"100%",width:`${Math.round(p*100)}%`,background:de(p),transition:"width 0.4s ease"}})}),a&&s.jsxs("div",{style:{padding:"10px 16px",borderTop:"1px solid var(--border)",background:"var(--bg-card)",fontSize:"12px",color:"var(--text-muted)",lineHeight:1.6},children:[s.jsxs("div",{style:{display:"flex",alignItems:"flex-start",gap:"6px"},children:[s.jsx(et,{size:13,style:{color:"var(--cyan, #06b6d4)",flexShrink:0,marginTop:"2px"}}),s.jsx("span",{children:m})]}),s.jsxs("div",{style:{marginTop:"6px",fontFamily:"var(--font-mono)",fontSize:"10px",color:"var(--text-muted)",opacity:.6},children:["doc id: ",d.id]})]})]})}function At({documents:o,className:e,onResultSelect:t,title:r="Semantic Search",placeholder:a='Search with natural language (e.g. "recent XLM payments", "failed contracts")…'}){const[n,l]=h.useState(""),[c,d]=h.useState(!1),p=h.useRef(null),{query:m,setQuery:v,results:w,loading:y,typoCorrections:b,queryExpansion:f,relevanceImprovement:j,recordFeedback:H,indexSize:U,suggestions:k}=kt({documents:o,enableImprovementMetric:!0}),O=S=>{const F=S.target.value;l(F),v(F),d(F.length>=2)},$=S=>{l(S),v(S),d(!1),p.current?.focus()},M=()=>{l(""),v(""),d(!1),p.current?.focus()},N=h.useCallback((S,F)=>{H(S,F)},[H]),T=m.toLowerCase().split(/\s+/).filter(S=>S.length>=2),B=f?Object.entries(f.synonymsUsed).filter(([S])=>f.originalTerms.includes(S)).map(([S,F])=>`${S} → ${F.slice(0,2).join("/")}`).slice(0,3):[],q=w.length>0,R=m.trim().length>0,z=j!==null?Math.round(j*100):null,L=z!==null&&z>=40;return s.jsxs("div",{className:e,style:{display:"flex",flexDirection:"column",gap:"16px"},role:"search","aria-label":r,children:[s.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between"},children:[s.jsxs("div",{children:[s.jsxs("div",{style:{fontFamily:"var(--font-display)",fontSize:"18px",fontWeight:700,display:"flex",alignItems:"center",gap:"8px"},children:[s.jsx(pe,{size:18,style:{color:"var(--cyan, #06b6d4)"}}),r]}),s.jsxs("div",{style:{fontSize:"12px",color:"var(--text-muted)",marginTop:"2px"},children:["AI-powered semantic search • ",U," documents indexed"]})]}),z!==null&&q&&s.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"5px",padding:"4px 10px",background:L?"rgba(34, 197, 94, 0.1)":"rgba(249, 115, 22, 0.1)",border:`1px solid ${L?"rgba(34, 197, 94, 0.4)":"rgba(249, 115, 22, 0.4)"}`,borderRadius:"999px",fontSize:"11px",color:L?"var(--green, #22c55e)":"var(--orange, #f97316)",fontWeight:600},title:`Semantic search scores ${z}% relevance improvement over keyword-only search`,children:[s.jsx(De,{size:12}),z,"% relevance improvement"]})]}),s.jsxs("div",{style:{position:"relative"},children:[s.jsxs("div",{style:{position:"relative"},children:[s.jsx(Z,{size:16,style:{position:"absolute",left:"12px",top:"50%",transform:"translateY(-50%)",color:"var(--text-muted)",pointerEvents:"none"}}),s.jsx("input",{ref:p,type:"text",value:n,onChange:O,onFocus:()=>n.length>=2&&d(!0),onBlur:()=>setTimeout(()=>d(!1),150),onKeyDown:S=>{S.key==="Escape"&&d(!1)},placeholder:a,"aria-label":"Semantic search query","aria-autocomplete":"list","aria-expanded":c&&k.length>0,style:{width:"100%",padding:"10px 44px 10px 40px",background:"var(--bg-elevated)",border:"1px solid var(--border)",borderRadius:"var(--radius-md)",color:"var(--text-primary)",fontSize:"14px",fontFamily:"var(--font-sans, sans-serif)",outline:"none",boxSizing:"border-box",transition:"border-color 0.2s"}}),s.jsxs("div",{style:{position:"absolute",right:"10px",top:"50%",transform:"translateY(-50%)",display:"flex",alignItems:"center",gap:"4px"},children:[y&&s.jsx(me,{size:14,style:{color:"var(--cyan, #06b6d4)",animation:"spin 1s linear infinite"},"aria-label":"Searching…"}),n&&s.jsx("button",{onClick:M,style:{...xe,width:"24px",height:"24px"},title:"Clear search","aria-label":"Clear search",children:s.jsx(ve,{size:12})})]})]}),c&&k.length>0&&s.jsx("div",{role:"listbox","aria-label":"Search suggestions",style:{position:"absolute",top:"calc(100% + 4px)",left:0,right:0,background:"var(--bg-card)",border:"1px solid var(--border)",borderRadius:"var(--radius-md)",boxShadow:"0 4px 16px rgba(0,0,0,0.12)",zIndex:1e3,overflow:"hidden"},children:k.map((S,F)=>s.jsxs("div",{role:"option","aria-selected":!1,onClick:()=>$(S),style:{padding:"8px 14px",cursor:"pointer",fontSize:"13px",color:"var(--text-primary)",borderBottom:FC.currentTarget.style.background="var(--bg-elevated)",onMouseLeave:C=>C.currentTarget.style.background="transparent",children:[s.jsx(Z,{size:11,style:{color:"var(--text-muted)",flexShrink:0}}),S]},F))})]}),R&&s.jsxs("div",{style:{display:"flex",flexWrap:"wrap",gap:"6px",alignItems:"center"},children:[b.length>0&&s.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"5px",padding:"3px 9px",background:"rgba(249, 115, 22, 0.1)",border:"1px solid rgba(249, 115, 22, 0.3)",borderRadius:"999px",fontSize:"11px",color:"var(--orange, #f97316)"},children:[s.jsx(Me,{size:11}),"Corrected:"," ",b.map(S=>`"${S.original}" → "${S.corrected}"`).join(", ")]}),B.length>0&&s.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"5px",padding:"3px 9px",background:"rgba(6, 182, 212, 0.1)",border:"1px solid rgba(6, 182, 212, 0.3)",borderRadius:"999px",fontSize:"11px",color:"var(--cyan, #06b6d4)"},title:"Query expanded with synonyms for better recall",children:[s.jsx(pe,{size:11}),"Expanded: ",B.join("; ")]}),!y&&R&&!q&&s.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"5px",fontSize:"12px",color:"var(--text-muted)"},children:[s.jsx(Ye,{size:12}),"No results found. Try different keywords or check spelling."]})]}),q&&s.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:"8px"},children:[s.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",fontSize:"12px",color:"var(--text-muted)"},children:[s.jsxs("span",{children:[w.length," result",w.length!==1?"s":""," for"," ",s.jsxs("strong",{style:{color:"var(--text-primary)"},children:['"',m,'"']})]}),s.jsx("span",{style:{fontSize:"11px",opacity:.7},children:"Rate results to improve future searches"})]}),w.map(S=>s.jsx(zt,{result:S,queryTerms:T,onFeedback:N,onSelect:t},S.document.id))]}),!R&&s.jsxs("div",{style:{display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",padding:"40px 24px",color:"var(--text-muted)",gap:"10px",textAlign:"center"},children:[s.jsx(pe,{size:32,style:{opacity:.3}}),s.jsx("div",{style:{fontSize:"14px",fontWeight:600},children:"Semantic search understands your intent"}),s.jsxs("div",{style:{fontSize:"12px",opacity:.7,maxWidth:"320px"},children:["Try queries like"," ",s.jsx("em",{children:'"recent XLM transfers"'}),","," ",s.jsx("em",{children:'"failed soroban contracts"'}),", or"," ",s.jsx("em",{children:'"payment from testnet account"'}),". Typos and synonyms are handled automatically."]})]})]})}const xe={display:"flex",alignItems:"center",justifyContent:"center",width:"28px",height:"28px",background:"var(--bg-elevated)",border:"1px solid var(--border)",borderRadius:"var(--radius-md)",color:"var(--text-primary)",cursor:"pointer",transition:"background 0.15s, color 0.15s, border-color 0.15s",flexShrink:0},Se=/\bG[A-Z0-9]{2,55}\b/g,je=/(\d+(?:\.\d+)?)\s*([A-Z]{3,})?/g,It=/\b([A-Z]{3,})\b/g,Ft=["payment","create account","manage offer","set options","change trust","allow trust","account merge","inflation","manage data","bump sequence"],Dt={today:()=>new Date,yesterday:()=>new Date(Date.now()-864e5),"last week":()=>new Date(Date.now()-7*864e5),"last month":()=>new Date(Date.now()-30*864e5)};function Mt(o){let e="general",t=.5;const r=o.toLowerCase(),n=["show me","find","list","look up","search","display"].some(c=>r.includes(c));/(transaction|transactions|payment|payments|transfer|transfers|send|sent)/i.test(r)?(e="transaction",t=.9):/(operation|operations|create account|manage offer|set options|change trust|allow trust)/i.test(r)?(e="operation",t=.84):/(account|accounts|balance|wallet)/i.test(r)?(e="account",t=.85):/(contract|smart contract|invoke)/i.test(r)&&(e="contract",t=.88),n&&e==="general"&&(t=.6);const l=_t(o);return{type:e,entities:l,query:o,confidence:t}}function _t(o){const e={},t=o.match(Se);t&&t.length>0&&(e.addresses=[...new Set(t)]);const r=[];let a;const n=new RegExp(je);for(;(a=n.exec(o))!==null;)r.push(parseFloat(a[1])),a[2]&&(e.assets=e.assets||[],e.assets.push(a[2]));r.length>0&&(e.amounts=r);const l=o.match(It);l&&(e.assets=[...new Set([...e.assets||[],...l])]);for(const[p,m]of Object.entries(Dt))if(o.toLowerCase().includes(p)){e.dateRanges=e.dateRanges||[],e.dateRanges.push({start:m()});break}const c=Ft.filter(p=>o.toLowerCase().includes(p));c.length>0&&(e.operationTypes=c);const d=o.replace(Se,"").replace(je,"").split(/\s+/).filter(p=>p.length>2&&!["show","me","find","list","look","up","search","display","the","and","for","from","to","all","over","only","those","that","with","last","month","week","today","yesterday"].includes(p.toLowerCase()));return d.length>0&&(e.keywords=[...new Set(d)]),e}function Lt(o,e){const t=Mt(o),r={},a=e?.entities.addresses;a&&a.length>0&&(r.addresses=a),t.entities.addresses&&t.entities.addresses.length>0&&(r.addresses=t.entities.addresses),t.entities.amounts&&t.entities.amounts.length>0&&(r.amounts={min:Math.min(...t.entities.amounts),max:Math.max(...t.entities.amounts)}),t.entities.assets&&(r.assets=t.entities.assets),t.entities.dateRanges&&t.entities.dateRanges.length>0&&(r.dateRange=t.entities.dateRanges[0]),t.entities.operationTypes&&(r.operationTypes=t.entities.operationTypes),t.entities.keywords&&t.entities.keywords.length>0&&(r.keywords=t.entities.keywords);const n=o.replace(Se,"").replace(je,"").split(/\s+/).filter(l=>l.length>2&&!["the","and","for","from","to","show","me","find","list","look","up","search","display","all","over","only","those","that","with","last","month","week","today","yesterday"].includes(l.toLowerCase()));return{filters:r,searchTerms:n,intent:t}}function Et(o,e,t={}){const r=Lt(o,e??void 0),a=`I found a ${r.intent.type} request${r.filters.amounts?" with amount filters":""}${r.filters.dateRange?" and a time window":""}. I can refine it further for ${r.intent.type==="contract"?"contract interactions":"matching Stellar data"}.`,n=[r.intent.type==="transaction"?"Show the matching transactions in a table":"Show the matching results in a table",r.intent.type==="account"?"Summarize the account activity":"Suggest related queries","Export these results as JSON"],l=[r.intent.type==="transaction"?"Filter these to only successful payments":"Narrow the results to a specific account",r.intent.type==="contract"?"Show accounts that interacted with this contract":"Show related operations for these results"];return{parsed:r,summary:a,suggestions:[...new Set(n)].slice(0,3),followUpQuestions:l,resultCount:t.total??0}}function Ot({onSubmit:o,placeholder:e="Ask for payments, accounts, contracts, or operations…",isBusy:t=!1,resultsSummary:r,onExport:a}){const[n,l]=h.useState(""),[c,d]=h.useState([{id:"welcome",role:"assistant",content:"I can help you explore Stellar data with natural language. Try “show me payments over 1000 XLM last month” or “find accounts that interact with contract X”.",suggestions:["Show me payments over 1000 XLM last month","Find accounts that interact with contract X","List failed transactions from last week"]}]),[p,m]=h.useState(null),v=h.useMemo(()=>[...c].reverse().find(y=>y.role==="assistant"),[c]),w=y=>{y.preventDefault();const b=n.trim();if(!b)return;const f=Et(b,p,{total:0}),j=[...c,{id:`${Date.now()}-user`,role:"user",content:b,intent:f.parsed.intent},{id:`${Date.now()}-assistant`,role:"assistant",content:f.summary,intent:f.parsed.intent,suggestions:f.suggestions,followUps:f.followUpQuestions}];d(j),m(f.parsed.intent),o(b,f.parsed,f.parsed.intent),l("")};return s.jsxs("div",{style:{border:"1px solid var(--border)",borderRadius:"var(--radius-lg)",background:"var(--bg-card)",padding:"16px",display:"flex",flexDirection:"column",gap:"12px"},children:[s.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"8px",color:"var(--cyan)"},children:[s.jsx(tt,{size:16}),s.jsx("strong",{style:{fontSize:"13px"},children:"Conversational AI assistant"})]}),s.jsx("div",{style:{display:"flex",flexDirection:"column",gap:"8px",maxHeight:"280px",overflowY:"auto"},children:c.map(y=>s.jsxs("div",{style:{padding:"10px 12px",borderRadius:"10px",background:y.role==="assistant"?"var(--bg-elevated)":"rgba(6, 182, 212, 0.12)",border:y.role==="assistant"?"1px solid var(--border)":"1px solid rgba(6, 182, 212, 0.24)"},children:[s.jsx("div",{style:{fontSize:"11px",fontWeight:700,textTransform:"uppercase",color:"var(--text-muted)",marginBottom:"4px"},children:y.role==="assistant"?"assistant":"you"}),s.jsx("div",{style:{fontSize:"13px",lineHeight:1.5,color:"var(--text-primary)"},children:y.content}),y.intent&&s.jsxs("div",{style:{fontSize:"11px",color:"var(--text-muted)",marginTop:"6px"},children:["Intent: ",s.jsx("strong",{children:y.intent.type})," • confidence ",Math.round(y.intent.confidence*100),"%"]}),y.suggestions&&y.suggestions.length>0&&s.jsx("div",{style:{display:"flex",flexWrap:"wrap",gap:"6px",marginTop:"8px"},children:y.suggestions.slice(0,3).map(b=>s.jsx("button",{type:"button",onClick:()=>{l(b)},style:{border:"1px solid var(--border)",borderRadius:"999px",padding:"4px 8px",background:"var(--bg-card)",cursor:"pointer",fontSize:"11px",color:"var(--text-primary)"},children:b},b))}),y.followUps&&y.followUps.length>0&&s.jsxs("div",{style:{marginTop:"8px"},children:[s.jsx("div",{style:{fontSize:"11px",color:"var(--text-muted)",marginBottom:"4px"},children:"Try next:"}),s.jsx("div",{style:{display:"flex",flexWrap:"wrap",gap:"6px"},children:y.followUps.slice(0,2).map(b=>s.jsx("button",{type:"button",onClick:()=>l(b),style:{border:"1px solid rgba(6, 182, 212, 0.24)",borderRadius:"999px",padding:"4px 8px",background:"rgba(6, 182, 212, 0.12)",cursor:"pointer",fontSize:"11px",color:"var(--cyan)"},children:b},b))})]})]},y.id))}),r&&s.jsx("div",{style:{fontSize:"12px",color:"var(--text-muted)"},children:r}),s.jsxs("form",{onSubmit:w,style:{display:"flex",gap:"8px"},children:[s.jsx("input",{value:n,onChange:y=>l(y.target.value),placeholder:e,style:{flex:1,padding:"10px 12px",border:"1px solid var(--border)",borderRadius:"10px",background:"var(--bg-elevated)",color:"var(--text-primary)"}}),s.jsx("button",{type:"submit",disabled:t,style:{border:"none",borderRadius:"10px",padding:"10px 12px",background:"var(--cyan)",color:"white",cursor:t?"wait":"pointer",display:"inline-flex",alignItems:"center",gap:"6px"},children:t?"Working…":s.jsxs(s.Fragment,{children:[s.jsx(st,{size:14})," Ask"]})})]}),s.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",gap:"10px"},children:[s.jsx("div",{style:{fontSize:"11px",color:"var(--text-muted)"},children:v?.intent?`Last intent: ${v.intent.type}`:"Ask a question to refine the results."}),a&&s.jsxs("button",{type:"button",onClick:a,style:{border:"1px solid var(--border)",borderRadius:"999px",padding:"6px 10px",background:"var(--bg-elevated)",cursor:"pointer",display:"inline-flex",alignItems:"center",gap:"6px",fontSize:"12px",color:"var(--text-primary)"},children:[s.jsx(_e,{size:13})," Export"]})]})]})}function Xt(){const[o,e]=h.useState(""),[t,r]=h.useState(null),[a,n]=h.useState(!1),[l,c]=h.useState(!1),[d,p]=h.useState(!1),[m,v]=h.useState([]),[w,y]=h.useState([]),[b,f]=h.useState(null),[j,H]=h.useState([]),[U,k]=h.useState([]),[O,$]=h.useState(!1),[M,N]=h.useState(["transactions","operations","contracts","accounts"]),[T,B]=h.useState("General"),[q,R]=h.useState(!1),[z,L]=h.useState("0 * * * *"),[S,F]=h.useState(""),[C,ee]=h.useState(!1),[g,D]=h.useState({dateRange:{start:"",end:""},assetType:"",operationType:"",amountRange:{min:"",max:""},addressFilter:"",memoFilter:"",statusFilter:"",networkFilter:""}),[se,fe]=h.useState({field:"timestamp",direction:"desc"}),[W,oe]=h.useState({page:1,limit:20}),X=h.useMemo(()=>{const i=[];return I.getSearchHistory().slice(0,30).forEach((x,A)=>{const Te=x.query?.text;Te&&i.push({id:`history-${A}`,text:Te,metadata:{type:"search_history",resultCount:x.resultCount??0,timestamp:x.timestamp??""}})}),I.getSavedSearches().forEach(x=>{const A=x.query?.text;A&&i.push({id:`saved-${x.id}`,text:`${x.name} ${A}`,metadata:{type:"saved_search",name:x.name,folder:x.folder??"General"}})}),t?.results&&t.results.forEach(x=>{const A=[x.type,x.operationType,x.asset,x.memo,x.status,x.address,x.transactionHash].filter(Boolean).join(" ");A.trim()&&i.push({id:`result-${x.id}`,text:A,metadata:{type:x.type,status:x.status??"",amount:x.amount??""}})}),i},[t]);h.useEffect(()=>{Q()},[]),h.useEffect(()=>{if(o.length>1){const i=I.getSuggestions(o);k(i),$(!0)}else k([]),$(!1)},[o]);const Q=()=>{v(I.getSavedSearches()),y(I.getSavedSearchFolders()),H(I.getSearchHistory()),f(I.getSearchAnalytics())},te=async i=>{const u=(i??o).trim();if(!(!u&&!we())){n(!0);try{const x={text:u,types:M,filters:re(),sort:se,page:W.page,limit:W.limit},A=I.search(x);r(A),i&&e(u),ie.logUserAction("Performed advanced search",{query:u,types:M,resultCount:A.total,searchTime:A.searchTime}),Q()}catch(x){ie.logError(x,{operation:"advancedSearch",query:u}),console.error("Search failed:",x)}finally{n(!1)}}},re=()=>{const i={};return g.dateRange.start&&(i.dateRange={...i.dateRange,start:new Date(g.dateRange.start).getTime()}),g.dateRange.end&&(i.dateRange={...i.dateRange,end:new Date(g.dateRange.end).getTime()}),g.assetType&&(i.assetType=g.assetType),g.operationType&&(i.operationType=g.operationType),g.addressFilter&&(i.addressFilter=g.addressFilter),g.memoFilter&&(i.memoFilter=g.memoFilter),g.statusFilter&&(i.statusFilter=g.statusFilter),g.networkFilter&&(i.networkFilter=g.networkFilter),g.amountRange.min&&(i.amountRange={...i.amountRange,min:parseFloat(g.amountRange.min)}),g.amountRange.max&&(i.amountRange={...i.amountRange,max:parseFloat(g.amountRange.max)}),i},we=()=>Object.values(g).some(i=>typeof i=="object"&&i!==null?Object.values(i).some(u=>u!==""):i!==""),Ce=()=>{D({dateRange:{start:"",end:""},assetType:"",operationType:"",amountRange:{min:"",max:""},addressFilter:"",memoFilter:"",statusFilter:"",networkFilter:""}),I.resetFilters()},qe=()=>{const i=prompt("Enter a name for this search:");if(i){const u={text:o.trim(),types:M,filters:re(),sort:se},x=I.saveSearch(i,u,{folder:T});q&&I.createSearchAlert({savedSearchId:x.id,name:`${i} alert`,cron:z,channels:["in-app"]}),Q(),ie.logUserAction("Saved search",{name:i,query:u})}},Ue=i=>{const u=I.loadSavedSearch(i.id)||i;e(u.query.text||""),N(u.query.types||["transactions","operations"]),Ce(),u.query.filters&&D({...g,...u.query.filters}),u.query.sort&&fe(u.query.sort),p(!1),Q(),te()},We=(i,u)=>{i.stopPropagation();const x=I.shareSearch(u.id);F(x),Q()},ke=()=>{if(!t)return;const i=JSON.stringify(t,null,2),u=new Blob([i],{type:"application/json"}),x=URL.createObjectURL(u),A=document.createElement("a");A.href=x,A.download=`stellar-search-results-${Date.now()}.json`,A.click(),URL.revokeObjectURL(x),ie.logUserAction("Exported search results",{resultCount:t.total})},Qe=i=>{e(i),$(!1)},Pe=i=>{N(u=>u.includes(i)?u.filter(x=>x!==i):[...u,i])};return s.jsxs("div",{className:"animate-in",style:{display:"flex",flexDirection:"column",gap:"24px"},children:[s.jsxs("div",{children:[s.jsxs("div",{style:{fontFamily:"var(--font-display)",fontSize:"22px",fontWeight:700,display:"flex",alignItems:"center",gap:"10px"},children:[s.jsx(Z,{size:22,style:{color:"var(--cyan)"}}),"Advanced Search"]}),s.jsx("div",{style:{fontSize:"13px",color:"var(--text-muted)",marginTop:"4px"},children:"Global search across transactions, operations, contracts, and accounts"})]}),s.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"8px"},children:[s.jsxs("button",{onClick:()=>ee(!1),style:{padding:"6px 14px",borderRadius:"999px",border:`1px solid ${C?"var(--border)":"var(--cyan)"}`,background:C?"var(--bg-elevated)":"rgba(6, 182, 212, 0.12)",color:C?"var(--text-muted)":"var(--cyan)",fontSize:"12px",fontWeight:600,cursor:"pointer",display:"flex",alignItems:"center",gap:"5px",transition:"all 0.15s"},children:[s.jsx(Z,{size:12})," Keyword Search"]}),s.jsxs("button",{onClick:()=>ee(!0),style:{padding:"6px 14px",borderRadius:"999px",border:`1px solid ${C?"var(--cyan)":"var(--border)"}`,background:C?"rgba(6, 182, 212, 0.12)":"var(--bg-elevated)",color:C?"var(--cyan)":"var(--text-muted)",fontSize:"12px",fontWeight:600,cursor:"pointer",display:"flex",alignItems:"center",gap:"5px",transition:"all 0.15s"},children:[s.jsx(pe,{size:12})," Semantic Search",s.jsx("span",{style:{padding:"1px 5px",background:"rgba(6,182,212,0.2)",borderRadius:"999px",fontSize:"9px",fontWeight:700,letterSpacing:"0.3px",color:"var(--cyan)"},children:"AI"})]}),C&&s.jsx("span",{style:{fontSize:"11px",color:"var(--text-muted)",marginLeft:"4px"},children:"Understands synonyms, typos, and intent. Rate results to improve ranking."})]}),C&&s.jsx("div",{style:{background:"var(--bg-card)",border:"1px solid var(--border)",borderRadius:"var(--radius-lg)",padding:"20px"},children:s.jsx(At,{documents:X,title:"AI Semantic Search",placeholder:"Try 'recent XLM payments', 'failed soroban contracts', 'testnet account'…"})}),!C&&s.jsx(Ot,{onSubmit:(i,u)=>{e(i);const x={text:i,types:M,filters:{...re(),...u.filters.addresses?{addressFilter:u.filters.addresses[0]}:{},...u.filters.amounts?{amountRange:{min:u.filters.amounts.min?.toString()??"",max:u.filters.amounts.max?.toString()??""}}:{}},sort:se,page:W.page,limit:W.limit};r(I.search(x)),Q()},placeholder:"Ask for payments, accounts, contracts, or operations",isBusy:a,resultsSummary:t?`${t.total??0} results ready for review.`:void 0,onExport:()=>ke()}),!C&&s.jsxs("div",{style:{background:"var(--bg-card)",border:"1px solid var(--border)",borderRadius:"var(--radius-lg)",padding:"20px"},children:[s.jsxs("div",{style:{position:"relative",marginBottom:"16px"},children:[s.jsx(Z,{size:16,style:{position:"absolute",left:"12px",top:"50%",transform:"translateY(-50%)",color:"var(--text-muted)"}}),s.jsx("input",{type:"text",value:o,onChange:i=>e(i.target.value),onKeyPress:i=>i.key==="Enter"&&te(),placeholder:"Search transactions, operations, contracts, accounts...",style:{..._,paddingLeft:"40px",paddingRight:"120px",fontSize:"14px"}}),s.jsxs("div",{style:{position:"absolute",right:"8px",top:"50%",transform:"translateY(-50%)",display:"flex",gap:"4px"},children:[s.jsx("button",{onClick:()=>p(!d),style:{...J,title:"Search History"},children:s.jsx(rt,{size:14})}),s.jsx("button",{onClick:qe,style:{...J,title:"Save Search"},children:s.jsx(at,{size:14})}),s.jsx("button",{onClick:te,disabled:a,style:{...J,background:"var(--cyan)",color:"white",title:"Search"},children:a?s.jsx(me,{size:14,className:"animate-spin"}):s.jsx(Z,{size:14})})]}),O&&U.length>0&&s.jsx("div",{style:{position:"absolute",top:"100%",left:0,right:0,background:"var(--bg-elevated)",border:"1px solid var(--border)",borderTop:"none",borderRadius:"0 0 var(--radius-md) var(--radius-md)",maxHeight:"200px",overflowY:"auto",zIndex:10},children:U.map((i,u)=>s.jsx("div",{onClick:()=>Qe(i),style:{padding:"8px 12px",cursor:"pointer",fontSize:"13px",color:"var(--text-primary)",borderBottom:"1px solid var(--border)"},onMouseEnter:x=>x.target.style.background="var(--bg-card)",onMouseLeave:x=>x.target.style.background="transparent",children:i},u))})]}),s.jsxs("div",{style:{marginBottom:"16px"},children:[s.jsx("div",{style:{fontSize:"12px",color:"var(--text-muted)",marginBottom:"8px"},children:"Search in:"}),s.jsx("div",{style:{display:"flex",gap:"8px",flexWrap:"wrap"},children:["transactions","operations","contracts","accounts"].map(i=>s.jsx("button",{onClick:()=>Pe(i),style:{...Bt,background:M.includes(i)?"var(--cyan)":"var(--bg-elevated)",color:M.includes(i)?"white":"var(--text-primary)"},children:i},i))})]}),s.jsxs("div",{style:{display:"grid",gridTemplateColumns:"repeat(auto-fit, minmax(180px, 1fr))",gap:"10px",marginBottom:"16px"},children:[s.jsxs("label",{style:{display:"flex",flexDirection:"column",gap:"6px",fontSize:"12px",color:"var(--text-muted)"},children:[s.jsxs("span",{style:{display:"inline-flex",alignItems:"center",gap:"5px"},children:[s.jsx(nt,{size:12})," Save folder"]}),s.jsx("input",{value:T,onChange:i=>B(i.target.value),style:{..._,fontSize:"12px"}})]}),s.jsxs("label",{style:{display:"flex",flexDirection:"column",gap:"6px",fontSize:"12px",color:"var(--text-muted)"},children:[s.jsxs("span",{style:{display:"inline-flex",alignItems:"center",gap:"5px"},children:[s.jsx(ot,{size:12})," Alert schedule"]}),s.jsx("input",{value:z,onChange:i=>L(i.target.value),disabled:!q,style:{..._,fontSize:"12px",opacity:q?1:.55}})]}),s.jsxs("label",{style:{display:"flex",alignItems:"center",gap:"8px",fontSize:"12px",color:"var(--text-secondary)",alignSelf:"end",minHeight:"34px"},children:[s.jsx("input",{type:"checkbox",checked:q,onChange:i=>R(i.target.checked)}),"Create alert when saved"]})]}),s.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center"},children:[s.jsxs("button",{onClick:()=>c(!l),style:{display:"inline-flex",alignItems:"center",gap:"6px",padding:"8px 12px",background:"var(--bg-elevated)",border:"1px solid var(--border)",borderRadius:"var(--radius-md)",color:"var(--text-primary)",fontSize:"12px",cursor:"pointer"},children:[s.jsx(it,{size:14}),l?"Hide Filters":"Show Filters",l?s.jsx(Le,{size:14}):s.jsx(Ee,{size:14})]}),we()&&s.jsxs("button",{onClick:Ce,style:{display:"inline-flex",alignItems:"center",gap:"6px",padding:"8px 12px",background:"rgba(239, 68, 68, 0.1)",border:"1px solid var(--red)",borderRadius:"var(--radius-md)",color:"var(--red)",fontSize:"12px",cursor:"pointer"},children:[s.jsx(ve,{size:14}),"Clear Filters"]})]}),l&&s.jsx("div",{style:{marginTop:"16px",padding:"16px",background:"var(--bg-elevated)",borderRadius:"var(--radius-md)",border:"1px solid var(--border)"},children:s.jsxs("div",{style:{display:"grid",gridTemplateColumns:"repeat(auto-fit, minmax(200px, 1fr))",gap:"16px"},children:[s.jsxs("div",{children:[s.jsxs("label",{style:G,children:[s.jsx(lt,{size:12,style:{marginRight:"4px"}}),"Date Range"]}),s.jsxs("div",{style:{display:"flex",gap:"8px"},children:[s.jsx("input",{type:"date",value:g.dateRange.start,onChange:i=>D(u=>({...u,dateRange:{...u.dateRange,start:i.target.value}})),style:{..._,fontSize:"12px"}}),s.jsx("input",{type:"date",value:g.dateRange.end,onChange:i=>D(u=>({...u,dateRange:{...u.dateRange,end:i.target.value}})),style:{..._,fontSize:"12px"}})]})]}),s.jsxs("div",{children:[s.jsxs("label",{style:G,children:[s.jsx(ct,{size:12,style:{marginRight:"4px"}}),"Asset Type"]}),s.jsxs("select",{value:g.assetType,onChange:i=>D(u=>({...u,assetType:i.target.value})),style:{..._,fontSize:"12px"},children:[s.jsx("option",{value:"",children:"All Assets"}),s.jsx("option",{value:"XLM",children:"XLM"}),s.jsx("option",{value:"USDC",children:"USDC"}),s.jsx("option",{value:"BTC",children:"BTC"}),s.jsx("option",{value:"ETH",children:"ETH"}),s.jsx("option",{value:"USDT",children:"USDT"})]})]}),s.jsxs("div",{children:[s.jsxs("label",{style:G,children:[s.jsx(Oe,{size:12,style:{marginRight:"4px"}}),"Operation Type"]}),s.jsxs("select",{value:g.operationType,onChange:i=>D(u=>({...u,operationType:i.target.value})),style:{..._,fontSize:"12px"},children:[s.jsx("option",{value:"",children:"All Operations"}),s.jsx("option",{value:"payment",children:"Payment"}),s.jsx("option",{value:"create_account",children:"Create Account"}),s.jsx("option",{value:"manage_offer",children:"Manage Offer"}),s.jsx("option",{value:"set_options",children:"Set Options"}),s.jsx("option",{value:"change_trust",children:"Change Trust"})]})]}),s.jsxs("div",{children:[s.jsxs("label",{style:G,children:[s.jsx(dt,{size:12,style:{marginRight:"4px"}}),"Amount Range"]}),s.jsxs("div",{style:{display:"flex",gap:"8px"},children:[s.jsx("input",{type:"number",placeholder:"Min",value:g.amountRange.min,onChange:i=>D(u=>({...u,amountRange:{...u.amountRange,min:i.target.value}})),style:{..._,fontSize:"12px"}}),s.jsx("input",{type:"number",placeholder:"Max",value:g.amountRange.max,onChange:i=>D(u=>({...u,amountRange:{...u.amountRange,max:i.target.value}})),style:{..._,fontSize:"12px"}})]})]}),s.jsxs("div",{children:[s.jsxs("label",{style:G,children:[s.jsx($e,{size:12,style:{marginRight:"4px"}}),"Address Filter"]}),s.jsx("input",{type:"text",placeholder:"Account address...",value:g.addressFilter,onChange:i=>D(u=>({...u,addressFilter:i.target.value})),style:{..._,fontSize:"12px"}})]}),s.jsxs("div",{children:[s.jsxs("label",{style:G,children:[s.jsx(Be,{size:12,style:{marginRight:"4px"}}),"Memo Filter"]}),s.jsx("input",{type:"text",placeholder:"Memo text...",value:g.memoFilter,onChange:i=>D(u=>({...u,memoFilter:i.target.value})),style:{..._,fontSize:"12px"}})]}),s.jsxs("div",{children:[s.jsxs("label",{style:G,children:[s.jsx(Me,{size:12,style:{marginRight:"4px"}}),"Status"]}),s.jsxs("select",{value:g.statusFilter,onChange:i=>D(u=>({...u,statusFilter:i.target.value})),style:{..._,fontSize:"12px"},children:[s.jsx("option",{value:"",children:"All Status"}),s.jsx("option",{value:"success",children:"Success"}),s.jsx("option",{value:"failed",children:"Failed"}),s.jsx("option",{value:"pending",children:"Pending"})]})]}),s.jsxs("div",{children:[s.jsxs("label",{style:G,children:[s.jsx(He,{size:12,style:{marginRight:"4px"}}),"Network"]}),s.jsxs("select",{value:g.networkFilter,onChange:i=>D(u=>({...u,networkFilter:i.target.value})),style:{..._,fontSize:"12px"},children:[s.jsx("option",{value:"",children:"All Networks"}),s.jsx("option",{value:"mainnet",children:"Mainnet"}),s.jsx("option",{value:"testnet",children:"Testnet"}),s.jsx("option",{value:"futurenet",children:"Futurenet"})]})]})]})})]}),d&&s.jsxs("div",{style:{background:"var(--bg-card)",border:"1px solid var(--border)",borderRadius:"var(--radius-lg)",padding:"16px"},children:[s.jsxs("div",{style:{fontSize:"14px",fontWeight:600,marginBottom:"12px",display:"flex",justifyContent:"space-between",alignItems:"center"},children:[s.jsx("span",{children:"Search History & Saved Searches"}),s.jsx("button",{onClick:()=>p(!1),style:J,children:s.jsx(ve,{size:14})})]}),b&&s.jsxs("div",{style:{display:"flex",gap:"8px",flexWrap:"wrap",marginBottom:"12px"},children:[s.jsx(AnalyticsChip,{label:"Searches",value:b.totalSearches}),s.jsx(AnalyticsChip,{label:"Cache hits",value:b.cachedSearches}),s.jsx(AnalyticsChip,{label:"Saved",value:b.savedSearches}),s.jsx(AnalyticsChip,{label:"Alerts",value:b.alerts})]}),s.jsxs("div",{style:{display:"grid",gridTemplateColumns:"repeat(auto-fit, minmax(300px, 1fr))",gap:"16px"},children:[s.jsxs("div",{children:[s.jsx("div",{style:{fontSize:"12px",color:"var(--text-muted)",marginBottom:"8px"},children:"Folders"}),s.jsx("div",{style:{display:"flex",flexDirection:"column",gap:"8px"},children:w.map(i=>s.jsxs("button",{onClick:()=>{B(i.name),v(I.getSavedSearches({folder:i.name}))},style:{padding:"8px 12px",background:T===i.name?"var(--cyan-glow)":"var(--bg-elevated)",border:`1px solid ${T===i.name?"var(--cyan-dim)":"var(--border)"}`,borderRadius:"var(--radius-md)",cursor:"pointer",fontSize:"12px",color:"var(--text-primary)",display:"flex",justifyContent:"space-between"},children:[s.jsx("span",{children:i.name}),s.jsx("span",{style:{color:"var(--text-muted)"},children:i.count})]},i.id))})]}),s.jsxs("div",{children:[s.jsx("div",{style:{fontSize:"12px",color:"var(--text-muted)",marginBottom:"8px"},children:"Recent Searches"}),s.jsx("div",{style:{display:"flex",flexDirection:"column",gap:"8px"},children:j.slice(0,5).map((i,u)=>s.jsxs("div",{onClick:()=>{e(i.query.text||""),p(!1)},style:{padding:"8px 12px",background:"var(--bg-elevated)",border:"1px solid var(--border)",borderRadius:"var(--radius-md)",cursor:"pointer",fontSize:"12px"},children:[s.jsx("div",{style:{fontWeight:500},children:i.query.text||"Empty search"}),s.jsxs("div",{style:{color:"var(--text-muted)",fontSize:"11px"},children:[ht(new Date(i.timestamp),"MMM dd, HH:mm")," / ",i.resultCount||0," results / ",i.cached?"cached":`${i.searchTime||0}ms`]})]},u))})]}),s.jsxs("div",{children:[s.jsx("div",{style:{fontSize:"12px",color:"var(--text-muted)",marginBottom:"8px"},children:"Saved Searches"}),s.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:"8px"},children:[m.slice(0,5).map((i,u)=>s.jsxs("div",{onClick:()=>Ue(i),style:{padding:"8px 12px",background:"var(--bg-elevated)",border:"1px solid var(--border)",borderRadius:"var(--radius-md)",cursor:"pointer",fontSize:"12px"},children:[s.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",gap:"8px"},children:[s.jsx("div",{style:{fontWeight:500},children:i.name}),s.jsx("button",{onClick:x=>We(x,i),style:{...J,width:"26px",height:"26px"},title:"Share query",children:s.jsx(ut,{size:12})})]}),s.jsxs("div",{style:{color:"var(--text-muted)",fontSize:"11px"},children:[i.folder||"General"," / ",i.query.text||"No query"," / used ",i.usageCount||0,"x"]})]},u)),S&&s.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"8px",padding:"8px 12px",background:"var(--bg-elevated)",border:"1px solid var(--border)",borderRadius:"var(--radius-md)",fontSize:"11px",color:"var(--text-muted)"},children:[s.jsx(pt,{size:12}),s.jsx("span",{style:{overflowWrap:"anywhere"},children:S})]})]})]})]})]}),!C&&t&&s.jsxs("div",{style:{background:"var(--bg-card)",border:"1px solid var(--border)",borderRadius:"var(--radius-lg)",overflow:"hidden"},children:[s.jsxs("div",{style:{padding:"16px 20px",borderBottom:"1px solid var(--border)",display:"flex",justifyContent:"space-between",alignItems:"center"},children:[s.jsxs("div",{children:[s.jsxs("div",{style:{fontSize:"14px",fontWeight:600},children:[t.total," results found"]}),s.jsxs("div",{style:{fontSize:"12px",color:"var(--text-muted)"},children:["Search completed in ",t.searchTime,"ms",t.cached?" from cache":""]}),t.queryPlan&&s.jsxs("div",{style:{fontSize:"11px",color:"var(--text-muted)",marginTop:"4px"},children:[t.queryPlan.usesIndex?"Index-assisted":"Scan"," / ",t.queryPlan.filterCount," filters / cache TTL ",Math.round(t.queryPlan.cacheTtlMs/1e3),"s"]})]}),s.jsxs("div",{style:{display:"flex",gap:"8px"},children:[s.jsx("button",{onClick:ke,style:J,title:"Export Results",children:s.jsx(_e,{size:14})}),s.jsx("button",{onClick:te,style:J,title:"Refresh",children:s.jsx(me,{size:14})})]})]}),t.results.length===0?s.jsx("div",{style:{padding:"48px",textAlign:"center",color:"var(--text-muted)"},children:"No results found for your search criteria."}):s.jsxs("div",{children:[t.aggregations&&s.jsxs("div",{style:{padding:"16px 20px",borderBottom:"1px solid var(--border)"},children:[s.jsx("div",{style:{fontSize:"12px",color:"var(--text-muted)",marginBottom:"8px"},children:"Results Overview"}),s.jsxs("div",{style:{display:"flex",gap:"16px",flexWrap:"wrap"},children:[s.jsx(ue,{label:"Types",data:t.aggregations.typeCounts}),s.jsx(ue,{label:"Operations",data:t.aggregations.operationTypeCounts}),s.jsx(ue,{label:"Assets",data:t.aggregations.assetCounts}),s.jsx(ue,{label:"Status",data:t.aggregations.statusCounts})]})]}),s.jsx("div",{children:t.results.map((i,u)=>s.jsx($t,{result:i},i.id))}),t.totalPages>1&&s.jsxs("div",{style:{padding:"16px 20px",borderTop:"1px solid var(--border)",display:"flex",justifyContent:"center",alignItems:"center",gap:"8px"},children:[s.jsx("button",{onClick:()=>oe(i=>({...i,page:Math.max(1,i.page-1)})),disabled:t.page===1,style:Fe,children:"Previous"}),s.jsxs("span",{style:{fontSize:"12px",color:"var(--text-muted)"},children:["Page ",t.page," of ",t.totalPages]}),s.jsx("button",{onClick:()=>oe(i=>({...i,page:Math.min(t.totalPages,i.page+1)})),disabled:t.page===t.totalPages,style:Fe,children:"Next"})]})]})]})]})}function $t({result:o}){const[e,t]=h.useState(!1),r=n=>({transactions:s.jsx($e,{size:14}),operations:s.jsx(Oe,{size:14}),contracts:s.jsx(Be,{size:14}),accounts:s.jsx(He,{size:14})})[n]||s.jsx(Z,{size:14}),a=n=>({transactions:"var(--blue)",operations:"var(--green)",contracts:"var(--purple)",accounts:"var(--orange)"})[n]||"var(--text-secondary)";return s.jsxs("div",{style:{borderBottom:"1px solid var(--border)"},children:[s.jsx("div",{style:{padding:"16px 20px",cursor:"pointer",transition:"var(--transition)"},onClick:()=>t(!e),children:s.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"flex-start"},children:[s.jsxs("div",{style:{display:"flex",alignItems:"flex-start",gap:"12px",flex:1},children:[s.jsx("div",{style:{color:a(o.type),marginTop:"2px"},children:r(o.type)}),s.jsxs("div",{style:{flex:1},children:[s.jsxs("div",{style:{fontSize:"14px",fontWeight:600,color:"var(--text-primary)",marginBottom:"4px"},children:[o.type.charAt(0).toUpperCase()+o.type.slice(1),o.operationType&&` • ${o.operationType}`]}),s.jsxs("div",{style:{fontSize:"12px",color:"var(--text-muted)",marginBottom:"8px"},children:[o.address&&s.jsxs("span",{children:["Address: ",o.address.substring(0,16),"... "]}),o.asset&&s.jsxs("span",{children:["Asset: ",o.asset," "]}),o.amount&&s.jsxs("span",{children:["Amount: ",o.amount," "]}),o.status&&s.jsxs("span",{children:["Status: ",o.status]})]}),s.jsx("div",{style:{fontSize:"11px",color:"var(--text-muted)"},children:new Date(o.timestamp).toLocaleString()})]})]}),s.jsx("div",{style:{color:"var(--text-muted)"},children:e?s.jsx(Le,{size:16}):s.jsx(Ee,{size:16})})]})}),e&&s.jsx("div",{style:{padding:"0 20px 16px",background:"var(--bg-elevated)"},children:s.jsx("pre",{style:{margin:0,fontSize:"11px",color:"var(--text-secondary)",whiteSpace:"pre-wrap",wordBreak:"break-all",maxHeight:"300px",overflowY:"auto"},children:JSON.stringify(o.data,null,2)})})]})}function ue({label:o,data:e}){const t=Object.entries(e).slice(0,3);return s.jsxs("div",{style:{padding:"4px 8px",background:"var(--bg-elevated)",border:"1px solid var(--border)",borderRadius:"999px",fontSize:"11px"},children:[s.jsxs("span",{style:{color:"var(--text-muted)"},children:[o,":"]}),t.map(([r,a],n)=>s.jsxs("span",{style:{marginLeft:"4px"},children:[r," (",a,")",n3&&"..."]})}const _={width:"100%",padding:"8px 12px",background:"var(--bg-elevated)",border:"1px solid var(--border)",borderRadius:"var(--radius-md)",color:"var(--text-primary)",fontSize:"13px",fontFamily:"var(--font-mono)",outline:"none"},G={fontSize:"12px",color:"var(--text-muted)",textTransform:"uppercase",letterSpacing:"0.5px",display:"flex",alignItems:"center",marginBottom:"6px"},Bt={padding:"4px 12px",background:"var(--bg-elevated)",border:"1px solid var(--border)",borderRadius:"999px",fontSize:"12px",cursor:"pointer",transition:"var(--transition)"},J={display:"flex",alignItems:"center",justifyContent:"center",width:"32px",height:"32px",background:"var(--bg-elevated)",border:"1px solid var(--border)",borderRadius:"var(--radius-md)",color:"var(--text-primary)",cursor:"pointer",transition:"var(--transition)"},Fe={padding:"6px 12px",background:"var(--bg-elevated)",border:"1px solid var(--border)",borderRadius:"var(--radius-md)",color:"var(--text-primary)",fontSize:"12px",cursor:"pointer",transition:"var(--transition)"};export{Xt as default}; +//# sourceMappingURL=AdvancedSearch-ELYmfCV_.js.map diff --git a/dist/assets/AdvancedSearch-ELYmfCV_.js.map b/dist/assets/AdvancedSearch-ELYmfCV_.js.map new file mode 100644 index 00000000..a569f54e --- /dev/null +++ b/dist/assets/AdvancedSearch-ELYmfCV_.js.map @@ -0,0 +1 @@ +{"version":3,"file":"AdvancedSearch-ELYmfCV_.js","sources":["../../src/lib/advancedSearch.js","../../src/lib/semanticSearch.ts","../../src/lib/relevanceFeedback.ts","../../src/hooks/useSemanticSearch.ts","../../src/components/search/SemanticSearchPanel.tsx","../../src/lib/nlpSearchEngine.ts","../../src/components/search/ConversationalAIInterface.tsx","../../src/components/dashboard/AdvancedSearch.tsx"],"sourcesContent":["/**\r\n * Advanced Search and Filtering System\r\n * Global search functionality across transactions, operations, and contracts\r\n */\r\n\r\nconst STORAGE_KEYS = {\r\n history: 'stellar-advanced-search-history-v1',\r\n saved: 'stellar-advanced-search-saved-v1',\r\n alerts: 'stellar-advanced-search-alerts-v1',\r\n folders: 'stellar-advanced-search-folders-v1',\r\n};\r\n\r\nfunction getBrowserStorage() {\r\n try {\r\n return typeof localStorage !== 'undefined' ? localStorage : null;\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\nfunction readStoredArray(storage, key, fallback = []) {\r\n if (!storage) return [...fallback];\r\n try {\r\n const parsed = JSON.parse(storage.getItem(key) || 'null');\r\n return Array.isArray(parsed) ? parsed : [...fallback];\r\n } catch {\r\n return [...fallback];\r\n }\r\n}\r\n\r\nfunction writeStoredArray(storage, key, value) {\r\n if (!storage) return;\r\n try {\r\n storage.setItem(key, JSON.stringify(value));\r\n } catch {\r\n // Persistence is best-effort because private browsing can reject writes.\r\n }\r\n}\r\n\r\nfunction stableStringify(value) {\r\n if (Array.isArray(value)) {\r\n return `[${value.map(stableStringify).join(',')}]`;\r\n }\r\n if (value && typeof value === 'object') {\r\n return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${stableStringify(value[key])}`).join(',')}}`;\r\n }\r\n return JSON.stringify(value);\r\n}\r\n\r\nfunction makeId(prefix) {\r\n return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\r\n}\r\n\r\nfunction encodeSharePayload(payload) {\r\n const serialized = encodeURIComponent(JSON.stringify(payload));\r\n if (typeof btoa === 'function') return btoa(serialized);\r\n return serialized;\r\n}\r\n\r\nfunction decodeSharePayload(token) {\r\n const serialized = typeof atob === 'function' ? atob(token) : token;\r\n return JSON.parse(decodeURIComponent(serialized));\r\n}\r\n\r\nclass AdvancedSearchService {\r\n constructor(options = {}) {\r\n this.storage = options.storage || getBrowserStorage();\r\n this.searchHistory = readStoredArray(this.storage, STORAGE_KEYS.history);\r\n this.savedSearches = readStoredArray(this.storage, STORAGE_KEYS.saved);\r\n this.searchAlerts = readStoredArray(this.storage, STORAGE_KEYS.alerts);\r\n this.savedQueryFolders = readStoredArray(this.storage, STORAGE_KEYS.folders, [{ id: 'general', name: 'General', createdAt: new Date().toISOString() }]);\r\n this.resultCache = new Map();\r\n this.cacheTtlMs = options.cacheTtlMs || 60 * 1000;\r\n this.indexedData = new Map();\r\n this.searchIndex = new Map();\r\n this.filters = {\r\n dateRange: { start: null, end: null },\r\n assetType: null,\r\n operationType: null,\r\n amountRange: { min: null, max: null },\r\n addressFilter: null,\r\n memoFilter: null,\r\n statusFilter: null,\r\n networkFilter: null\r\n };\r\n this.sortOptions = {\r\n field: 'timestamp',\r\n direction: 'desc'\r\n };\r\n }\r\n\r\n /**\r\n * Index data for fast searching\r\n * @param {string} type - Data type (transactions, operations, contracts, accounts)\r\n * @param {array} data - Array of data objects\r\n */\r\n indexData(type, data) {\r\n if (!Array.isArray(data)) return;\r\n\r\n const indexed = data.map(item => this.createSearchableItem(type, item));\r\n this.indexedData.set(type, indexed);\r\n \r\n // Build search index\r\n indexed.forEach(item => {\r\n const terms = this.extractSearchTerms(item);\r\n terms.forEach(term => {\r\n if (!this.searchIndex.has(term)) {\r\n this.searchIndex.set(term, new Set());\r\n }\r\n this.searchIndex.get(term).add(item.id);\r\n });\r\n });\r\n }\r\n\r\n /**\r\n * Create searchable item from raw data\r\n * @param {string} type - Data type\r\n * @param {object} item - Raw data item\r\n * @returns {object} Searchable item\r\n */\r\n createSearchableItem(type, item) {\r\n const baseItem = {\r\n id: `${type}_${item.id || item.hash || item.address}`,\r\n type,\r\n data: item,\r\n timestamp: this.extractTimestamp(item),\r\n amount: this.extractAmount(item),\r\n asset: this.extractAsset(item),\r\n operationType: this.extractOperationType(item),\r\n address: this.extractAddress(item),\r\n memo: this.extractMemo(item),\r\n status: this.extractStatus(item),\r\n network: item.network || 'unknown'\r\n };\r\n\r\n // Add type-specific fields\r\n switch (type) {\r\n case 'transactions':\r\n baseItem.transactionHash = item.hash;\r\n baseItem.fee = item.fee;\r\n baseItem.operationCount = item.operation_count;\r\n break;\r\n case 'operations':\r\n baseItem.operationId = item.id;\r\n baseItem.transactionHash = item.transaction_hash;\r\n baseItem.sourceAccount = item.source_account;\r\n break;\r\n case 'contracts':\r\n baseItem.contractId = item.contract_id || item.id;\r\n baseItem.contractType = item.type;\r\n break;\r\n case 'accounts':\r\n baseItem.accountId = item.account_id || item.address;\r\n baseItem.balance = item.balance;\r\n baseItem.sequence = item.sequence;\r\n break;\r\n }\r\n\r\n return baseItem;\r\n }\r\n\r\n /**\r\n * Extract search terms from item\r\n * @param {object} item - Searchable item\r\n * @returns {array} Array of search terms\r\n */\r\n extractSearchTerms(item) {\r\n const terms = new Set();\r\n\r\n // Add basic fields\r\n terms.add(item.type.toLowerCase());\r\n terms.add(item.operationType?.toLowerCase() || '');\r\n terms.add(item.asset?.toLowerCase() || '');\r\n terms.add(item.status?.toLowerCase() || '');\r\n terms.add(item.network?.toLowerCase() || '');\r\n\r\n // Add addresses and hashes\r\n if (item.address) terms.add(item.address.toLowerCase());\r\n if (item.transactionHash) terms.add(item.transactionHash.toLowerCase());\r\n if (item.contractId) terms.add(item.contractId.toLowerCase());\r\n if (item.accountId) terms.add(item.accountId.toLowerCase());\r\n\r\n // Add memo text\r\n if (item.memo) {\r\n terms.add(item.memo.toLowerCase());\r\n // Split memo into words\r\n item.memo.toLowerCase().split(/\\s+/).forEach(word => {\r\n if (word.length > 2) terms.add(word);\r\n });\r\n }\r\n\r\n // Add amount variations\r\n if (item.amount) {\r\n terms.add(item.amount.toString());\r\n terms.add(parseFloat(item.amount).toFixed(2));\r\n }\r\n\r\n // Add data-specific terms\r\n this.extractDataSpecificTerms(item.data, terms);\r\n\r\n return Array.from(terms).filter(term => term.length > 0);\r\n }\r\n\r\n /**\r\n * Extract data-specific search terms\r\n * @param {object} data - Raw data object\r\n * @param {Set} terms - Terms set to add to\r\n */\r\n extractDataSpecificTerms(data, terms) {\r\n // Recursively extract string values from nested objects\r\n const extractStrings = (obj, prefix = '') => {\r\n Object.entries(obj).forEach(([key, value]) => {\r\n const fullKey = prefix ? `${prefix}.${key}` : key;\r\n \r\n if (typeof value === 'string' && value.length > 0) {\r\n terms.add(value.toLowerCase());\r\n // Split into words\r\n value.toLowerCase().split(/\\s+/).forEach(word => {\r\n if (word.length > 2) terms.add(word);\r\n });\r\n } else if (typeof value === 'number') {\r\n terms.add(value.toString());\r\n } else if (typeof value === 'object' && value !== null) {\r\n extractStrings(value, fullKey);\r\n }\r\n });\r\n };\r\n\r\n extractStrings(data);\r\n }\r\n\r\n /**\r\n * Extract timestamp from item\r\n * @param {object} item - Raw data item\r\n * @returns {number} Timestamp\r\n */\r\n extractTimestamp(item) {\r\n if (item.created_at) return new Date(item.created_at).getTime();\r\n if (item.timestamp) return new Date(item.timestamp).getTime();\r\n if (item.time) return new Date(item.time).getTime();\r\n return Date.now();\r\n }\r\n\r\n /**\r\n * Extract amount from item\r\n * @param {object} item - Raw data item\r\n * @returns {number|null} Amount\r\n */\r\n extractAmount(item) {\r\n if (item.amount) return parseFloat(item.amount);\r\n if (item.starting_balance) return parseFloat(item.starting_balance);\r\n if (item.amount_in) return parseFloat(item.amount_in);\r\n if (item.amount_out) return parseFloat(item.amount_out);\r\n return null;\r\n }\r\n\r\n /**\r\n * Extract asset from item\r\n * @param {object} item - Raw data item\r\n * @returns {string|null} Asset code\r\n */\r\n extractAsset(item) {\r\n if (item.asset_code) return item.asset_code;\r\n if (item.asset_type === 'native') return 'XLM';\r\n if (item.asset_code && item.asset_issuer) return `${item.asset_code}:${item.asset_issuer}`;\r\n return null;\r\n }\r\n\r\n /**\r\n * Extract operation type from item\r\n * @param {object} item - Raw data item\r\n * @returns {string|null} Operation type\r\n */\r\n extractOperationType(item) {\r\n if (item.type) return item.type;\r\n if (item.operation_type) return this.getOperationTypeName(item.operation_type);\r\n return null;\r\n }\r\n\r\n /**\r\n * Get operation type name from code\r\n * @param {number} code - Operation type code\r\n * @returns {string} Operation type name\r\n */\r\n getOperationTypeName(code) {\r\n const types = {\r\n 0: 'payment',\r\n 1: 'create_account',\r\n 2: 'manage_offer',\r\n 3: 'set_options',\r\n 4: 'change_trust',\r\n 5: 'allow_trust',\r\n 6: 'account_merge',\r\n 7: 'inflation',\r\n 8: 'manage_data',\r\n 9: 'bump_sequence',\r\n 10: 'create_claimable_balance',\r\n 11: 'claim_claimable_balance',\r\n 12: 'begin_sponsoring_future_reserves',\r\n 13: 'end_sponsoring_future_reserves',\r\n 14: 'revoke_sponsorship'\r\n };\r\n return types[code] || 'unknown';\r\n }\r\n\r\n /**\r\n * Extract address from item\r\n * @param {object} item - Raw data item\r\n * @returns {string|null} Address\r\n */\r\n extractAddress(item) {\r\n if (item.account_id) return item.account_id;\r\n if (item.source_account) return item.source_account;\r\n if (item.destination_account) return item.destination_account;\r\n if (item.address) return item.address;\r\n return null;\r\n }\r\n\r\n /**\r\n * Extract memo from item\r\n * @param {object} item - Raw data item\r\n * @returns {string|null} Memo text\r\n */\r\n extractMemo(item) {\r\n if (item.memo) return item.memo;\r\n if (item.memo_type && item.memo_value) {\r\n if (item.memo_type === 'text') return item.memo_value;\r\n if (item.memo_type === 'id') return item.memo_value.toString();\r\n }\r\n return null;\r\n }\r\n\r\n /**\r\n * Extract status from item\r\n * @param {object} item - Raw data item\r\n * @returns {string|null} Status\r\n */\r\n extractStatus(item) {\r\n if (item.status) return item.status;\r\n if (item.successful !== undefined) return item.successful ? 'success' : 'failed';\r\n if (item.result_successful !== undefined) return item.result_successful ? 'success' : 'failed';\r\n return null;\r\n }\r\n\r\n /**\r\n * Perform global search\r\n * @param {object} query - Search query object\r\n * @returns {object} Search results\r\n */\r\n search(query) {\r\n const startTime = Date.now();\r\n \r\n try {\r\n const optimizedQuery = this.optimizeQuery(query);\r\n\r\n // Update filters if provided\r\n if (optimizedQuery.filters) {\r\n this.filters = { ...this.filters, ...optimizedQuery.filters };\r\n }\r\n\r\n // Update sort options if provided\r\n if (optimizedQuery.sort) {\r\n this.sortOptions = { ...this.sortOptions, ...optimizedQuery.sort };\r\n }\r\n\r\n const queryPlan = this.buildQueryPlan(optimizedQuery);\r\n const cacheKey = this.createQueryKey({ ...optimizedQuery, filters: this.filters, sort: this.sortOptions });\r\n const cached = optimizedQuery.cache !== false ? this.getCachedResults(cacheKey) : null;\r\n if (cached) {\r\n const cachedResult = {\r\n ...cached,\r\n query: optimizedQuery,\r\n cached: true,\r\n searchTime: Date.now() - startTime,\r\n queryPlan,\r\n };\r\n this.addToSearchHistory(optimizedQuery, {\r\n resultCount: cached.total,\r\n searchTime: cachedResult.searchTime,\r\n cached: true,\r\n });\r\n return cachedResult;\r\n }\r\n\r\n // Get all indexed data\r\n let results = [];\r\n this.indexedData.forEach((items, type) => {\r\n if (!optimizedQuery.types || optimizedQuery.types.includes(type)) {\r\n results.push(...items);\r\n }\r\n });\r\n\r\n // Apply text search\r\n if (optimizedQuery.text && optimizedQuery.text.trim()) {\r\n results = this.applyTextSearch(results, optimizedQuery.text.trim());\r\n }\r\n\r\n // Apply filters\r\n results = this.applyFilters(results);\r\n\r\n // Apply sorting\r\n results = this.applySorting(results);\r\n\r\n // Apply pagination\r\n const paginatedResults = this.applyPagination(results, optimizedQuery.page, optimizedQuery.limit);\r\n\r\n const searchTime = Date.now() - startTime;\r\n\r\n const response = {\r\n query: optimizedQuery,\r\n results: paginatedResults.items,\r\n total: paginatedResults.total,\r\n page: paginatedResults.page,\r\n limit: paginatedResults.limit,\r\n searchTime,\r\n cached: false,\r\n cacheKey,\r\n queryPlan,\r\n filters: { ...this.filters },\r\n sort: { ...this.sortOptions },\r\n aggregations: this.calculateAggregations(results)\r\n };\r\n\r\n this.setCachedResults(cacheKey, response);\r\n this.addToSearchHistory(optimizedQuery, {\r\n resultCount: response.total,\r\n searchTime,\r\n cached: false,\r\n });\r\n\r\n return response;\r\n\r\n } catch (error) {\r\n throw new Error(`Search failed: ${error.message}`);\r\n }\r\n }\r\n\r\n /**\r\n * Apply text search to results\r\n * @param {array} results - Results array\r\n * @param {string} searchText - Search text\r\n * @returns {array} Filtered results\r\n */\r\n applyTextSearch(results, searchText) {\r\n const searchTerms = searchText.toLowerCase().split(/\\s+/).filter(term => term.length > 0);\r\n \r\n if (searchTerms.length === 0) return results;\r\n\r\n return results.filter(item => {\r\n return searchTerms.every(term => {\r\n // Check if any search term matches the item\r\n return this.itemContainsTerm(item, term);\r\n });\r\n });\r\n }\r\n\r\n /**\r\n * Check if item contains search term\r\n * @param {object} item - Searchable item\r\n * @param {string} term - Search term\r\n * @returns {boolean} True if item contains term\r\n */\r\n itemContainsTerm(item, term) {\r\n // Check basic fields\r\n if (item.type?.toLowerCase().includes(term)) return true;\r\n if (item.operationType?.toLowerCase().includes(term)) return true;\r\n if (item.asset?.toLowerCase().includes(term)) return true;\r\n if (item.status?.toLowerCase().includes(term)) return true;\r\n if (item.address?.toLowerCase().includes(term)) return true;\r\n if (item.memo?.toLowerCase().includes(term)) return true;\r\n\r\n // Check hashes and IDs\r\n if (item.transactionHash?.toLowerCase().includes(term)) return true;\r\n if (item.contractId?.toLowerCase().includes(term)) return true;\r\n if (item.accountId?.toLowerCase().includes(term)) return true;\r\n\r\n // Check numeric values\r\n if (item.amount?.toString().includes(term)) return true;\r\n\r\n // Check search index for exact matches\r\n const indexedItems = this.searchIndex.get(term.toLowerCase());\r\n if (indexedItems && indexedItems.has(item.id)) return true;\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Apply filters to results\r\n * @param {array} results - Results array\r\n * @returns {array} Filtered results\r\n */\r\n applyFilters(results) {\r\n return results.filter(item => {\r\n // Date range filter\r\n if (this.filters.dateRange.start && item.timestamp < this.filters.dateRange.start) {\r\n return false;\r\n }\r\n if (this.filters.dateRange.end && item.timestamp > this.filters.dateRange.end) {\r\n return false;\r\n }\r\n\r\n // Asset type filter\r\n if (this.filters.assetType && item.asset !== this.filters.assetType) {\r\n return false;\r\n }\r\n\r\n // Operation type filter\r\n if (this.filters.operationType && item.operationType !== this.filters.operationType) {\r\n return false;\r\n }\r\n\r\n // Amount range filter\r\n if (this.filters.amountRange.min !== null && (!item.amount || item.amount < this.filters.amountRange.min)) {\r\n return false;\r\n }\r\n if (this.filters.amountRange.max !== null && (!item.amount || item.amount > this.filters.amountRange.max)) {\r\n return false;\r\n }\r\n\r\n // Address filter\r\n if (this.filters.addressFilter && !item.address?.includes(this.filters.addressFilter)) {\r\n return false;\r\n }\r\n\r\n // Memo filter\r\n if (this.filters.memoFilter && !item.memo?.toLowerCase().includes(this.filters.memoFilter.toLowerCase())) {\r\n return false;\r\n }\r\n\r\n // Status filter\r\n if (this.filters.statusFilter && item.status !== this.filters.statusFilter) {\r\n return false;\r\n }\r\n\r\n // Network filter\r\n if (this.filters.networkFilter && item.network !== this.filters.networkFilter) {\r\n return false;\r\n }\r\n\r\n return true;\r\n });\r\n }\r\n\r\n /**\r\n * Apply sorting to results\r\n * @param {array} results - Results array\r\n * @returns {array} Sorted results\r\n */\r\n applySorting(results) {\r\n const { field, direction } = this.sortOptions;\r\n \r\n return results.sort((a, b) => {\r\n let aValue = a[field];\r\n let bValue = b[field];\r\n\r\n // Handle null/undefined values\r\n if (aValue === null || aValue === undefined) aValue = '';\r\n if (bValue === null || bValue === undefined) bValue = '';\r\n\r\n // Compare based on type\r\n let comparison = 0;\r\n if (typeof aValue === 'number' && typeof bValue === 'number') {\r\n comparison = aValue - bValue;\r\n } else {\r\n comparison = String(aValue).localeCompare(String(bValue));\r\n }\r\n\r\n return direction === 'asc' ? comparison : -comparison;\r\n });\r\n }\r\n\r\n /**\r\n * Apply pagination to results\r\n * @param {array} results - Results array\r\n * @param {number} page - Page number (1-based)\r\n * @param {number} limit - Page size\r\n * @returns {object} Paginated results\r\n */\r\n applyPagination(results, page = 1, limit = 20) {\r\n const startIndex = (page - 1) * limit;\r\n const endIndex = startIndex + limit;\r\n \r\n return {\r\n items: results.slice(startIndex, endIndex),\r\n total: results.length,\r\n page,\r\n limit,\r\n totalPages: Math.ceil(results.length / limit)\r\n };\r\n }\r\n\r\n /**\r\n * Calculate aggregations for results\r\n * @param {array} results - Results array\r\n * @returns {object} Aggregations\r\n */\r\n calculateAggregations(results) {\r\n const aggregations = {\r\n typeCounts: {},\r\n operationTypeCounts: {},\r\n assetCounts: {},\r\n statusCounts: {},\r\n totalAmount: 0,\r\n averageAmount: 0,\r\n dateRange: { earliest: null, latest: null }\r\n };\r\n\r\n results.forEach(item => {\r\n // Type counts\r\n aggregations.typeCounts[item.type] = (aggregations.typeCounts[item.type] || 0) + 1;\r\n\r\n // Operation type counts\r\n if (item.operationType) {\r\n aggregations.operationTypeCounts[item.operationType] = \r\n (aggregations.operationTypeCounts[item.operationType] || 0) + 1;\r\n }\r\n\r\n // Asset counts\r\n if (item.asset) {\r\n aggregations.assetCounts[item.asset] = (aggregations.assetCounts[item.asset] || 0) + 1;\r\n }\r\n\r\n // Status counts\r\n if (item.status) {\r\n aggregations.statusCounts[item.status] = (aggregations.statusCounts[item.status] || 0) + 1;\r\n }\r\n\r\n // Amount aggregations\r\n if (item.amount) {\r\n aggregations.totalAmount += item.amount;\r\n }\r\n\r\n // Date range\r\n if (item.timestamp) {\r\n if (!aggregations.dateRange.earliest || item.timestamp < aggregations.dateRange.earliest) {\r\n aggregations.dateRange.earliest = item.timestamp;\r\n }\r\n if (!aggregations.dateRange.latest || item.timestamp > aggregations.dateRange.latest) {\r\n aggregations.dateRange.latest = item.timestamp;\r\n }\r\n }\r\n });\r\n\r\n // Calculate average amount\r\n const amountCount = results.filter(item => item.amount !== null).length;\r\n aggregations.averageAmount = amountCount > 0 ? aggregations.totalAmount / amountCount : 0;\r\n\r\n return aggregations;\r\n }\r\n\r\n /**\r\n * Normalize query fields before execution.\r\n * @param {object} query - Search query\r\n * @returns {object} Optimized query\r\n */\r\n optimizeQuery(query = {}) {\r\n const text = (query.text || '').trim();\r\n const types = Array.isArray(query.types) && query.types.length\r\n ? Array.from(new Set(query.types)).sort()\r\n : null;\r\n\r\n return {\r\n ...query,\r\n text,\r\n types,\r\n page: Math.max(Number(query.page) || 1, 1),\r\n limit: Math.min(Math.max(Number(query.limit) || 20, 1), 100),\r\n };\r\n }\r\n\r\n /**\r\n * Build a stable cache key for the effective query.\r\n * @param {object} query - Search query\r\n * @returns {string} Cache key\r\n */\r\n createQueryKey(query) {\r\n return stableStringify({\r\n text: query.text || '',\r\n types: query.types || null,\r\n filters: query.filters || {},\r\n sort: query.sort || {},\r\n page: query.page || 1,\r\n limit: query.limit || 20,\r\n });\r\n }\r\n\r\n /**\r\n * Store a result in the in-memory cache.\r\n * @param {string} key - Cache key\r\n * @param {object} result - Search response\r\n */\r\n setCachedResults(key, result) {\r\n this.resultCache.set(key, {\r\n expiresAt: Date.now() + this.cacheTtlMs,\r\n result,\r\n });\r\n }\r\n\r\n /**\r\n * Read a result from the in-memory cache.\r\n * @param {string} key - Cache key\r\n * @returns {object|null} Cached response\r\n */\r\n getCachedResults(key) {\r\n const entry = this.resultCache.get(key);\r\n if (!entry) return null;\r\n if (entry.expiresAt <= Date.now()) {\r\n this.resultCache.delete(key);\r\n return null;\r\n }\r\n return entry.result;\r\n }\r\n\r\n clearResultCache() {\r\n this.resultCache.clear();\r\n }\r\n\r\n /**\r\n * Produce a lightweight plan for index/caching observability.\r\n * @param {object} query - Optimized query\r\n * @returns {object} Query plan summary\r\n */\r\n buildQueryPlan(query) {\r\n const terms = (query.text || '').toLowerCase().split(/\\s+/).filter(Boolean);\r\n const indexedTerms = terms.filter((term) => this.searchIndex.has(term));\r\n const filterCount = Object.values(query.filters || {}).filter((value) => {\r\n if (value && typeof value === 'object') {\r\n return Object.values(value).some((nested) => nested !== null && nested !== '');\r\n }\r\n return value !== null && value !== '';\r\n }).length;\r\n\r\n return {\r\n textTerms: terms,\r\n indexedTerms,\r\n filterCount,\r\n usesIndex: indexedTerms.length > 0,\r\n cacheTtlMs: this.cacheTtlMs,\r\n indexedTypes: query.types || Array.from(this.indexedData.keys()),\r\n };\r\n }\r\n\r\n /**\r\n * Add search to history\r\n * @param {object} query - Search query\r\n */\r\n addToSearchHistory(query, meta = {}) {\r\n const historyEntry = {\r\n id: makeId('history'),\r\n timestamp: new Date().toISOString(),\r\n query: { ...query },\r\n resultCount: meta.resultCount || 0,\r\n searchTime: meta.searchTime || 0,\r\n cached: Boolean(meta.cached)\r\n };\r\n\r\n this.searchHistory.unshift(historyEntry);\r\n \r\n // Keep only last 50 searches\r\n if (this.searchHistory.length > 50) {\r\n this.searchHistory = this.searchHistory.slice(0, 50);\r\n }\r\n\r\n writeStoredArray(this.storage, STORAGE_KEYS.history, this.searchHistory);\r\n }\r\n\r\n /**\r\n * Save search for later use\r\n * @param {string} name - Search name\r\n * @param {object} query - Search query\r\n */\r\n saveSearch(name, query, options = {}) {\r\n const folder = options.folder || 'General';\r\n this.createSavedSearchFolder(folder);\r\n const savedSearch = {\r\n id: makeId('saved'),\r\n name,\r\n query: { ...query },\r\n folder,\r\n tags: options.tags || [],\r\n description: options.description || '',\r\n sharedWith: [],\r\n shareToken: null,\r\n createdAt: new Date().toISOString(),\r\n updatedAt: new Date().toISOString(),\r\n usageCount: 0\r\n };\r\n\r\n this.savedSearches.push(savedSearch);\r\n writeStoredArray(this.storage, STORAGE_KEYS.saved, this.savedSearches);\r\n return savedSearch;\r\n }\r\n\r\n /**\r\n * Get saved searches\r\n * @returns {array} Saved searches\r\n */\r\n getSavedSearches(options = {}) {\r\n return [...this.savedSearches]\r\n .filter((search) => !options.folder || search.folder === options.folder)\r\n .sort((a, b) => b.usageCount - a.usageCount || new Date(b.updatedAt || b.createdAt).getTime() - new Date(a.updatedAt || a.createdAt).getTime());\r\n }\r\n\r\n loadSavedSearch(id) {\r\n const savedSearch = this.savedSearches.find((search) => search.id === id);\r\n if (!savedSearch) return null;\r\n savedSearch.usageCount += 1;\r\n savedSearch.updatedAt = new Date().toISOString();\r\n writeStoredArray(this.storage, STORAGE_KEYS.saved, this.savedSearches);\r\n return savedSearch;\r\n }\r\n\r\n deleteSavedSearch(id) {\r\n this.savedSearches = this.savedSearches.filter((search) => search.id !== id);\r\n writeStoredArray(this.storage, STORAGE_KEYS.saved, this.savedSearches);\r\n }\r\n\r\n createSavedSearchFolder(name) {\r\n const normalizedName = (name || 'General').trim() || 'General';\r\n const existing = this.savedQueryFolders.find((folder) => folder.name.toLowerCase() === normalizedName.toLowerCase());\r\n if (existing) return existing;\r\n\r\n const folder = {\r\n id: makeId('folder'),\r\n name: normalizedName,\r\n createdAt: new Date().toISOString(),\r\n };\r\n this.savedQueryFolders.push(folder);\r\n writeStoredArray(this.storage, STORAGE_KEYS.folders, this.savedQueryFolders);\r\n return folder;\r\n }\r\n\r\n getSavedSearchFolders() {\r\n return this.savedQueryFolders.map((folder) => ({\r\n ...folder,\r\n count: this.savedSearches.filter((search) => search.folder === folder.name).length,\r\n }));\r\n }\r\n\r\n shareSearch(id, options = {}) {\r\n const savedSearch = this.savedSearches.find((search) => search.id === id);\r\n if (!savedSearch) {\r\n throw new Error('Saved search not found');\r\n }\r\n\r\n savedSearch.sharedWith = Array.from(new Set([...(savedSearch.sharedWith || []), ...(options.users || [])]));\r\n savedSearch.shareToken = savedSearch.shareToken || encodeSharePayload({\r\n id: savedSearch.id,\r\n name: savedSearch.name,\r\n query: savedSearch.query,\r\n folder: savedSearch.folder,\r\n });\r\n savedSearch.updatedAt = new Date().toISOString();\r\n writeStoredArray(this.storage, STORAGE_KEYS.saved, this.savedSearches);\r\n return savedSearch.shareToken;\r\n }\r\n\r\n importSharedSearch(shareToken, options = {}) {\r\n const parsed = decodeSharePayload(shareToken);\r\n return this.saveSearch(options.name || parsed.name, parsed.query, {\r\n folder: options.folder || parsed.folder || 'Shared',\r\n tags: ['shared'],\r\n });\r\n }\r\n\r\n createSearchAlert(input) {\r\n const alert = {\r\n id: makeId('alert'),\r\n savedSearchId: input.savedSearchId || null,\r\n name: input.name || 'Search alert',\r\n query: input.query || this.savedSearches.find((search) => search.id === input.savedSearchId)?.query || {},\r\n cron: input.cron || '0 * * * *',\r\n channels: input.channels || ['in-app'],\r\n threshold: Number(input.threshold || 1),\r\n enabled: input.enabled !== false,\r\n lastRunAt: null,\r\n nextRunAt: this.getNextAlertRun(input.cron || '0 * * * *'),\r\n createdAt: new Date().toISOString(),\r\n };\r\n\r\n this.searchAlerts.push(alert);\r\n writeStoredArray(this.storage, STORAGE_KEYS.alerts, this.searchAlerts);\r\n return alert;\r\n }\r\n\r\n getSearchAlerts() {\r\n return [...this.searchAlerts].sort((a, b) => new Date(a.nextRunAt).getTime() - new Date(b.nextRunAt).getTime());\r\n }\r\n\r\n getNextAlertRun(cronExpression, from = new Date()) {\r\n const [minute = '0', hour = '*'] = cronExpression.trim().split(/\\s+/);\r\n const next = new Date(from);\r\n next.setSeconds(0, 0);\r\n next.setMinutes(next.getMinutes() + 1);\r\n if (minute !== '*') next.setMinutes(Number(minute.replace('*/', '')) || 0);\r\n if (hour !== '*') next.setHours(Number(hour.replace('*/', '')) || next.getHours());\r\n if (next.getTime() <= from.getTime()) next.setHours(next.getHours() + 1);\r\n return next.toISOString();\r\n }\r\n\r\n evaluateSearchAlerts(now = new Date()) {\r\n return this.searchAlerts\r\n .filter((alert) => alert.enabled && new Date(alert.nextRunAt).getTime() <= now.getTime())\r\n .map((alert) => {\r\n const result = this.search({ ...alert.query, cache: false });\r\n alert.lastRunAt = now.toISOString();\r\n alert.nextRunAt = this.getNextAlertRun(alert.cron, now);\r\n writeStoredArray(this.storage, STORAGE_KEYS.alerts, this.searchAlerts);\r\n return {\r\n alert,\r\n resultCount: result.total,\r\n triggered: result.total >= alert.threshold,\r\n };\r\n });\r\n }\r\n\r\n getSearchHistory() {\r\n return [...this.searchHistory];\r\n }\r\n\r\n getFrequentSearches(limit = 5) {\r\n const counts = new Map();\r\n this.searchHistory.forEach((entry) => {\r\n const key = entry.query?.text || JSON.stringify(entry.query?.filters || {});\r\n counts.set(key, (counts.get(key) || 0) + 1);\r\n });\r\n return Array.from(counts.entries())\r\n .map(([query, count]) => ({ query, count }))\r\n .sort((a, b) => b.count - a.count)\r\n .slice(0, limit);\r\n }\r\n\r\n getSearchAnalytics() {\r\n const history = this.getSearchHistory();\r\n const totalSearchTime = history.reduce((sum, entry) => sum + (entry.searchTime || 0), 0);\r\n return {\r\n totalSearches: history.length,\r\n cachedSearches: history.filter((entry) => entry.cached).length,\r\n averageSearchTime: history.length ? totalSearchTime / history.length : 0,\r\n savedSearches: this.savedSearches.length,\r\n folders: this.savedQueryFolders.length,\r\n alerts: this.searchAlerts.length,\r\n frequentSearches: this.getFrequentSearches(),\r\n cacheEntries: this.resultCache.size,\r\n };\r\n }\r\n\r\n /**\r\n * Get search suggestions\r\n * @param {string} partial - Partial search term\r\n * @returns {array} Suggestions\r\n */\r\n getSuggestions(partial) {\r\n if (!partial || partial.length < 2) return [];\r\n\r\n const suggestions = new Set();\r\n const lowerPartial = partial.toLowerCase();\r\n\r\n // Find matching terms from search index\r\n this.searchIndex.forEach((items, term) => {\r\n if (term.includes(lowerPartial)) {\r\n suggestions.add(term);\r\n }\r\n });\r\n\r\n // Add common operation types\r\n const operationTypes = ['payment', 'create_account', 'manage_offer', 'set_options', 'change_trust'];\r\n operationTypes.forEach(type => {\r\n if (type.includes(lowerPartial)) {\r\n suggestions.add(type);\r\n }\r\n });\r\n\r\n // Add common assets\r\n const commonAssets = ['XLM', 'USDC', 'BTC', 'ETH', 'USDT'];\r\n commonAssets.forEach(asset => {\r\n if (asset.toLowerCase().includes(lowerPartial)) {\r\n suggestions.add(asset);\r\n }\r\n });\r\n\r\n return Array.from(suggestions).slice(0, 10);\r\n }\r\n\r\n /**\r\n * Clear search history\r\n */\r\n clearHistory() {\r\n this.searchHistory = [];\r\n }\r\n\r\n /**\r\n * Reset all filters\r\n */\r\n resetFilters() {\r\n this.filters = {\r\n dateRange: { start: null, end: null },\r\n assetType: null,\r\n operationType: null,\r\n amountRange: { min: null, max: null },\r\n addressFilter: null,\r\n memoFilter: null,\r\n statusFilter: null,\r\n networkFilter: null\r\n };\r\n }\r\n\r\n /**\r\n * Get current filters\r\n * @returns {object} Current filters\r\n */\r\n getFilters() {\r\n return { ...this.filters };\r\n }\r\n\r\n /**\r\n * Get search statistics\r\n * @returns {object} Search statistics\r\n */\r\n getStatistics() {\r\n return {\r\n indexedItems: Array.from(this.indexedData.values()).reduce((total, items) => total + items.length, 0),\r\n indexedTypes: Array.from(this.indexedData.keys()),\r\n searchTerms: this.searchIndex.size,\r\n searchHistory: this.searchHistory.length,\r\n savedSearches: this.savedSearches.length\r\n };\r\n }\r\n}\r\n\r\n// Create singleton instance\r\nconst advancedSearchService = new AdvancedSearchService();\r\n\r\nexport default advancedSearchService;\r\nexport { AdvancedSearchService };\r\n","/**\r\n * Enhanced Semantic Search Engine\r\n *\r\n * Combines TF-IDF weighted embeddings, BM25-style relevance scoring, Stellar-domain\r\n * synonym expansion, Levenshtein-based typo correction, and relevance feedback boosting\r\n * to deliver meaningful semantic search results over Stellar blockchain data.\r\n *\r\n * Key capabilities:\r\n * - Builds a vocabulary from indexed documents (no external model needed)\r\n * - Expands queries with domain synonyms (e.g. \"send\" → [\"payment\",\"transfer\"])\r\n * - Corrects single-character typos before scoring\r\n * - Ranks results with cosine similarity on TF-IDF vectors, further boosted by\r\n * BM25-style term saturation and user relevance feedback\r\n * - Generates human-readable explanations for every result\r\n */\r\n\r\n// ---------------------------------------------------------------------------\r\n// Types\r\n// ---------------------------------------------------------------------------\r\n\r\nexport interface SemanticDocument {\r\n /** Unique identifier */\r\n id: string;\r\n /** Plain-text content used for indexing */\r\n text: string;\r\n /** Structured metadata preserved in results */\r\n metadata?: Record;\r\n /** Computed embedding (set by engine; consumers should not set directly) */\r\n embedding?: number[];\r\n}\r\n\r\nexport interface SearchResult {\r\n document: SemanticDocument;\r\n /** Normalised relevance score in [0, 1] */\r\n score: number;\r\n /** Human-readable breakdown of why this result ranked here */\r\n explanation: string;\r\n /** Terms from the query that matched this document */\r\n matchedTerms: string[];\r\n /** True when the document's score was boosted by relevance feedback */\r\n feedbackBoosted: boolean;\r\n}\r\n\r\nexport interface QueryExpansion {\r\n originalTerms: string[];\r\n expandedTerms: string[];\r\n synonymsUsed: Record;\r\n}\r\n\r\nexport interface TypoCorrection {\r\n original: string;\r\n corrected: string;\r\n wasCorreected: boolean;\r\n}\r\n\r\nexport interface SemanticSearchOptions {\r\n /** Maximum number of results to return (default: 10) */\r\n topK?: number;\r\n /** Minimum similarity score to include a result (default: 0.01) */\r\n minScore?: number;\r\n /** Whether to apply synonym expansion (default: true) */\r\n expandQuery?: boolean;\r\n /** Whether to attempt typo correction (default: true) */\r\n correctTypos?: boolean;\r\n /** Whether to use feedback boosts from RelevanceFeedbackStore (default: true) */\r\n applyFeedback?: boolean;\r\n /** External relevance boosts keyed by docId */\r\n feedbackBoosts?: Record;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Stellar-domain synonym dictionary\r\n// ---------------------------------------------------------------------------\r\n\r\nconst STELLAR_SYNONYMS: Record = {\r\n // Payments / transfers\r\n send: ['payment', 'transfer', 'transmit', 'remit', 'pay'],\r\n payment: ['send', 'transfer', 'remit', 'pay', 'disbursement'],\r\n transfer: ['payment', 'send', 'move', 'shift'],\r\n receive: ['incoming', 'received', 'destination', 'credited'],\r\n // Accounts\r\n account: ['wallet', 'address', 'publickey', 'user'],\r\n wallet: ['account', 'address', 'publickey'],\r\n address: ['account', 'wallet', 'publickey', 'key'],\r\n balance: ['funds', 'holdings', 'amount', 'total'],\r\n // Assets\r\n xlm: ['lumen', 'lumens', 'native', 'stellar'],\r\n lumen: ['xlm', 'lumens', 'native'],\r\n native: ['xlm', 'lumen', 'lumens'],\r\n asset: ['token', 'currency', 'coin', 'trustline'],\r\n token: ['asset', 'currency', 'coin'],\r\n trustline: ['trust', 'asset', 'token'],\r\n // Operations\r\n transaction: ['tx', 'txn', 'operation', 'op', 'record'],\r\n tx: ['transaction', 'txn', 'op'],\r\n operation: ['tx', 'transaction', 'op', 'action'],\r\n op: ['operation', 'transaction', 'tx'],\r\n // Specific operations\r\n create: ['createaccount', 'new', 'open', 'genesis'],\r\n merge: ['accountmerge', 'close', 'combine'],\r\n offer: ['order', 'trade', 'dex', 'sell', 'buy'],\r\n trade: ['offer', 'swap', 'exchange', 'dex'],\r\n swap: ['trade', 'exchange', 'offer'],\r\n liquidity: ['pool', 'amm', 'lp', 'liquiditypool'],\r\n // Contracts\r\n contract: ['soroban', 'smart', 'wasm', 'program'],\r\n soroban: ['contract', 'smart', 'wasm'],\r\n invoke: ['call', 'execute', 'run', 'deploy'],\r\n // Status\r\n success: ['successful', 'completed', 'confirmed', 'ok'],\r\n failed: ['failure', 'error', 'rejected', 'unsuccessful'],\r\n pending: ['unconfirmed', 'waiting', 'queued'],\r\n // Time\r\n recent: ['latest', 'new', 'last', 'newest'],\r\n old: ['oldest', 'historic', 'early', 'first'],\r\n today: ['now', 'current', 'daily'],\r\n // Network\r\n mainnet: ['main', 'production', 'live'],\r\n testnet: ['test', 'sandbox', 'dev'],\r\n};\r\n\r\n// Pre-build reverse map: for any synonym value, map back to the canonical key\r\nconst SYNONYM_REVERSE: Record = {};\r\nfor (const [canonical, synonyms] of Object.entries(STELLAR_SYNONYMS)) {\r\n for (const syn of synonyms) {\r\n if (!SYNONYM_REVERSE[syn]) SYNONYM_REVERSE[syn] = [];\r\n if (!SYNONYM_REVERSE[syn].includes(canonical)) SYNONYM_REVERSE[syn].push(canonical);\r\n }\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// BM25 hyper-parameters\r\n// ---------------------------------------------------------------------------\r\nconst BM25_K1 = 1.5; // term-frequency saturation\r\nconst BM25_B = 0.75; // document-length normalisation\r\n\r\n// ---------------------------------------------------------------------------\r\n// Helper: Levenshtein distance\r\n// ---------------------------------------------------------------------------\r\nfunction levenshtein(a: string, b: string): number {\r\n const m = a.length;\r\n const n = b.length;\r\n // dp[i][j] = edit distance between a[0..i-1] and b[0..j-1]\r\n const dp: number[][] = Array.from({ length: m + 1 }, (_, i) =>\r\n Array.from({ length: n + 1 }, (_, j) => (i === 0 ? j : j === 0 ? i : 0))\r\n );\r\n for (let i = 1; i <= m; i++) {\r\n for (let j = 1; j <= n; j++) {\r\n if (a[i - 1] === b[j - 1]) {\r\n dp[i][j] = dp[i - 1][j - 1];\r\n } else {\r\n dp[i][j] = 1 + Math.min(dp[i - 1][j - 1], dp[i][j - 1], dp[i - 1][j]);\r\n }\r\n }\r\n }\r\n return dp[m][n];\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Helper: tokenise text\r\n// ---------------------------------------------------------------------------\r\nfunction tokenise(text: string): string[] {\r\n return text\r\n .toLowerCase()\r\n .replace(/[^a-z0-9\\s]/g, ' ')\r\n .split(/\\s+/)\r\n .filter((t) => t.length >= 2);\r\n}\r\n\r\n// Stop-words to strip before indexing\r\nconst STOP_WORDS = new Set([\r\n 'the', 'a', 'an', 'is', 'in', 'it', 'of', 'or', 'at', 'by', 'be', 'as',\r\n 'to', 'for', 'on', 'do', 'if', 'no', 'so', 'up', 'we', 'me', 'my',\r\n]);\r\n\r\nfunction filterStopWords(tokens: string[]): string[] {\r\n return tokens.filter((t) => !STOP_WORDS.has(t));\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// SemanticSearchEngine\r\n// ---------------------------------------------------------------------------\r\n\r\nexport class SemanticSearchEngine {\r\n // Indexed documents\r\n private docs: SemanticDocument[] = [];\r\n // term → [docIdx, …] (inverted index)\r\n private invertedIndex: Map = new Map();\r\n // term → IDF value\r\n private idf: Map = new Map();\r\n // term → global document frequency\r\n private df: Map = new Map();\r\n // Vocabulary array (position = dimension in embedding vector)\r\n private vocab: string[] = [];\r\n private vocabIndex: Map = new Map();\r\n // Average document length (tokens)\r\n private avgDocLen = 0;\r\n\r\n // ---------------------------------------------------------------------------\r\n // Index management\r\n // ---------------------------------------------------------------------------\r\n\r\n /** Add a single document to the index. */\r\n indexDocument(doc: SemanticDocument): void {\r\n const tokens = filterStopWords(tokenise(doc.text));\r\n const docIdx = this.docs.length;\r\n\r\n // TF for this document\r\n const tf = new Map();\r\n for (const token of tokens) {\r\n tf.set(token, (tf.get(token) ?? 0) + 1);\r\n }\r\n\r\n // Update vocab & inverted index\r\n for (const term of tf.keys()) {\r\n if (!this.vocabIndex.has(term)) {\r\n this.vocabIndex.set(term, this.vocab.length);\r\n this.vocab.push(term);\r\n }\r\n if (!this.invertedIndex.has(term)) this.invertedIndex.set(term, []);\r\n this.invertedIndex.get(term)!.push(docIdx);\r\n this.df.set(term, (this.df.get(term) ?? 0) + 1);\r\n }\r\n\r\n // Store document with its token list length\r\n const stored: SemanticDocument & { _tokens?: string[]; _tf?: Map } = {\r\n ...doc,\r\n _tokens: tokens,\r\n _tf: tf,\r\n };\r\n this.docs.push(stored);\r\n\r\n // Recompute IDF and average doc length (incremental approximation)\r\n this._recomputeIdf();\r\n this._recomputeAvgDocLen();\r\n }\r\n\r\n /** Index many documents at once. More efficient than repeated single calls. */\r\n indexDocuments(docs: SemanticDocument[]): void {\r\n for (const doc of docs) {\r\n // Defer IDF recompute until the end\r\n const tokens = filterStopWords(tokenise(doc.text));\r\n const docIdx = this.docs.length;\r\n const tf = new Map();\r\n for (const token of tokens) tf.set(token, (tf.get(token) ?? 0) + 1);\r\n for (const term of tf.keys()) {\r\n if (!this.vocabIndex.has(term)) {\r\n this.vocabIndex.set(term, this.vocab.length);\r\n this.vocab.push(term);\r\n }\r\n if (!this.invertedIndex.has(term)) this.invertedIndex.set(term, []);\r\n this.invertedIndex.get(term)!.push(docIdx);\r\n this.df.set(term, (this.df.get(term) ?? 0) + 1);\r\n }\r\n const stored = { ...doc, _tokens: tokens, _tf: tf } as SemanticDocument & {\r\n _tokens: string[];\r\n _tf: Map;\r\n };\r\n this.docs.push(stored as SemanticDocument);\r\n }\r\n this._recomputeIdf();\r\n this._recomputeAvgDocLen();\r\n }\r\n\r\n private _recomputeIdf(): void {\r\n const N = this.docs.length;\r\n if (N === 0) return;\r\n for (const [term, df] of this.df.entries()) {\r\n // Smoothed IDF (BM25 variant)\r\n this.idf.set(term, Math.log((N - df + 0.5) / (df + 0.5) + 1));\r\n }\r\n }\r\n\r\n private _recomputeAvgDocLen(): void {\r\n if (this.docs.length === 0) { this.avgDocLen = 0; return; }\r\n const total = (this.docs as Array)\r\n .reduce((sum, d) => sum + (d._tokens?.length ?? 0), 0);\r\n this.avgDocLen = total / this.docs.length;\r\n }\r\n\r\n clearIndex(): void {\r\n this.docs = [];\r\n this.invertedIndex.clear();\r\n this.idf.clear();\r\n this.df.clear();\r\n this.vocab = [];\r\n this.vocabIndex.clear();\r\n this.avgDocLen = 0;\r\n }\r\n\r\n getIndexSize(): number { return this.docs.length; }\r\n\r\n // ---------------------------------------------------------------------------\r\n // Query expansion\r\n // ---------------------------------------------------------------------------\r\n\r\n expandQuery(query: string): QueryExpansion {\r\n const originalTerms = filterStopWords(tokenise(query));\r\n const synonymsUsed: Record = {};\r\n const expanded = new Set(originalTerms);\r\n\r\n for (const term of originalTerms) {\r\n // Direct synonyms from canonical → synonyms\r\n const direct = STELLAR_SYNONYMS[term];\r\n if (direct?.length) {\r\n for (const syn of direct) expanded.add(syn);\r\n synonymsUsed[term] = direct;\r\n }\r\n // Reverse: term is a synonym of some canonical\r\n const reverse = SYNONYM_REVERSE[term];\r\n if (reverse?.length) {\r\n for (const canonical of reverse) {\r\n expanded.add(canonical);\r\n const canSyns = STELLAR_SYNONYMS[canonical] ?? [];\r\n for (const syn of canSyns) expanded.add(syn);\r\n synonymsUsed[term] = [...(synonymsUsed[term] ?? []), canonical, ...canSyns];\r\n }\r\n }\r\n }\r\n\r\n return {\r\n originalTerms,\r\n expandedTerms: Array.from(expanded),\r\n synonymsUsed,\r\n };\r\n }\r\n\r\n // ---------------------------------------------------------------------------\r\n // Typo correction\r\n // ---------------------------------------------------------------------------\r\n\r\n correctTypo(word: string): TypoCorrection {\r\n if (this.vocab.length === 0 || word.length < 4) {\r\n return { original: word, corrected: word, wasCorreected: false };\r\n }\r\n // Only correct if the word is NOT already in vocab\r\n if (this.vocabIndex.has(word)) {\r\n return { original: word, corrected: word, wasCorreected: false };\r\n }\r\n\r\n let best = word;\r\n let bestDist = Infinity;\r\n for (const vocabTerm of this.vocab) {\r\n // Cheap length-difference guard before running full levenshtein\r\n if (Math.abs(vocabTerm.length - word.length) > 2) continue;\r\n const d = levenshtein(word, vocabTerm);\r\n if (d < bestDist) {\r\n bestDist = d;\r\n best = vocabTerm;\r\n }\r\n }\r\n // Accept correction only if edit distance ≤ 2\r\n if (bestDist <= 2 && best !== word) {\r\n return { original: word, corrected: best, wasCorreected: true };\r\n }\r\n return { original: word, corrected: word, wasCorreected: false };\r\n }\r\n\r\n correctQueryTerms(terms: string[]): { corrected: string[]; corrections: TypoCorrection[] } {\r\n const corrections: TypoCorrection[] = [];\r\n const corrected = terms.map((t) => {\r\n const c = this.correctTypo(t);\r\n corrections.push(c);\r\n return c.corrected;\r\n });\r\n return { corrected, corrections };\r\n }\r\n\r\n // ---------------------------------------------------------------------------\r\n // TF-IDF embedding\r\n // ---------------------------------------------------------------------------\r\n\r\n /**\r\n * Build a TF-IDF vector for a list of terms against the current vocabulary.\r\n * The vector length equals the vocab size.\r\n */\r\n private buildVector(terms: string[], docLen: number): number[] {\r\n const vec = new Array(this.vocab.length).fill(0);\r\n const tf = new Map();\r\n for (const t of terms) tf.set(t, (tf.get(t) ?? 0) + 1);\r\n\r\n for (const [term, rawTf] of tf.entries()) {\r\n const idx = this.vocabIndex.get(term);\r\n if (idx === undefined) continue;\r\n const idfVal = this.idf.get(term) ?? 0;\r\n // BM25-style TF normalisation\r\n const normTf =\r\n (rawTf * (BM25_K1 + 1)) /\r\n (rawTf + BM25_K1 * (1 - BM25_B + BM25_B * (docLen / (this.avgDocLen || 1))));\r\n vec[idx] = normTf * idfVal;\r\n }\r\n return vec;\r\n }\r\n\r\n private dotProduct(a: number[], b: number[]): number {\r\n let dot = 0;\r\n for (let i = 0; i < a.length; i++) dot += a[i] * b[i];\r\n return dot;\r\n }\r\n\r\n private magnitude(v: number[]): number {\r\n return Math.sqrt(v.reduce((s, x) => s + x * x, 0));\r\n }\r\n\r\n private cosineSimilarity(a: number[], b: number[]): number {\r\n const magA = this.magnitude(a);\r\n const magB = this.magnitude(b);\r\n if (magA === 0 || magB === 0) return 0;\r\n return this.dotProduct(a, b) / (magA * magB);\r\n }\r\n\r\n // ---------------------------------------------------------------------------\r\n // Search\r\n // ---------------------------------------------------------------------------\r\n\r\n search(query: string, options: SemanticSearchOptions = {}): SearchResult[] {\r\n const {\r\n topK = 10,\r\n minScore = 0.01,\r\n expandQuery = true,\r\n correctTypos = true,\r\n feedbackBoosts = {},\r\n } = options;\r\n\r\n if (this.docs.length === 0) return [];\r\n\r\n // Step 1 – Tokenise query\r\n let queryTerms = filterStopWords(tokenise(query));\r\n\r\n // Step 2 – Typo correction\r\n const typoResults: TypoCorrection[] = [];\r\n if (correctTypos) {\r\n const { corrected, corrections } = this.correctQueryTerms(queryTerms);\r\n queryTerms = corrected;\r\n typoResults.push(...corrections);\r\n }\r\n\r\n // Step 3 – Synonym expansion\r\n let allQueryTerms = queryTerms;\r\n let expansion: QueryExpansion | null = null;\r\n if (expandQuery) {\r\n expansion = this.expandQuery(queryTerms.join(' '));\r\n allQueryTerms = expansion.expandedTerms;\r\n }\r\n\r\n if (allQueryTerms.length === 0) return [];\r\n\r\n // Step 4 – Build query vector\r\n const queryVec = this.buildVector(allQueryTerms, allQueryTerms.length);\r\n const queryMag = this.magnitude(queryVec);\r\n\r\n // Step 5 – Score documents using cosine similarity\r\n const results: SearchResult[] = [];\r\n\r\n for (let docIdx = 0; docIdx < this.docs.length; docIdx++) {\r\n const doc = this.docs[docIdx] as SemanticDocument & {\r\n _tokens?: string[];\r\n _tf?: Map;\r\n };\r\n const docTokens = doc._tokens ?? filterStopWords(tokenise(doc.text));\r\n const docVec = this.buildVector(docTokens, docTokens.length);\r\n\r\n let score = this.cosineSimilarity(queryVec, docVec);\r\n if (queryMag === 0) score = 0;\r\n\r\n // Step 6 – Apply relevance feedback boost\r\n const feedbackBoost = feedbackBoosts[doc.id] ?? 0;\r\n let feedbackBoosted = false;\r\n if (feedbackBoost !== 0) {\r\n score = Math.min(1, score + feedbackBoost);\r\n feedbackBoosted = feedbackBoost > 0;\r\n }\r\n\r\n if (score < minScore) continue;\r\n\r\n // Step 7 – Find matched terms for explanation\r\n const matchedTerms = allQueryTerms.filter((t) => docTokens.includes(t));\r\n\r\n // Step 8 – Generate explanation\r\n const explanation = this._buildExplanation(\r\n score,\r\n matchedTerms,\r\n queryTerms,\r\n expansion,\r\n typoResults.filter((c) => c.wasCorreected),\r\n feedbackBoosted,\r\n feedbackBoost\r\n );\r\n\r\n results.push({\r\n document: { id: doc.id, text: doc.text, metadata: doc.metadata },\r\n score,\r\n explanation,\r\n matchedTerms,\r\n feedbackBoosted,\r\n });\r\n }\r\n\r\n // Step 9 – Sort by score descending, take topK\r\n results.sort((a, b) => b.score - a.score);\r\n return results.slice(0, topK);\r\n }\r\n\r\n // ---------------------------------------------------------------------------\r\n // Explanation generation\r\n // ---------------------------------------------------------------------------\r\n\r\n private _buildExplanation(\r\n score: number,\r\n matchedTerms: string[],\r\n originalTerms: string[],\r\n expansion: QueryExpansion | null,\r\n corrections: TypoCorrection[],\r\n feedbackBoosted: boolean,\r\n feedbackBoost: number\r\n ): string {\r\n const parts: string[] = [];\r\n\r\n // Relevance score\r\n const pct = Math.round(score * 100);\r\n if (pct >= 80) parts.push(`Very high relevance (${pct}%)`);\r\n else if (pct >= 50) parts.push(`Good relevance (${pct}%)`);\r\n else if (pct >= 20) parts.push(`Moderate relevance (${pct}%)`);\r\n else parts.push(`Low relevance (${pct}%)`);\r\n\r\n // Matched terms\r\n if (matchedTerms.length > 0) {\r\n parts.push(`Matched: ${matchedTerms.slice(0, 5).join(', ')}`);\r\n } else {\r\n parts.push('No direct term matches');\r\n }\r\n\r\n // Synonym expansion\r\n if (expansion) {\r\n const synsUsed = Object.entries(expansion.synonymsUsed)\r\n .filter(([k]) => originalTerms.includes(k))\r\n .map(([k, v]) => `${k} → ${v.slice(0, 2).join('/')}`)\r\n .slice(0, 2);\r\n if (synsUsed.length > 0) parts.push(`Synonyms expanded: ${synsUsed.join('; ')}`);\r\n }\r\n\r\n // Typo corrections\r\n if (corrections.length > 0) {\r\n const corrStr = corrections\r\n .map((c) => `\"${c.original}\" → \"${c.corrected}\"`)\r\n .join(', ');\r\n parts.push(`Typo corrected: ${corrStr}`);\r\n }\r\n\r\n // Feedback boost\r\n if (feedbackBoosted) {\r\n parts.push(`Boosted by your feedback (+${Math.round(feedbackBoost * 100)}%)`);\r\n } else if (feedbackBoost < 0) {\r\n parts.push(`Demoted by your feedback (${Math.round(feedbackBoost * 100)}%)`);\r\n }\r\n\r\n return parts.join(' • ');\r\n }\r\n\r\n // ---------------------------------------------------------------------------\r\n // Utility / compat\r\n // ---------------------------------------------------------------------------\r\n\r\n /**\r\n * Compare two query vectors (legacy cosine utility, kept for compat).\r\n */\r\n compareQueries(queryA: string, queryB: string): number {\r\n const tokA = filterStopWords(tokenise(queryA));\r\n const tokB = filterStopWords(tokenise(queryB));\r\n const vecA = this.buildVector(tokA, tokA.length);\r\n const vecB = this.buildVector(tokB, tokB.length);\r\n return this.cosineSimilarity(vecA, vecB);\r\n }\r\n\r\n /**\r\n * Return a set of query suggestions based on partial input and the current vocab.\r\n */\r\n getSuggestions(partial: string, maxSuggestions = 8): string[] {\r\n const lower = partial.toLowerCase().trim();\r\n if (lower.length < 2) return [];\r\n\r\n const suggestions = new Set();\r\n\r\n // Vocab completions\r\n for (const term of this.vocab) {\r\n if (term.startsWith(lower) && term !== lower) suggestions.add(term);\r\n if (suggestions.size >= maxSuggestions) break;\r\n }\r\n\r\n // Synonym suggestions\r\n for (const [canonical, syns] of Object.entries(STELLAR_SYNONYMS)) {\r\n if (canonical.startsWith(lower)) suggestions.add(canonical);\r\n for (const syn of syns) {\r\n if (syn.startsWith(lower)) suggestions.add(syn);\r\n }\r\n }\r\n\r\n return Array.from(suggestions).slice(0, maxSuggestions);\r\n }\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Singleton for app-wide use\r\n// ---------------------------------------------------------------------------\r\nexport const globalSemanticSearch = new SemanticSearchEngine();\r\n","/**\r\n * Relevance Feedback Store\r\n *\r\n * Captures three types of user signal for a (queryId, documentId) pair:\r\n * - click : user clicked a result (weak positive)\r\n * - thumbsUp : user explicitly marked a result as relevant\r\n * - thumbsDown : user explicitly marked a result as not relevant\r\n *\r\n * Signals are accumulated over sessions using localStorage. A boost value\r\n * between -1 and +1 is derived from the net signal strength and exposed via\r\n * getRelevanceBoost(), which the SemanticSearchEngine uses during ranking.\r\n *\r\n * Boost derivation:\r\n * rawScore = (thumbsUp * 2 + clicks) - (thumbsDown * 2)\r\n * boost = tanh(rawScore / 5) → smoothly bounded to (-1, +1)\r\n *\r\n * The tanh function ensures that a few strong signals produce a meaningful\r\n * boost, while noisy or contradictory signals average out gracefully.\r\n */\r\n\r\n// ---------------------------------------------------------------------------\r\n// Types\r\n// ---------------------------------------------------------------------------\r\n\r\nexport type FeedbackSignal = 'click' | 'thumbsUp' | 'thumbsDown';\r\n\r\nexport interface FeedbackEntry {\r\n queryId: string;\r\n documentId: string;\r\n clicks: number;\r\n thumbsUp: number;\r\n thumbsDown: number;\r\n lastUpdated: number; // Unix ms\r\n}\r\n\r\nexport interface FeedbackStats {\r\n totalEntries: number;\r\n totalClicks: number;\r\n totalThumbsUp: number;\r\n totalThumbsDown: number;\r\n topDocuments: Array<{ documentId: string; boost: number }>;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Storage helpers\r\n// ---------------------------------------------------------------------------\r\n\r\nconst STORAGE_KEY = 'stellar-relevance-feedback-v1';\r\n\r\nfunction loadFromStorage(): Map {\r\n try {\r\n if (typeof localStorage === 'undefined') return new Map();\r\n const raw = localStorage.getItem(STORAGE_KEY);\r\n if (!raw) return new Map();\r\n const entries: FeedbackEntry[] = JSON.parse(raw);\r\n return new Map(entries.map((e) => [`${e.queryId}::${e.documentId}`, e]));\r\n } catch {\r\n return new Map();\r\n }\r\n}\r\n\r\nfunction saveToStorage(store: Map): void {\r\n try {\r\n if (typeof localStorage === 'undefined') return;\r\n const entries = Array.from(store.values());\r\n localStorage.setItem(STORAGE_KEY, JSON.stringify(entries));\r\n } catch {\r\n // localStorage can throw in private browsing or when storage is full\r\n }\r\n}\r\n\r\nfunction composeKey(queryId: string, documentId: string): string {\r\n return `${queryId}::${documentId}`;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Boost maths\r\n// ---------------------------------------------------------------------------\r\n\r\nfunction computeBoost(entry: FeedbackEntry): number {\r\n const rawScore = entry.thumbsUp * 2 + entry.clicks - entry.thumbsDown * 2;\r\n // tanh smoothly maps (-∞,+∞) → (-1,+1) with unit-scale around 0\r\n return Math.tanh(rawScore / 5);\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// RelevanceFeedbackStore\r\n// ---------------------------------------------------------------------------\r\n\r\nexport class RelevanceFeedbackStore {\r\n private store: Map;\r\n\r\n constructor() {\r\n this.store = loadFromStorage();\r\n }\r\n\r\n // ---------------------------------------------------------------------------\r\n // Record signals\r\n // ---------------------------------------------------------------------------\r\n\r\n /**\r\n * Record a user signal for a (queryId, documentId) pair.\r\n *\r\n * @param queryId - A stable identifier for the current query (e.g. normalised query string)\r\n * @param documentId - The document's unique identifier\r\n * @param signal - The type of user interaction\r\n */\r\n record(queryId: string, documentId: string, signal: FeedbackSignal): void {\r\n const key = composeKey(queryId, documentId);\r\n const existing = this.store.get(key) ?? {\r\n queryId,\r\n documentId,\r\n clicks: 0,\r\n thumbsUp: 0,\r\n thumbsDown: 0,\r\n lastUpdated: 0,\r\n };\r\n\r\n switch (signal) {\r\n case 'click':\r\n existing.clicks += 1;\r\n break;\r\n case 'thumbsUp':\r\n existing.thumbsUp += 1;\r\n // Remove any thumbsDown to avoid contradictions accumulating\r\n existing.thumbsDown = Math.max(0, existing.thumbsDown - 1);\r\n break;\r\n case 'thumbsDown':\r\n existing.thumbsDown += 1;\r\n existing.thumbsUp = Math.max(0, existing.thumbsUp - 1);\r\n break;\r\n }\r\n\r\n existing.lastUpdated = Date.now();\r\n this.store.set(key, existing);\r\n saveToStorage(this.store);\r\n }\r\n\r\n // ---------------------------------------------------------------------------\r\n // Retrieve boosts\r\n // ---------------------------------------------------------------------------\r\n\r\n /**\r\n * Get the relevance boost for a specific (queryId, documentId) pair.\r\n * Returns a value in (-1, +1). Positive = boost; negative = demotion.\r\n */\r\n getRelevanceBoost(queryId: string, documentId: string): number {\r\n const key = composeKey(queryId, documentId);\r\n const entry = this.store.get(key);\r\n if (!entry) return 0;\r\n return computeBoost(entry);\r\n }\r\n\r\n /**\r\n * Get a map of { documentId → boost } for all documents associated with a\r\n * given query. Pass the result directly to SemanticSearchEngine.search()\r\n * as the `feedbackBoosts` option.\r\n */\r\n getBoostsForQuery(queryId: string): Record {\r\n const boosts: Record = {};\r\n for (const entry of this.store.values()) {\r\n if (entry.queryId === queryId) {\r\n const boost = computeBoost(entry);\r\n if (boost !== 0) boosts[entry.documentId] = boost;\r\n }\r\n }\r\n return boosts;\r\n }\r\n\r\n /**\r\n * Return raw feedback entry for a (queryId, documentId) pair, or null if\r\n * no feedback has been recorded.\r\n */\r\n getEntry(queryId: string, documentId: string): FeedbackEntry | null {\r\n return this.store.get(composeKey(queryId, documentId)) ?? null;\r\n }\r\n\r\n // ---------------------------------------------------------------------------\r\n // Introspection / management\r\n // ---------------------------------------------------------------------------\r\n\r\n getStats(): FeedbackStats {\r\n let totalClicks = 0;\r\n let totalThumbsUp = 0;\r\n let totalThumbsDown = 0;\r\n const boostMap: Map = new Map();\r\n\r\n for (const entry of this.store.values()) {\r\n totalClicks += entry.clicks;\r\n totalThumbsUp += entry.thumbsUp;\r\n totalThumbsDown += entry.thumbsDown;\r\n\r\n const boost = computeBoost(entry);\r\n const prev = boostMap.get(entry.documentId) ?? 0;\r\n boostMap.set(entry.documentId, Math.max(prev, boost));\r\n }\r\n\r\n const topDocuments = Array.from(boostMap.entries())\r\n .map(([documentId, boost]) => ({ documentId, boost }))\r\n .sort((a, b) => b.boost - a.boost)\r\n .slice(0, 10);\r\n\r\n return {\r\n totalEntries: this.store.size,\r\n totalClicks,\r\n totalThumbsUp,\r\n totalThumbsDown,\r\n topDocuments,\r\n };\r\n }\r\n\r\n /** Remove feedback for a specific document across all queries. */\r\n clearDocument(documentId: string): void {\r\n for (const key of Array.from(this.store.keys())) {\r\n if (key.endsWith(`::${documentId}`)) this.store.delete(key);\r\n }\r\n saveToStorage(this.store);\r\n }\r\n\r\n /** Remove all feedback for a specific query. */\r\n clearQuery(queryId: string): void {\r\n for (const key of Array.from(this.store.keys())) {\r\n if (key.startsWith(`${queryId}::`)) this.store.delete(key);\r\n }\r\n saveToStorage(this.store);\r\n }\r\n\r\n /** Wipe all stored feedback. */\r\n clearAll(): void {\r\n this.store.clear();\r\n saveToStorage(this.store);\r\n }\r\n\r\n /**\r\n * Prune entries older than `maxAgeDays` days.\r\n * Useful to call periodically to prevent unbounded storage growth.\r\n */\r\n pruneOld(maxAgeDays = 90): number {\r\n const cutoff = Date.now() - maxAgeDays * 86_400_000;\r\n let pruned = 0;\r\n for (const [key, entry] of Array.from(this.store.entries())) {\r\n if (entry.lastUpdated < cutoff) {\r\n this.store.delete(key);\r\n pruned++;\r\n }\r\n }\r\n if (pruned > 0) saveToStorage(this.store);\r\n return pruned;\r\n }\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Singleton\r\n// ---------------------------------------------------------------------------\r\nexport const globalRelevanceFeedback = new RelevanceFeedbackStore();\r\n","/**\r\n * useSemanticSearch\r\n *\r\n * React hook that wraps the SemanticSearchEngine + RelevanceFeedbackStore to\r\n * provide a complete semantic search experience:\r\n *\r\n * - Indexes a caller-supplied set of documents on mount (or when they change)\r\n * - Runs a live search as `query` changes (debounced 200 ms)\r\n * - Expands queries with domain synonyms\r\n * - Corrects typos against the index vocabulary\r\n * - Ranks results with TF-IDF + BM25 cosine similarity\r\n * - Applies stored relevance feedback boosts\r\n * - Exposes `recordFeedback()` so the UI can log click / thumbs signals\r\n * - Tracks a \"relevance improvement\" score comparing semantic vs keyword results\r\n *\r\n * Usage:\r\n * const {\r\n * results, loading, query, setQuery,\r\n * typoCorrections, queryExpansion,\r\n * recordFeedback, relevanceImprovement,\r\n * } = useSemanticSearch({ documents, options });\r\n */\r\n\r\nimport { useState, useEffect, useCallback, useRef, useMemo } from 'react';\r\nimport {\r\n SemanticSearchEngine,\r\n SearchResult,\r\n SemanticDocument,\r\n QueryExpansion,\r\n TypoCorrection,\r\n SemanticSearchOptions,\r\n} from '../lib/semanticSearch';\r\nimport {\r\n RelevanceFeedbackStore,\r\n FeedbackSignal,\r\n globalRelevanceFeedback,\r\n} from '../lib/relevanceFeedback';\r\n\r\n// ---------------------------------------------------------------------------\r\n// Types\r\n// ---------------------------------------------------------------------------\r\n\r\nexport interface UseSemanticSearchOptions {\r\n /** Documents to index; engine re-indexes when this reference changes */\r\n documents: SemanticDocument[];\r\n /** Initial query string */\r\n initialQuery?: string;\r\n /** Override default search options */\r\n searchOptions?: Partial;\r\n /**\r\n * Optional external feedback store. Defaults to the app-wide singleton so\r\n * signals persist across sessions.\r\n */\r\n feedbackStore?: RelevanceFeedbackStore;\r\n /** Debounce delay in ms (default: 200) */\r\n debounceMs?: number;\r\n /**\r\n * If provided, a simple keyword search is run in parallel and the\r\n * \"relevanceImprovement\" metric is derived as the ratio of semantic score\r\n * sum to keyword match count.\r\n */\r\n enableImprovementMetric?: boolean;\r\n}\r\n\r\nexport interface UseSemanticSearchResult {\r\n /** Current search query string */\r\n query: string;\r\n /** Set the search query */\r\n setQuery: (q: string) => void;\r\n /** Ranked search results from the semantic engine */\r\n results: SearchResult[];\r\n /** True while the engine is processing */\r\n loading: boolean;\r\n /** Typo corrections applied to the last query */\r\n typoCorrections: TypoCorrection[];\r\n /** Synonym expansion applied to the last query */\r\n queryExpansion: QueryExpansion | null;\r\n /**\r\n * Estimated relevance improvement over keyword search (0–1, higher is better).\r\n * Only populated when `enableImprovementMetric` is true and at least one\r\n * result exists.\r\n */\r\n relevanceImprovement: number | null;\r\n /** Log a user feedback signal for a (queryId, documentId) pair */\r\n recordFeedback: (documentId: string, signal: FeedbackSignal) => void;\r\n /** Total number of indexed documents */\r\n indexSize: number;\r\n /** Autocomplete / query suggestions from the vocabulary */\r\n suggestions: string[];\r\n /** A stable identifier for the current query (normalised lowercase) */\r\n queryId: string;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Normalise query into a stable identifier\r\n// ---------------------------------------------------------------------------\r\nfunction normaliseQueryId(query: string): string {\r\n return query.toLowerCase().trim().replace(/\\s+/g, ' ');\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Simple keyword match count (for improvement metric baseline)\r\n// ---------------------------------------------------------------------------\r\nfunction keywordMatchCount(documents: SemanticDocument[], query: string): number {\r\n const terms = query.toLowerCase().split(/\\s+/).filter(Boolean);\r\n if (terms.length === 0) return 0;\r\n return documents.filter((doc) =>\r\n terms.every((t) => doc.text.toLowerCase().includes(t))\r\n ).length;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Hook\r\n// ---------------------------------------------------------------------------\r\n\r\nexport function useSemanticSearch({\r\n documents,\r\n initialQuery = '',\r\n searchOptions = {},\r\n feedbackStore = globalRelevanceFeedback,\r\n debounceMs = 200,\r\n enableImprovementMetric = true,\r\n}: UseSemanticSearchOptions): UseSemanticSearchResult {\r\n // Engine lives in a ref so it's not re-created on every render\r\n const engineRef = useRef(new SemanticSearchEngine());\r\n\r\n const [query, setQuery] = useState(initialQuery);\r\n const [results, setResults] = useState([]);\r\n const [loading, setLoading] = useState(false);\r\n const [typoCorrections, setTypoCorrections] = useState([]);\r\n const [queryExpansion, setQueryExpansion] = useState(null);\r\n const [relevanceImprovement, setRelevanceImprovement] = useState(null);\r\n const [suggestions, setSuggestions] = useState([]);\r\n const [indexSize, setIndexSize] = useState(0);\r\n\r\n // Stable query id (normalised)\r\n const queryId = useMemo(() => normaliseQueryId(query), [query]);\r\n\r\n // -------------------------------------------------------------------------\r\n // Re-index when documents change\r\n // -------------------------------------------------------------------------\r\n useEffect(() => {\r\n const engine = engineRef.current;\r\n engine.clearIndex();\r\n if (documents.length > 0) {\r\n engine.indexDocuments(documents);\r\n }\r\n setIndexSize(engine.getIndexSize());\r\n // Trigger a fresh search against the new index\r\n if (query.trim()) {\r\n runSearch(query, engine);\r\n }\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, [documents]);\r\n\r\n // -------------------------------------------------------------------------\r\n // Debounced search\r\n // -------------------------------------------------------------------------\r\n const debounceTimer = useRef | null>(null);\r\n\r\n const runSearch = useCallback(\r\n (q: string, engine: SemanticSearchEngine) => {\r\n const trimmed = q.trim();\r\n if (!trimmed) {\r\n setResults([]);\r\n setTypoCorrections([]);\r\n setQueryExpansion(null);\r\n setRelevanceImprovement(null);\r\n setSuggestions([]);\r\n setLoading(false);\r\n return;\r\n }\r\n\r\n setLoading(true);\r\n\r\n // Resolve feedback boosts for the current query\r\n const qId = normaliseQueryId(q);\r\n const feedbackBoosts = feedbackStore.getBoostsForQuery(qId);\r\n\r\n const opts: SemanticSearchOptions = {\r\n topK: 20,\r\n minScore: 0.01,\r\n expandQuery: true,\r\n correctTypos: true,\r\n applyFeedback: true,\r\n ...searchOptions,\r\n feedbackBoosts,\r\n };\r\n\r\n // Run the engine synchronously (all computation is in-memory)\r\n const searchResults = engine.search(trimmed, opts);\r\n\r\n // Extract typo corrections & query expansion from the engine using\r\n // the same pipeline (cheap — the engine exposes these utilities)\r\n const rawTerms = trimmed.toLowerCase().split(/\\s+/).filter(Boolean);\r\n const { corrections } = engine.correctQueryTerms(rawTerms);\r\n const actualCorrections = corrections.filter((c) => c.wasCorreected);\r\n\r\n const expansion = engine.expandQuery(trimmed);\r\n\r\n // Relevance improvement metric\r\n let improvement: number | null = null;\r\n if (enableImprovementMetric && documents.length > 0) {\r\n const kwCount = keywordMatchCount(documents, trimmed);\r\n const semanticScoreSum = searchResults.reduce((s, r) => s + r.score, 0);\r\n if (kwCount > 0 && semanticScoreSum > 0) {\r\n // Normalise: semantic score sum / keyword hit count, capped at 1\r\n improvement = Math.min(1, semanticScoreSum / kwCount);\r\n } else if (kwCount === 0 && searchResults.length > 0) {\r\n // Semantic found results where keyword found none → maximum improvement\r\n improvement = 1;\r\n } else {\r\n improvement = 0;\r\n }\r\n }\r\n\r\n // Suggestions for the current partial query\r\n const sug = engine.getSuggestions(trimmed, 8);\r\n\r\n setResults(searchResults);\r\n setTypoCorrections(actualCorrections);\r\n setQueryExpansion(expansion);\r\n setRelevanceImprovement(improvement);\r\n setSuggestions(sug);\r\n setLoading(false);\r\n },\r\n // searchOptions object reference changes on every render; stringify for stability\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n [feedbackStore, enableImprovementMetric, documents, JSON.stringify(searchOptions)]\r\n );\r\n\r\n useEffect(() => {\r\n if (debounceTimer.current) clearTimeout(debounceTimer.current);\r\n debounceTimer.current = setTimeout(() => {\r\n runSearch(query, engineRef.current);\r\n }, debounceMs);\r\n\r\n return () => {\r\n if (debounceTimer.current) clearTimeout(debounceTimer.current);\r\n };\r\n }, [query, runSearch, debounceMs]);\r\n\r\n // -------------------------------------------------------------------------\r\n // Feedback recorder\r\n // -------------------------------------------------------------------------\r\n const recordFeedback = useCallback(\r\n (documentId: string, signal: FeedbackSignal) => {\r\n feedbackStore.record(queryId, documentId, signal);\r\n // Re-run search immediately so ranking reflects the new feedback\r\n runSearch(query, engineRef.current);\r\n },\r\n [feedbackStore, queryId, query, runSearch]\r\n );\r\n\r\n return {\r\n query,\r\n setQuery,\r\n results,\r\n loading,\r\n typoCorrections,\r\n queryExpansion,\r\n relevanceImprovement,\r\n recordFeedback,\r\n indexSize,\r\n suggestions,\r\n queryId,\r\n };\r\n}\r\n\r\nexport default useSemanticSearch;\r\n","/**\r\n * SemanticSearchPanel\r\n *\r\n * Full-featured semantic search UI component that integrates the\r\n * SemanticSearchEngine and RelevanceFeedbackStore to deliver:\r\n *\r\n * - A search bar with live debounced results\r\n * - Detected query intent badge (powered by NLP engine)\r\n * - Typo-correction notice (e.g. \"Showing results for 'payment'\")\r\n * - Query-expansion badge listing the synonyms applied\r\n * - Relevance improvement indicator vs keyword search\r\n * - Result cards with score bars, match highlights, and search explanations\r\n * - Per-result thumbs-up / thumbs-down feedback buttons\r\n * - Autocomplete suggestions dropdown\r\n */\r\n\r\nimport React, { useState, useCallback, useRef } from 'react';\r\nimport {\r\n Search,\r\n ThumbsUp,\r\n ThumbsDown,\r\n Info,\r\n Zap,\r\n AlertCircle,\r\n ChevronDown,\r\n ChevronUp,\r\n X,\r\n TrendingUp,\r\n Lightbulb,\r\n CheckCircle,\r\n RefreshCw,\r\n} from 'lucide-react';\r\nimport { useSemanticSearch } from '../../hooks/useSemanticSearch';\r\nimport type { SemanticDocument, SearchResult } from '../../lib/semanticSearch';\r\nimport type { FeedbackSignal } from '../../lib/relevanceFeedback';\r\nimport { globalRelevanceFeedback } from '../../lib/relevanceFeedback';\r\n\r\n// ---------------------------------------------------------------------------\r\n// Types\r\n// ---------------------------------------------------------------------------\r\n\r\nexport interface SemanticSearchPanelProps {\r\n /** Documents to search over */\r\n documents: SemanticDocument[];\r\n /** Optional extra class on the root element */\r\n className?: string;\r\n /** Called when user selects a result */\r\n onResultSelect?: (result: SearchResult) => void;\r\n /** Panel title (default: \"Semantic Search\") */\r\n title?: string;\r\n /** Placeholder text for search input */\r\n placeholder?: string;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Helpers\r\n// ---------------------------------------------------------------------------\r\n\r\n/** Score 0-1 → colour */\r\nfunction scoreColor(score: number): string {\r\n if (score >= 0.7) return 'var(--green, #22c55e)';\r\n if (score >= 0.4) return 'var(--cyan, #06b6d4)';\r\n if (score >= 0.2) return 'var(--orange, #f97316)';\r\n return 'var(--text-muted, #6b7280)';\r\n}\r\n\r\n/** Score 0-1 → label */\r\nfunction scoreLabel(score: number): string {\r\n if (score >= 0.7) return 'Excellent';\r\n if (score >= 0.4) return 'Good';\r\n if (score >= 0.2) return 'Fair';\r\n return 'Low';\r\n}\r\n\r\n/** Truncate long text with ellipsis */\r\nfunction truncate(text: string, max: number): string {\r\n return text.length > max ? text.slice(0, max) + '…' : text;\r\n}\r\n\r\n/** Highlight query terms in text */\r\nfunction Highlighted({ text, terms }: { text: string; terms: string[] }) {\r\n if (!terms.length) return <>{text};\r\n const pattern = terms\r\n .filter(Boolean)\r\n .map((t) => t.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'))\r\n .join('|');\r\n if (!pattern) return <>{text};\r\n const regex = new RegExp(`(${pattern})`, 'gi');\r\n const parts = text.split(regex);\r\n return (\r\n <>\r\n {parts.map((part, i) =>\r\n regex.test(part) ? (\r\n \r\n {part}\r\n \r\n ) : (\r\n {part}\r\n )\r\n )}\r\n \r\n );\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Sub-component: single result card\r\n// ---------------------------------------------------------------------------\r\n\r\ninterface ResultCardProps {\r\n result: SearchResult;\r\n queryTerms: string[];\r\n onFeedback: (docId: string, signal: FeedbackSignal) => void;\r\n onSelect?: (result: SearchResult) => void;\r\n}\r\n\r\nfunction ResultCard({ result, queryTerms, onFeedback, onSelect }: ResultCardProps) {\r\n const [expanded, setExpanded] = useState(false);\r\n const [feedbackGiven, setFeedbackGiven] = useState(null);\r\n\r\n const { document: doc, score, explanation, matchedTerms, feedbackBoosted } = result;\r\n\r\n const handleFeedback = (signal: FeedbackSignal) => {\r\n setFeedbackGiven(signal);\r\n onFeedback(doc.id, signal);\r\n };\r\n\r\n const handleClick = () => {\r\n onFeedback(doc.id, 'click');\r\n onSelect?.(result);\r\n };\r\n\r\n return (\r\n \r\n {/* Main row */}\r\n e.key === 'Enter' && handleClick()}\r\n aria-label={`Result: ${truncate(doc.text, 60)}, relevance ${Math.round(score * 100)}%`}\r\n >\r\n {/* Score badge */}\r\n \r\n {/* Score circle */}\r\n \r\n {Math.round(score * 100)}%\r\n \r\n \r\n {scoreLabel(score)}\r\n \r\n \r\n\r\n {/* Content */}\r\n
\r\n {/* Document text */}\r\n \r\n \r\n
\r\n\r\n {/* Metadata badges */}\r\n {doc.metadata && Object.keys(doc.metadata).length > 0 && (\r\n
\r\n {Object.entries(doc.metadata)\r\n .slice(0, 3)\r\n .map(([k, v]) => (\r\n \r\n {k}: {String(v).slice(0, 20)}\r\n \r\n ))}\r\n
\r\n )}\r\n\r\n {/* Matched terms */}\r\n {matchedTerms.length > 0 && (\r\n
\r\n {matchedTerms.slice(0, 6).map((term) => (\r\n \r\n {term}\r\n \r\n ))}\r\n
\r\n )}\r\n \r\n\r\n {/* Actions */}\r\n
\r\n {/* Feedback boosted indicator */}\r\n {feedbackBoosted && (\r\n
\r\n \r\n
\r\n )}\r\n {/* Expand explanation */}\r\n {\r\n e.stopPropagation();\r\n setExpanded((prev) => !prev);\r\n }}\r\n style={iconBtnStyle}\r\n title={expanded ? 'Hide explanation' : 'Why this result?'}\r\n aria-expanded={expanded}\r\n aria-label=\"Toggle explanation\"\r\n >\r\n \r\n \r\n {/* Thumbs up */}\r\n {\r\n e.stopPropagation();\r\n handleFeedback('thumbsUp');\r\n }}\r\n style={{\r\n ...iconBtnStyle,\r\n ...(feedbackGiven === 'thumbsUp'\r\n ? { background: 'rgba(34, 197, 94, 0.2)', borderColor: 'var(--green, #22c55e)', color: 'var(--green, #22c55e)' }\r\n : {}),\r\n }}\r\n title=\"This result is relevant\"\r\n aria-label=\"Mark as relevant\"\r\n aria-pressed={feedbackGiven === 'thumbsUp'}\r\n >\r\n \r\n \r\n {/* Thumbs down */}\r\n {\r\n e.stopPropagation();\r\n handleFeedback('thumbsDown');\r\n }}\r\n style={{\r\n ...iconBtnStyle,\r\n ...(feedbackGiven === 'thumbsDown'\r\n ? { background: 'rgba(239, 68, 68, 0.2)', borderColor: 'var(--red, #ef4444)', color: 'var(--red, #ef4444)' }\r\n : {}),\r\n }}\r\n title=\"This result is not relevant\"\r\n aria-label=\"Mark as not relevant\"\r\n aria-pressed={feedbackGiven === 'thumbsDown'}\r\n >\r\n \r\n \r\n
\r\n \r\n\r\n {/* Score bar */}\r\n
\r\n \r\n
\r\n\r\n {/* Expandable explanation */}\r\n {expanded && (\r\n \r\n
\r\n \r\n {explanation}\r\n
\r\n
\r\n doc id: {doc.id}\r\n
\r\n \r\n )}\r\n \r\n );\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Main component\r\n// ---------------------------------------------------------------------------\r\n\r\nexport default function SemanticSearchPanel({\r\n documents,\r\n className,\r\n onResultSelect,\r\n title = 'Semantic Search',\r\n placeholder = 'Search with natural language (e.g. \"recent XLM payments\", \"failed contracts\")…',\r\n}: SemanticSearchPanelProps) {\r\n const [inputValue, setInputValue] = useState('');\r\n const [showSuggestions, setShowSuggestions] = useState(false);\r\n const inputRef = useRef(null);\r\n\r\n const {\r\n query,\r\n setQuery,\r\n results,\r\n loading,\r\n typoCorrections,\r\n queryExpansion,\r\n relevanceImprovement,\r\n recordFeedback,\r\n indexSize,\r\n suggestions,\r\n } = useSemanticSearch({\r\n documents,\r\n enableImprovementMetric: true,\r\n });\r\n\r\n // Sync the local input with the hook's debounced query\r\n const handleInputChange = (e: React.ChangeEvent) => {\r\n const v = e.target.value;\r\n setInputValue(v);\r\n setQuery(v);\r\n setShowSuggestions(v.length >= 2);\r\n };\r\n\r\n const handleSuggestionClick = (sug: string) => {\r\n setInputValue(sug);\r\n setQuery(sug);\r\n setShowSuggestions(false);\r\n inputRef.current?.focus();\r\n };\r\n\r\n const handleClear = () => {\r\n setInputValue('');\r\n setQuery('');\r\n setShowSuggestions(false);\r\n inputRef.current?.focus();\r\n };\r\n\r\n const handleFeedback = useCallback(\r\n (docId: string, signal: FeedbackSignal) => {\r\n recordFeedback(docId, signal);\r\n },\r\n [recordFeedback]\r\n );\r\n\r\n // Derive query terms for highlighting\r\n const queryTerms = query\r\n .toLowerCase()\r\n .split(/\\s+/)\r\n .filter((t) => t.length >= 2);\r\n\r\n // Active synonyms for the badge\r\n const activeSynonyms = queryExpansion\r\n ? Object.entries(queryExpansion.synonymsUsed)\r\n .filter(([k]) => queryExpansion.originalTerms.includes(k))\r\n .map(([k, v]) => `${k} → ${v.slice(0, 2).join('/')}`)\r\n .slice(0, 3)\r\n : [];\r\n\r\n const hasResults = results.length > 0;\r\n const hasQuery = query.trim().length > 0;\r\n\r\n // Relevance improvement percentage relative to 40% target\r\n const improvementPct = relevanceImprovement !== null\r\n ? Math.round(relevanceImprovement * 100)\r\n : null;\r\n const meetsTarget = improvementPct !== null && improvementPct >= 40;\r\n\r\n return (\r\n \r\n {/* Header */}\r\n
\r\n
\r\n \r\n \r\n {title}\r\n
\r\n
\r\n AI-powered semantic search • {indexSize} documents indexed\r\n
\r\n
\r\n\r\n {/* Relevance improvement badge */}\r\n {improvementPct !== null && hasResults && (\r\n \r\n \r\n {improvementPct}% relevance improvement\r\n \r\n )}\r\n \r\n\r\n {/* Search input */}\r\n
\r\n
\r\n \r\n inputValue.length >= 2 && setShowSuggestions(true)}\r\n onBlur={() => setTimeout(() => setShowSuggestions(false), 150)}\r\n onKeyDown={(e) => {\r\n if (e.key === 'Escape') {\r\n setShowSuggestions(false);\r\n }\r\n }}\r\n placeholder={placeholder}\r\n aria-label=\"Semantic search query\"\r\n aria-autocomplete=\"list\"\r\n aria-expanded={showSuggestions && suggestions.length > 0}\r\n style={{\r\n width: '100%',\r\n padding: '10px 44px 10px 40px',\r\n background: 'var(--bg-elevated)',\r\n border: '1px solid var(--border)',\r\n borderRadius: 'var(--radius-md)',\r\n color: 'var(--text-primary)',\r\n fontSize: '14px',\r\n fontFamily: 'var(--font-sans, sans-serif)',\r\n outline: 'none',\r\n boxSizing: 'border-box',\r\n transition: 'border-color 0.2s',\r\n }}\r\n />\r\n\r\n \r\n {loading && (\r\n \r\n )}\r\n {inputValue && (\r\n \r\n \r\n \r\n )}\r\n
\r\n
\r\n\r\n {/* Autocomplete suggestions */}\r\n {showSuggestions && suggestions.length > 0 && (\r\n \r\n {suggestions.map((sug, idx) => (\r\n handleSuggestionClick(sug)}\r\n style={{\r\n padding: '8px 14px',\r\n cursor: 'pointer',\r\n fontSize: '13px',\r\n color: 'var(--text-primary)',\r\n borderBottom:\r\n idx < suggestions.length - 1 ? '1px solid var(--border)' : 'none',\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: '8px',\r\n }}\r\n onMouseEnter={(e) =>\r\n ((e.currentTarget as HTMLDivElement).style.background = 'var(--bg-elevated)')\r\n }\r\n onMouseLeave={(e) =>\r\n ((e.currentTarget as HTMLDivElement).style.background = 'transparent')\r\n }\r\n >\r\n \r\n {sug}\r\n \r\n ))}\r\n \r\n )}\r\n \r\n\r\n {/* Smart badges row */}\r\n {hasQuery && (\r\n
\r\n {/* Typo corrections */}\r\n {typoCorrections.length > 0 && (\r\n \r\n \r\n Corrected:{' '}\r\n {typoCorrections\r\n .map((c) => `\"${c.original}\" → \"${c.corrected}\"`)\r\n .join(', ')}\r\n
\r\n )}\r\n\r\n {/* Synonym expansion */}\r\n {activeSynonyms.length > 0 && (\r\n \r\n \r\n Expanded: {activeSynonyms.join('; ')}\r\n \r\n )}\r\n\r\n {/* No results hint */}\r\n {!loading && hasQuery && !hasResults && (\r\n \r\n \r\n No results found. Try different keywords or check spelling.\r\n \r\n )}\r\n \r\n )}\r\n\r\n {/* Results */}\r\n {hasResults && (\r\n
\r\n {/* Results header */}\r\n \r\n \r\n {results.length} result{results.length !== 1 ? 's' : ''} for{' '}\r\n \"{query}\"\r\n \r\n \r\n Rate results to improve future searches\r\n \r\n
\r\n\r\n {/* Result cards */}\r\n {results.map((result) => (\r\n \r\n ))}\r\n \r\n )}\r\n\r\n {/* Empty state */}\r\n {!hasQuery && (\r\n \r\n \r\n
\r\n Semantic search understands your intent\r\n
\r\n
\r\n Try queries like{' '}\r\n \"recent XLM transfers\",{' '}\r\n \"failed soroban contracts\", or{' '}\r\n \"payment from testnet account\". Typos and synonyms are\r\n handled automatically.\r\n
\r\n \r\n )}\r\n \r\n );\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Shared micro-styles\r\n// ---------------------------------------------------------------------------\r\nconst iconBtnStyle: React.CSSProperties = {\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n width: '28px',\r\n height: '28px',\r\n background: 'var(--bg-elevated)',\r\n border: '1px solid var(--border)',\r\n borderRadius: 'var(--radius-md)',\r\n color: 'var(--text-primary)',\r\n cursor: 'pointer',\r\n transition: 'background 0.15s, color 0.15s, border-color 0.15s',\r\n flexShrink: 0,\r\n};\r\n","export interface SearchIntent {\r\n type: 'transaction' | 'account' | 'operation' | 'contract' | 'general';\r\n entities: {\r\n addresses?: string[];\r\n amounts?: number[];\r\n assets?: string[];\r\n dateRanges?: Array<{ start?: Date; end?: Date }>;\r\n operationTypes?: string[];\r\n keywords?: string[];\r\n };\r\n query: string;\r\n confidence: number;\r\n}\r\n\r\ninterface ParseResult {\r\n filters: {\r\n addresses?: string[];\r\n amounts?: { min?: number; max?: number };\r\n assets?: string[];\r\n dateRange?: { start?: Date; end?: Date };\r\n operationTypes?: string[];\r\n keywords?: string[];\r\n };\r\n searchTerms: string[];\r\n intent: SearchIntent;\r\n}\r\n\r\nconst INTENT_PATTERNS = {\r\n transaction: [\r\n /transaction(?:s)?\\s+(?:for|from|to|involving)\\s+([A-Z0-9]{56})/i,\r\n /tx(?:s)?\\s+([A-Z0-9]{56})/i,\r\n /payment(?:s)?\\s+(?:to|from)\\s+([A-Z0-9]{56})/i,\r\n /send(?:ing)?\\s+(\\d+(?:\\.\\d+)?)\\s*([A-Z]{3,})?/i,\r\n ],\r\n account: [\r\n /account\\s+([A-Z0-9]{56})/i,\r\n /balance(?:s)?\\s+(?:for|of)\\s+([A-Z0-9]{56})/i,\r\n /who\\s+is\\s+([A-Z0-9]{56})/i,\r\n ],\r\n operation: [\r\n /operation(?:s)?\\s+(?:type|of\\s+type)\\s+(\\w+)/i,\r\n /(create|payment|path_payment|manage_offer|set_options|change_trust|allow_trust|account_merge|inflation|manage_data|bump_sequence)/i,\r\n ],\r\n contract: [\r\n /contract(?:s)?\\s+([A-Z0-9]{56})/i,\r\n /smart\\s+contract\\s+([A-Z0-9]{56})/i,\r\n /invoke\\s+([A-Z0-9]{56})/i,\r\n ],\r\n};\r\n\r\nconst STELLAR_ADDRESS_REGEX = /\\bG[A-Z0-9]{2,55}\\b/g;\r\nconst AMOUNT_REGEX = /(\\d+(?:\\.\\d+)?)\\s*([A-Z]{3,})?/g;\r\nconst ASSET_REGEX = /\\b([A-Z]{3,})\\b/g;\r\nconst OPERATION_KEYWORDS = ['payment', 'create account', 'manage offer', 'set options', 'change trust', 'allow trust', 'account merge', 'inflation', 'manage data', 'bump sequence'];\r\nconst DATE_KEYWORDS = {\r\n today: () => new Date(),\r\n yesterday: () => new Date(Date.now() - 86400000),\r\n 'last week': () => new Date(Date.now() - 7 * 86400000),\r\n 'last month': () => new Date(Date.now() - 30 * 86400000),\r\n};\r\n\r\nexport function classifyIntent(query: string): SearchIntent {\r\n let type: SearchIntent['type'] = 'general';\r\n let confidence = 0.5;\r\n\r\n const lowerQuery = query.toLowerCase();\r\n const conversationalKeywords = ['show me', 'find', 'list', 'look up', 'search', 'display'];\r\n const hasConversationalKeyword = conversationalKeywords.some(keyword => lowerQuery.includes(keyword));\r\n\r\n if (/(transaction|transactions|payment|payments|transfer|transfers|send|sent)/i.test(lowerQuery)) {\r\n type = 'transaction';\r\n confidence = 0.9;\r\n } else if (/(operation|operations|create account|manage offer|set options|change trust|allow trust)/i.test(lowerQuery)) {\r\n type = 'operation';\r\n confidence = 0.84;\r\n } else if (/(account|accounts|balance|wallet)/i.test(lowerQuery)) {\r\n type = 'account';\r\n confidence = 0.85;\r\n } else if (/(contract|smart contract|invoke)/i.test(lowerQuery)) {\r\n type = 'contract';\r\n confidence = 0.88;\r\n }\r\n\r\n if (hasConversationalKeyword && type === 'general') {\r\n confidence = 0.6;\r\n }\r\n\r\n const entities = extractEntities(query);\r\n\r\n return { type, entities, query, confidence };\r\n}\r\n\r\nexport function extractEntities(query: string): SearchIntent['entities'] {\r\n const entities: SearchIntent['entities'] = {};\r\n\r\n const addresses = query.match(STELLAR_ADDRESS_REGEX);\r\n if (addresses && addresses.length > 0) {\r\n entities.addresses = [...new Set(addresses)];\r\n }\r\n\r\n const amounts: number[] = [];\r\n let amountMatch;\r\n const amountRegex = new RegExp(AMOUNT_REGEX);\r\n while ((amountMatch = amountRegex.exec(query)) !== null) {\r\n amounts.push(parseFloat(amountMatch[1]));\r\n if (amountMatch[2]) {\r\n entities.assets = entities.assets || [];\r\n entities.assets.push(amountMatch[2]);\r\n }\r\n }\r\n if (amounts.length > 0) {\r\n entities.amounts = amounts;\r\n }\r\n\r\n const assetMatches = query.match(ASSET_REGEX);\r\n if (assetMatches) {\r\n entities.assets = [...new Set([...(entities.assets || []), ...assetMatches])];\r\n }\r\n\r\n for (const [keyword, dateFunc] of Object.entries(DATE_KEYWORDS)) {\r\n if (query.toLowerCase().includes(keyword)) {\r\n entities.dateRanges = entities.dateRanges || [];\r\n entities.dateRanges.push({ start: dateFunc() });\r\n break;\r\n }\r\n }\r\n\r\n const operationMatches = OPERATION_KEYWORDS.filter((keyword) => query.toLowerCase().includes(keyword));\r\n if (operationMatches.length > 0) {\r\n entities.operationTypes = operationMatches;\r\n }\r\n\r\n const keywordTerms = query\r\n .replace(STELLAR_ADDRESS_REGEX, '')\r\n .replace(AMOUNT_REGEX, '')\r\n .split(/\\s+/)\r\n .filter((term) => term.length > 2 && !['show','me','find','list','look','up','search','display','the','and','for','from','to','all','over','only','those','that','with','last','month','week','today','yesterday'].includes(term.toLowerCase()));\r\n if (keywordTerms.length > 0) {\r\n entities.keywords = [...new Set(keywordTerms)];\r\n }\r\n\r\n return entities;\r\n}\r\n\r\nexport function parseNaturalLanguageQuery(query: string, context?: SearchIntent): ParseResult {\r\n const intent = classifyIntent(query);\r\n const filters: any = {};\r\n\r\n const contextAddresses = context?.entities.addresses;\r\n if (contextAddresses && contextAddresses.length > 0) {\r\n filters.addresses = contextAddresses;\r\n }\r\n\r\n if (intent.entities.addresses && intent.entities.addresses.length > 0) {\r\n filters.addresses = intent.entities.addresses;\r\n }\r\n\r\n if (intent.entities.amounts && intent.entities.amounts.length > 0) {\r\n filters.amounts = {\r\n min: Math.min(...intent.entities.amounts),\r\n max: Math.max(...intent.entities.amounts),\r\n };\r\n }\r\n\r\n if (intent.entities.assets) {\r\n filters.assets = intent.entities.assets;\r\n }\r\n\r\n if (intent.entities.dateRanges && intent.entities.dateRanges.length > 0) {\r\n filters.dateRange = intent.entities.dateRanges[0];\r\n }\r\n\r\n if (intent.entities.operationTypes) {\r\n filters.operationTypes = intent.entities.operationTypes;\r\n }\r\n\r\n if (intent.entities.keywords && intent.entities.keywords.length > 0) {\r\n filters.keywords = intent.entities.keywords;\r\n }\r\n\r\n const searchTerms = query\r\n .replace(STELLAR_ADDRESS_REGEX, '')\r\n .replace(AMOUNT_REGEX, '')\r\n .split(/\\s+/)\r\n .filter(term => term.length > 2 && !['the', 'and', 'for', 'from', 'to', 'show', 'me', 'find', 'list', 'look', 'up', 'search', 'display', 'all', 'over', 'only', 'those', 'that', 'with', 'last', 'month', 'week', 'today', 'yesterday'].includes(term.toLowerCase()));\r\n\r\n return { filters, searchTerms, intent };\r\n}\r\n\r\nexport function buildConversationResponse(query: string, context: SearchIntent | null, results: { total?: number } = {}) {\r\n const parsed = parseNaturalLanguageQuery(query, context ?? undefined);\r\n const summary = `I found a ${parsed.intent.type} request${parsed.filters.amounts ? ' with amount filters' : ''}${parsed.filters.dateRange ? ' and a time window' : ''}. I can refine it further for ${parsed.intent.type === 'contract' ? 'contract interactions' : 'matching Stellar data'}.`;\r\n const suggestions = [\r\n parsed.intent.type === 'transaction' ? 'Show the matching transactions in a table' : 'Show the matching results in a table',\r\n parsed.intent.type === 'account' ? 'Summarize the account activity' : 'Suggest related queries',\r\n 'Export these results as JSON',\r\n ];\r\n const followUpQuestions = [\r\n parsed.intent.type === 'transaction' ? 'Filter these to only successful payments' : 'Narrow the results to a specific account',\r\n parsed.intent.type === 'contract' ? 'Show accounts that interacted with this contract' : 'Show related operations for these results',\r\n ];\r\n\r\n return {\r\n parsed,\r\n summary,\r\n suggestions: [...new Set(suggestions)].slice(0, 3),\r\n followUpQuestions,\r\n resultCount: results.total ?? 0,\r\n };\r\n}\r\n\r\nexport function generateSearchSuggestions(query: string, history: string[]): string[] {\r\n const lowerQuery = query.toLowerCase();\r\n const suggestions: string[] = [];\r\n\r\n const historySuggestions = history\r\n .filter(h => h.toLowerCase().includes(lowerQuery))\r\n .slice(0, 3);\r\n suggestions.push(...historySuggestions);\r\n\r\n if (lowerQuery.includes('payment')) {\r\n suggestions.push('payments to account', 'payment history', 'payment amounts');\r\n }\r\n\r\n if (lowerQuery.includes('account')) {\r\n suggestions.push('account balance', 'account operations', 'account created');\r\n }\r\n\r\n if (lowerQuery.includes('transaction')) {\r\n suggestions.push('transactions today', 'transaction hash', 'transaction status');\r\n }\r\n\r\n return [...new Set(suggestions)].slice(0, 5);\r\n}\r\n\r\nexport function fuzzyMatch(query: string, text: string, threshold: number = 0.6): boolean {\r\n const q = query.toLowerCase();\r\n const t = text.toLowerCase();\r\n\r\n if (t.includes(q)) return true;\r\n\r\n const distance = levenshteinDistance(q, t);\r\n const maxLength = Math.max(q.length, t.length);\r\n const similarity = 1 - distance / maxLength;\r\n\r\n return similarity >= threshold;\r\n}\r\n\r\nfunction levenshteinDistance(a: string, b: string): number {\r\n const matrix: number[][] = [];\r\n\r\n for (let i = 0; i <= b.length; i++) {\r\n matrix[i] = [i];\r\n }\r\n\r\n for (let j = 0; j <= a.length; j++) {\r\n matrix[0][j] = j;\r\n }\r\n\r\n for (let i = 1; i <= b.length; i++) {\r\n for (let j = 1; j <= a.length; j++) {\r\n if (b.charAt(i - 1) === a.charAt(j - 1)) {\r\n matrix[i][j] = matrix[i - 1][j - 1];\r\n } else {\r\n matrix[i][j] = Math.min(\r\n matrix[i - 1][j - 1] + 1,\r\n matrix[i][j - 1] + 1,\r\n matrix[i - 1][j] + 1\r\n );\r\n }\r\n }\r\n }\r\n\r\n return matrix[b.length][a.length];\r\n}\r\n","import React, { useMemo, useState } from 'react';\r\nimport { ArrowRight, Download, Sparkles, Send } from 'lucide-react';\r\nimport {\r\n buildConversationResponse,\r\n type SearchIntent,\r\n} from '../../lib/nlpSearchEngine';\r\n\r\ninterface ConversationalAIInterfaceProps {\r\n onSubmit: (query: string, parsed: ReturnType, intent: SearchIntent | null) => void;\r\n placeholder?: string;\r\n isBusy?: boolean;\r\n resultsSummary?: string;\r\n onExport?: () => void;\r\n}\r\n\r\ntype Message = {\r\n id: string;\r\n role: 'user' | 'assistant';\r\n content: string;\r\n intent?: SearchIntent | null;\r\n suggestions?: string[];\r\n followUps?: string[];\r\n};\r\n\r\nexport default function ConversationalAIInterface({\r\n onSubmit,\r\n placeholder = 'Ask for payments, accounts, contracts, or operations…',\r\n isBusy = false,\r\n resultsSummary,\r\n onExport,\r\n}: ConversationalAIInterfaceProps) {\r\n const [input, setInput] = useState('');\r\n const [messages, setMessages] = useState([\r\n {\r\n id: 'welcome',\r\n role: 'assistant',\r\n content: 'I can help you explore Stellar data with natural language. Try “show me payments over 1000 XLM last month” or “find accounts that interact with contract X”.',\r\n suggestions: [\r\n 'Show me payments over 1000 XLM last month',\r\n 'Find accounts that interact with contract X',\r\n 'List failed transactions from last week',\r\n ],\r\n },\r\n ]);\r\n const [activeIntent, setActiveIntent] = useState(null);\r\n\r\n const latestAssistantMessage = useMemo(() => {\r\n return [...messages].reverse().find((message) => message.role === 'assistant');\r\n }, [messages]);\r\n\r\n const handleSubmit = (event: React.FormEvent) => {\r\n event.preventDefault();\r\n const trimmed = input.trim();\r\n if (!trimmed) return;\r\n\r\n const response = buildConversationResponse(trimmed, activeIntent, { total: 0 });\r\n const nextMessages: Message[] = [\r\n ...messages,\r\n { id: `${Date.now()}-user`, role: 'user', content: trimmed, intent: response.parsed.intent },\r\n {\r\n id: `${Date.now()}-assistant`,\r\n role: 'assistant',\r\n content: response.summary,\r\n intent: response.parsed.intent,\r\n suggestions: response.suggestions,\r\n followUps: response.followUpQuestions,\r\n },\r\n ];\r\n\r\n setMessages(nextMessages);\r\n setActiveIntent(response.parsed.intent);\r\n onSubmit(trimmed, response.parsed, response.parsed.intent);\r\n setInput('');\r\n };\r\n\r\n return (\r\n \r\n
\r\n \r\n Conversational AI assistant\r\n
\r\n\r\n
\r\n {messages.map((message) => (\r\n \r\n
\r\n {message.role === 'assistant' ? 'assistant' : 'you'}\r\n
\r\n
{message.content}
\r\n {message.intent && (\r\n
\r\n Intent: {message.intent.type} • confidence {Math.round(message.intent.confidence * 100)}%\r\n
\r\n )}\r\n {message.suggestions && message.suggestions.length > 0 && (\r\n
\r\n {message.suggestions.slice(0, 3).map((suggestion) => (\r\n {\r\n setInput(suggestion);\r\n }}\r\n style={{\r\n border: '1px solid var(--border)',\r\n borderRadius: '999px',\r\n padding: '4px 8px',\r\n background: 'var(--bg-card)',\r\n cursor: 'pointer',\r\n fontSize: '11px',\r\n color: 'var(--text-primary)',\r\n }}\r\n >\r\n {suggestion}\r\n \r\n ))}\r\n
\r\n )}\r\n {message.followUps && message.followUps.length > 0 && (\r\n
\r\n
Try next:
\r\n
\r\n {message.followUps.slice(0, 2).map((followUp) => (\r\n setInput(followUp)}\r\n style={{\r\n border: '1px solid rgba(6, 182, 212, 0.24)',\r\n borderRadius: '999px',\r\n padding: '4px 8px',\r\n background: 'rgba(6, 182, 212, 0.12)',\r\n cursor: 'pointer',\r\n fontSize: '11px',\r\n color: 'var(--cyan)',\r\n }}\r\n >\r\n {followUp}\r\n \r\n ))}\r\n
\r\n
\r\n )}\r\n
\r\n ))}\r\n \r\n\r\n {resultsSummary && (\r\n
{resultsSummary}
\r\n )}\r\n\r\n
\r\n setInput(event.target.value)}\r\n placeholder={placeholder}\r\n style={{\r\n flex: 1,\r\n padding: '10px 12px',\r\n border: '1px solid var(--border)',\r\n borderRadius: '10px',\r\n background: 'var(--bg-elevated)',\r\n color: 'var(--text-primary)',\r\n }}\r\n />\r\n \r\n {isBusy ? 'Working…' : <> Ask}\r\n \r\n \r\n\r\n
\r\n
\r\n {latestAssistantMessage?.intent ? `Last intent: ${latestAssistantMessage.intent.type}` : 'Ask a question to refine the results.'}\r\n
\r\n {onExport && (\r\n \r\n Export\r\n \r\n )}\r\n
\r\n \r\n );\r\n}\r\n","import React, { useState, useEffect, useMemo } from 'react';\r\nimport {\r\n Search,\r\n Filter,\r\n Calendar,\r\n DollarSign,\r\n Hash,\r\n FileText,\r\n Clock,\r\n ChevronDown,\r\n ChevronUp,\r\n X,\r\n Save,\r\n History,\r\n BarChart3,\r\n Download,\r\n RefreshCw,\r\n SlidersHorizontal,\r\n Tag,\r\n Activity,\r\n Globe,\r\n CheckCircle,\r\n AlertCircle,\r\n Folder,\r\n Share2,\r\n BellRing,\r\n Copy,\r\n Zap,\r\n} from 'lucide-react';\r\nimport advancedSearchService from '../../lib/advancedSearch.js';\r\nimport auditTrail from '../../lib/auditTrail.js';\r\nimport { format } from 'date-fns';\r\nimport SemanticSearchPanel from '../search/SemanticSearchPanel';\r\nimport ConversationalAIInterface from '../search/ConversationalAIInterface';\r\n\r\nexport default function AdvancedSearch() {\r\n const [searchQuery, setSearchQuery] = useState('');\r\n const [searchResults, setSearchResults] = useState(null);\r\n const [loading, setLoading] = useState(false);\r\n const [showFilters, setShowFilters] = useState(false);\r\n const [showHistory, setShowHistory] = useState(false);\r\n const [savedSearches, setSavedSearches] = useState([]);\r\n const [savedFolders, setSavedFolders] = useState([]);\r\n const [searchAnalytics, setSearchAnalytics] = useState(null);\r\n const [searchHistory, setSearchHistory] = useState([]);\r\n const [suggestions, setSuggestions] = useState([]);\r\n const [showSuggestions, setShowSuggestions] = useState(false);\r\n const [selectedTypes, setSelectedTypes] = useState(['transactions', 'operations', 'contracts', 'accounts']);\r\n const [savedSearchFolder, setSavedSearchFolder] = useState('General');\r\n const [createAlertOnSave, setCreateAlertOnSave] = useState(false);\r\n const [alertCron, setAlertCron] = useState('0 * * * *');\r\n const [shareToken, setShareToken] = useState('');\r\n const [semanticMode, setSemanticMode] = useState(false);\r\n\r\n const [filters, setFilters] = useState({\r\n dateRange: { start: '', end: '' },\r\n assetType: '',\r\n operationType: '',\r\n amountRange: { min: '', max: '' },\r\n addressFilter: '',\r\n memoFilter: '',\r\n statusFilter: '',\r\n networkFilter: '',\r\n });\r\n\r\n const [sort, setSort] = useState({\r\n field: 'timestamp',\r\n direction: 'desc'\r\n });\r\n\r\n const [pagination, setPagination] = useState({\r\n page: 1,\r\n limit: 20\r\n });\r\n\r\n /**\r\n * Build a flat array of SemanticDocuments from the advancedSearch indexed\r\n * data so that SemanticSearchPanel can work without duplicating any fetching.\r\n * We generate these from the search history (previous results) + any\r\n * cached result items currently available in advancedSearchService.\r\n */\r\n const semanticDocuments = useMemo(() => {\r\n const docs: Array<{ id: string; text: string; metadata?: Record }> = [];\r\n\r\n // Pull recent search history entries as documents\r\n const history = advancedSearchService.getSearchHistory().slice(0, 30);\r\n history.forEach((entry, idx) => {\r\n const q = entry.query?.text;\r\n if (q) {\r\n docs.push({\r\n id: `history-${idx}`,\r\n text: q,\r\n metadata: {\r\n type: 'search_history',\r\n resultCount: entry.resultCount ?? 0,\r\n timestamp: entry.timestamp ?? '',\r\n },\r\n });\r\n }\r\n });\r\n\r\n // Pull saved searches\r\n advancedSearchService.getSavedSearches().forEach((saved) => {\r\n const q = saved.query?.text;\r\n if (q) {\r\n docs.push({\r\n id: `saved-${saved.id}`,\r\n text: `${saved.name} ${q}`,\r\n metadata: {\r\n type: 'saved_search',\r\n name: saved.name,\r\n folder: saved.folder ?? 'General',\r\n },\r\n });\r\n }\r\n });\r\n\r\n // If we have live search results, include them as indexable items\r\n if (searchResults?.results) {\r\n searchResults.results.forEach((item: any) => {\r\n const textParts = [\r\n item.type,\r\n item.operationType,\r\n item.asset,\r\n item.memo,\r\n item.status,\r\n item.address,\r\n item.transactionHash,\r\n ]\r\n .filter(Boolean)\r\n .join(' ');\r\n if (textParts.trim()) {\r\n docs.push({\r\n id: `result-${item.id}`,\r\n text: textParts,\r\n metadata: {\r\n type: item.type,\r\n status: item.status ?? '',\r\n amount: item.amount ?? '',\r\n },\r\n });\r\n }\r\n });\r\n }\r\n\r\n return docs;\r\n }, [searchResults]);\r\n\r\n useEffect(() => {\r\n loadData();\r\n }, []);\r\n\r\n useEffect(() => {\r\n if (searchQuery.length > 1) {\r\n const newSuggestions = advancedSearchService.getSuggestions(searchQuery);\r\n setSuggestions(newSuggestions);\r\n setShowSuggestions(true);\r\n } else {\r\n setSuggestions([]);\r\n setShowSuggestions(false);\r\n }\r\n }, [searchQuery]);\r\n\r\n const loadData = () => {\r\n setSavedSearches(advancedSearchService.getSavedSearches());\r\n setSavedFolders(advancedSearchService.getSavedSearchFolders());\r\n setSearchHistory(advancedSearchService.getSearchHistory());\r\n setSearchAnalytics(advancedSearchService.getSearchAnalytics());\r\n };\r\n\r\n const handleSearch = async (overrideQuery?: string) => {\r\n const activeQuery = (overrideQuery ?? searchQuery).trim();\r\n if (!activeQuery && !hasActiveFilters()) {\r\n return;\r\n }\r\n\r\n setLoading(true);\r\n try {\r\n const query = {\r\n text: activeQuery,\r\n types: selectedTypes,\r\n filters: buildFilters(),\r\n sort,\r\n page: pagination.page,\r\n limit: pagination.limit\r\n };\r\n\r\n const results = advancedSearchService.search(query);\r\n setSearchResults(results);\r\n if (overrideQuery) {\r\n setSearchQuery(activeQuery);\r\n }\r\n\r\n auditTrail.logUserAction('Performed advanced search', {\r\n query: activeQuery,\r\n types: selectedTypes,\r\n resultCount: results.total,\r\n searchTime: results.searchTime\r\n });\r\n loadData();\r\n\r\n } catch (error) {\r\n auditTrail.logError(error, { operation: 'advancedSearch', query: activeQuery });\r\n console.error('Search failed:', error);\r\n } finally {\r\n setLoading(false);\r\n }\r\n };\r\n\r\n const buildFilters = () => {\r\n const builtFilters = {};\r\n \r\n if (filters.dateRange.start) {\r\n builtFilters.dateRange = { ...builtFilters.dateRange, start: new Date(filters.dateRange.start).getTime() };\r\n }\r\n if (filters.dateRange.end) {\r\n builtFilters.dateRange = { ...builtFilters.dateRange, end: new Date(filters.dateRange.end).getTime() };\r\n }\r\n \r\n if (filters.assetType) builtFilters.assetType = filters.assetType;\r\n if (filters.operationType) builtFilters.operationType = filters.operationType;\r\n if (filters.addressFilter) builtFilters.addressFilter = filters.addressFilter;\r\n if (filters.memoFilter) builtFilters.memoFilter = filters.memoFilter;\r\n if (filters.statusFilter) builtFilters.statusFilter = filters.statusFilter;\r\n if (filters.networkFilter) builtFilters.networkFilter = filters.networkFilter;\r\n \r\n if (filters.amountRange.min) {\r\n builtFilters.amountRange = { ...builtFilters.amountRange, min: parseFloat(filters.amountRange.min) };\r\n }\r\n if (filters.amountRange.max) {\r\n builtFilters.amountRange = { ...builtFilters.amountRange, max: parseFloat(filters.amountRange.max) };\r\n }\r\n \r\n return builtFilters;\r\n };\r\n\r\n const hasActiveFilters = () => {\r\n return Object.values(filters).some(value => {\r\n if (typeof value === 'object' && value !== null) {\r\n return Object.values(value).some(v => v !== '');\r\n }\r\n return value !== '';\r\n });\r\n };\r\n\r\n const clearFilters = () => {\r\n setFilters({\r\n dateRange: { start: '', end: '' },\r\n assetType: '',\r\n operationType: '',\r\n amountRange: { min: '', max: '' },\r\n addressFilter: '',\r\n memoFilter: '',\r\n statusFilter: '',\r\n networkFilter: '',\r\n });\r\n advancedSearchService.resetFilters();\r\n };\r\n\r\n const saveSearch = () => {\r\n const name = prompt('Enter a name for this search:');\r\n if (name) {\r\n const query = {\r\n text: searchQuery.trim(),\r\n types: selectedTypes,\r\n filters: buildFilters(),\r\n sort\r\n };\r\n const saved = advancedSearchService.saveSearch(name, query, { folder: savedSearchFolder });\r\n if (createAlertOnSave) {\r\n advancedSearchService.createSearchAlert({\r\n savedSearchId: saved.id,\r\n name: `${name} alert`,\r\n cron: alertCron,\r\n channels: ['in-app'],\r\n });\r\n }\r\n loadData();\r\n \r\n auditTrail.logUserAction('Saved search', { name, query });\r\n }\r\n };\r\n\r\n const loadSavedSearch = (savedSearch) => {\r\n const selectedSearch = advancedSearchService.loadSavedSearch(savedSearch.id) || savedSearch;\r\n setSearchQuery(selectedSearch.query.text || '');\r\n setSelectedTypes(selectedSearch.query.types || ['transactions', 'operations']);\r\n \r\n // Reset filters and load saved ones\r\n clearFilters();\r\n if (selectedSearch.query.filters) {\r\n setFilters({ ...filters, ...selectedSearch.query.filters });\r\n }\r\n \r\n if (selectedSearch.query.sort) {\r\n setSort(selectedSearch.query.sort);\r\n }\r\n \r\n setShowHistory(false);\r\n loadData();\r\n handleSearch();\r\n };\r\n\r\n const shareSavedSearch = (event, savedSearch) => {\r\n event.stopPropagation();\r\n const token = advancedSearchService.shareSearch(savedSearch.id);\r\n setShareToken(token);\r\n loadData();\r\n };\r\n\r\n const exportResults = () => {\r\n if (!searchResults) return;\r\n \r\n const data = JSON.stringify(searchResults, null, 2);\r\n const blob = new Blob([data], { type: 'application/json' });\r\n const url = URL.createObjectURL(blob);\r\n const a = document.createElement('a');\r\n a.href = url;\r\n a.download = `stellar-search-results-${Date.now()}.json`;\r\n a.click();\r\n URL.revokeObjectURL(url);\r\n \r\n auditTrail.logUserAction('Exported search results', { resultCount: searchResults.total });\r\n };\r\n\r\n const handleSuggestionClick = (suggestion) => {\r\n setSearchQuery(suggestion);\r\n setShowSuggestions(false);\r\n };\r\n\r\n const handleTypeToggle = (type) => {\r\n setSelectedTypes(prev => \r\n prev.includes(type) \r\n ? prev.filter(t => t !== type)\r\n : [...prev, type]\r\n );\r\n };\r\n\r\n return (\r\n
\r\n {/* Header */}\r\n
\r\n
\r\n \r\n Advanced Search\r\n
\r\n
\r\n Global search across transactions, operations, contracts, and accounts\r\n
\r\n
\r\n\r\n {/* Semantic mode toggle */}\r\n
\r\n setSemanticMode(false)}\r\n style={{\r\n padding: '6px 14px',\r\n borderRadius: '999px',\r\n border: `1px solid ${!semanticMode ? 'var(--cyan)' : 'var(--border)'}`,\r\n background: !semanticMode ? 'rgba(6, 182, 212, 0.12)' : 'var(--bg-elevated)',\r\n color: !semanticMode ? 'var(--cyan)' : 'var(--text-muted)',\r\n fontSize: '12px',\r\n fontWeight: 600,\r\n cursor: 'pointer',\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: '5px',\r\n transition: 'all 0.15s',\r\n }}\r\n >\r\n Keyword Search\r\n \r\n setSemanticMode(true)}\r\n style={{\r\n padding: '6px 14px',\r\n borderRadius: '999px',\r\n border: `1px solid ${semanticMode ? 'var(--cyan)' : 'var(--border)'}`,\r\n background: semanticMode ? 'rgba(6, 182, 212, 0.12)' : 'var(--bg-elevated)',\r\n color: semanticMode ? 'var(--cyan)' : 'var(--text-muted)',\r\n fontSize: '12px',\r\n fontWeight: 600,\r\n cursor: 'pointer',\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: '5px',\r\n transition: 'all 0.15s',\r\n }}\r\n >\r\n Semantic Search\r\n AI\r\n \r\n {semanticMode && (\r\n \r\n Understands synonyms, typos, and intent. Rate results to improve ranking.\r\n \r\n )}\r\n
\r\n\r\n {/* Semantic Search Panel */}\r\n {semanticMode && (\r\n \r\n \r\n
\r\n )}\r\n\r\n {/* Conversational AI assistant */}\r\n {!semanticMode && (\r\n {\r\n setSearchQuery(query);\r\n const queryPayload = {\r\n text: query,\r\n types: selectedTypes,\r\n filters: {\r\n ...buildFilters(),\r\n ...(parsed.filters.addresses ? { addressFilter: parsed.filters.addresses[0] } : {}),\r\n ...(parsed.filters.amounts ? { amountRange: { min: parsed.filters.amounts.min?.toString() ?? '', max: parsed.filters.amounts.max?.toString() ?? '' } } : {}),\r\n },\r\n sort,\r\n page: pagination.page,\r\n limit: pagination.limit,\r\n };\r\n setSearchResults(advancedSearchService.search(queryPayload));\r\n loadData();\r\n }}\r\n placeholder=\"Ask for payments, accounts, contracts, or operations\"\r\n isBusy={loading}\r\n resultsSummary={searchResults ? `${searchResults.total ?? 0} results ready for review.` : undefined}\r\n onExport={() => exportResults()}\r\n />\r\n )}\r\n\r\n {/* Search Bar — keyword mode only */}\r\n {!semanticMode && (\r\n \r\n {/* Main Search Input */}\r\n
\r\n \r\n setSearchQuery(e.target.value)}\r\n onKeyPress={(e) => e.key === 'Enter' && handleSearch()}\r\n placeholder=\"Search transactions, operations, contracts, accounts...\"\r\n style={{\r\n ...inputStyle,\r\n paddingLeft: '40px',\r\n paddingRight: '120px',\r\n fontSize: '14px',\r\n }}\r\n />\r\n \r\n
\r\n setShowHistory(!showHistory)}\r\n style={{ ...iconButtonStyle, title: 'Search History' }}\r\n >\r\n \r\n \r\n \r\n \r\n \r\n \r\n {loading ? : }\r\n \r\n
\r\n\r\n {/* Suggestions */}\r\n {showSuggestions && suggestions.length > 0 && (\r\n
\r\n {suggestions.map((suggestion, index) => (\r\n handleSuggestionClick(suggestion)}\r\n style={{\r\n padding: '8px 12px',\r\n cursor: 'pointer',\r\n fontSize: '13px',\r\n color: 'var(--text-primary)',\r\n borderBottom: '1px solid var(--border)',\r\n }}\r\n onMouseEnter={(e) => e.target.style.background = 'var(--bg-card)'}\r\n onMouseLeave={(e) => e.target.style.background = 'transparent'}\r\n >\r\n {suggestion}\r\n
\r\n ))}\r\n
\r\n )}\r\n \r\n\r\n {/* Type Selection */}\r\n
\r\n
Search in:
\r\n
\r\n {['transactions', 'operations', 'contracts', 'accounts'].map(type => (\r\n handleTypeToggle(type)}\r\n style={{\r\n ...chipStyle,\r\n background: selectedTypes.includes(type) ? 'var(--cyan)' : 'var(--bg-elevated)',\r\n color: selectedTypes.includes(type) ? 'white' : 'var(--text-primary)',\r\n }}\r\n >\r\n {type}\r\n \r\n ))}\r\n
\r\n
\r\n\r\n {/* Saved Query Options */}\r\n
\r\n \r\n\r\n \r\n\r\n \r\n
\r\n\r\n {/* Filter Toggle */}\r\n
\r\n setShowFilters(!showFilters)}\r\n style={{\r\n display: 'inline-flex',\r\n alignItems: 'center',\r\n gap: '6px',\r\n padding: '8px 12px',\r\n background: 'var(--bg-elevated)',\r\n border: '1px solid var(--border)',\r\n borderRadius: 'var(--radius-md)',\r\n color: 'var(--text-primary)',\r\n fontSize: '12px',\r\n cursor: 'pointer',\r\n }}\r\n >\r\n \r\n {showFilters ? 'Hide Filters' : 'Show Filters'}\r\n {showFilters ? : }\r\n \r\n\r\n {hasActiveFilters() && (\r\n \r\n \r\n Clear Filters\r\n \r\n )}\r\n
\r\n\r\n {/* Advanced Filters */}\r\n {showFilters && (\r\n
\r\n
\r\n {/* Date Range */}\r\n
\r\n \r\n
\r\n setFilters(prev => ({ \r\n ...prev, \r\n dateRange: { ...prev.dateRange, start: e.target.value }\r\n }))}\r\n style={{ ...inputStyle, fontSize: '12px' }}\r\n />\r\n setFilters(prev => ({ \r\n ...prev, \r\n dateRange: { ...prev.dateRange, end: e.target.value }\r\n }))}\r\n style={{ ...inputStyle, fontSize: '12px' }}\r\n />\r\n
\r\n
\r\n\r\n {/* Asset Type */}\r\n
\r\n \r\n setFilters(prev => ({ ...prev, assetType: e.target.value }))}\r\n style={{ ...inputStyle, fontSize: '12px' }}\r\n >\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n\r\n {/* Operation Type */}\r\n
\r\n \r\n setFilters(prev => ({ ...prev, operationType: e.target.value }))}\r\n style={{ ...inputStyle, fontSize: '12px' }}\r\n >\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n\r\n {/* Amount Range */}\r\n
\r\n \r\n
\r\n setFilters(prev => ({ \r\n ...prev, \r\n amountRange: { ...prev.amountRange, min: e.target.value }\r\n }))}\r\n style={{ ...inputStyle, fontSize: '12px' }}\r\n />\r\n setFilters(prev => ({ \r\n ...prev, \r\n amountRange: { ...prev.amountRange, max: e.target.value }\r\n }))}\r\n style={{ ...inputStyle, fontSize: '12px' }}\r\n />\r\n
\r\n
\r\n\r\n {/* Address Filter */}\r\n
\r\n \r\n setFilters(prev => ({ ...prev, addressFilter: e.target.value }))}\r\n style={{ ...inputStyle, fontSize: '12px' }}\r\n />\r\n
\r\n\r\n {/* Memo Filter */}\r\n
\r\n \r\n setFilters(prev => ({ ...prev, memoFilter: e.target.value }))}\r\n style={{ ...inputStyle, fontSize: '12px' }}\r\n />\r\n
\r\n\r\n {/* Status Filter */}\r\n
\r\n \r\n setFilters(prev => ({ ...prev, statusFilter: e.target.value }))}\r\n style={{ ...inputStyle, fontSize: '12px' }}\r\n >\r\n \r\n \r\n \r\n \r\n \r\n
\r\n\r\n {/* Network Filter */}\r\n
\r\n \r\n setFilters(prev => ({ ...prev, networkFilter: e.target.value }))}\r\n style={{ ...inputStyle, fontSize: '12px' }}\r\n >\r\n \r\n \r\n \r\n \r\n \r\n
\r\n
\r\n
\r\n )}\r\n \r\n )}\r\n\r\n {/* Search History */}\r\n {showHistory && (\r\n \r\n
\r\n Search History & Saved Searches\r\n \r\n
\r\n\r\n {searchAnalytics && (\r\n
\r\n \r\n \r\n \r\n \r\n
\r\n )}\r\n\r\n
\r\n {/* Folders */}\r\n
\r\n
Folders
\r\n
\r\n {savedFolders.map((folder) => (\r\n {\r\n setSavedSearchFolder(folder.name);\r\n setSavedSearches(advancedSearchService.getSavedSearches({ folder: folder.name }));\r\n }}\r\n style={{\r\n padding: '8px 12px',\r\n background: savedSearchFolder === folder.name ? 'var(--cyan-glow)' : 'var(--bg-elevated)',\r\n border: `1px solid ${savedSearchFolder === folder.name ? 'var(--cyan-dim)' : 'var(--border)'}`,\r\n borderRadius: 'var(--radius-md)',\r\n cursor: 'pointer',\r\n fontSize: '12px',\r\n color: 'var(--text-primary)',\r\n display: 'flex',\r\n justifyContent: 'space-between',\r\n }}\r\n >\r\n {folder.name}\r\n {folder.count}\r\n \r\n ))}\r\n
\r\n
\r\n\r\n {/* Recent Searches */}\r\n
\r\n
Recent Searches
\r\n
\r\n {searchHistory.slice(0, 5).map((item, index) => (\r\n {\r\n setSearchQuery(item.query.text || '');\r\n setShowHistory(false);\r\n }}\r\n style={{\r\n padding: '8px 12px',\r\n background: 'var(--bg-elevated)',\r\n border: '1px solid var(--border)',\r\n borderRadius: 'var(--radius-md)',\r\n cursor: 'pointer',\r\n fontSize: '12px',\r\n }}\r\n >\r\n
{item.query.text || 'Empty search'}
\r\n
\r\n {format(new Date(item.timestamp), 'MMM dd, HH:mm')} / {item.resultCount || 0} results / {item.cached ? 'cached' : `${item.searchTime || 0}ms`}\r\n
\r\n
\r\n ))}\r\n
\r\n
\r\n\r\n {/* Saved Searches */}\r\n
\r\n
Saved Searches
\r\n
\r\n {savedSearches.slice(0, 5).map((item, index) => (\r\n loadSavedSearch(item)}\r\n style={{\r\n padding: '8px 12px',\r\n background: 'var(--bg-elevated)',\r\n border: '1px solid var(--border)',\r\n borderRadius: 'var(--radius-md)',\r\n cursor: 'pointer',\r\n fontSize: '12px',\r\n }}\r\n >\r\n
\r\n
{item.name}
\r\n \r\n
\r\n
\r\n {item.folder || 'General'} / {item.query.text || 'No query'} / used {item.usageCount || 0}x\r\n
\r\n
\r\n ))}\r\n {shareToken && (\r\n
\r\n \r\n {shareToken}\r\n
\r\n )}\r\n
\r\n \r\n \r\n \r\n )}\r\n\r\n\r\n {/* Search Results */}\r\n {!semanticMode && searchResults && (\r\n \r\n {/* Results Header */}\r\n
\r\n
\r\n
\r\n {searchResults.total} results found\r\n
\r\n
\r\n Search completed in {searchResults.searchTime}ms{searchResults.cached ? ' from cache' : ''}\r\n
\r\n {searchResults.queryPlan && (\r\n
\r\n {searchResults.queryPlan.usesIndex ? 'Index-assisted' : 'Scan'} / {searchResults.queryPlan.filterCount} filters / cache TTL {Math.round(searchResults.queryPlan.cacheTtlMs / 1000)}s\r\n
\r\n )}\r\n
\r\n \r\n
\r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n
\r\n\r\n {/* Results Body */}\r\n {searchResults.results.length === 0 ? (\r\n
\r\n No results found for your search criteria.\r\n
\r\n ) : (\r\n
\r\n {/* Aggregations */}\r\n {searchResults.aggregations && (\r\n
\r\n
Results Overview
\r\n
\r\n \r\n \r\n \r\n \r\n
\r\n
\r\n )}\r\n\r\n {/* Results List */}\r\n
\r\n {searchResults.results.map((result, index) => (\r\n \r\n ))}\r\n
\r\n\r\n {/* Pagination */}\r\n {searchResults.totalPages > 1 && (\r\n
\r\n setPagination(prev => ({ ...prev, page: Math.max(1, prev.page - 1) }))}\r\n disabled={searchResults.page === 1}\r\n style={paginationButtonStyle}\r\n >\r\n Previous\r\n \r\n \r\n \r\n Page {searchResults.page} of {searchResults.totalPages}\r\n \r\n \r\n setPagination(prev => ({ ...prev, page: Math.min(searchResults.totalPages, prev.page + 1) }))}\r\n disabled={searchResults.page === searchResults.totalPages}\r\n style={paginationButtonStyle}\r\n >\r\n Next\r\n \r\n
\r\n )}\r\n
\r\n )}\r\n \r\n )}\r\n \r\n );\r\n}\r\n\r\nfunction SearchResultItem({ result }) {\r\n const [expanded, setExpanded] = useState(false);\r\n\r\n const getTypeIcon = (type) => {\r\n const icons = {\r\n transactions: ,\r\n operations: ,\r\n contracts: ,\r\n accounts: \r\n };\r\n return icons[type] || ;\r\n };\r\n\r\n const getTypeColor = (type) => {\r\n const colors = {\r\n transactions: 'var(--blue)',\r\n operations: 'var(--green)',\r\n contracts: 'var(--purple)',\r\n accounts: 'var(--orange)'\r\n };\r\n return colors[type] || 'var(--text-secondary)';\r\n };\r\n\r\n return (\r\n
\r\n setExpanded(!expanded)}\r\n >\r\n
\r\n
\r\n
\r\n {getTypeIcon(result.type)}\r\n
\r\n \r\n
\r\n
\r\n {result.type.charAt(0).toUpperCase() + result.type.slice(1)}\r\n {result.operationType && ` • ${result.operationType}`}\r\n
\r\n \r\n
\r\n {result.address && Address: {result.address.substring(0, 16)}... }\r\n {result.asset && Asset: {result.asset} }\r\n {result.amount && Amount: {result.amount} }\r\n {result.status && Status: {result.status}}\r\n
\r\n \r\n
\r\n {new Date(result.timestamp).toLocaleString()}\r\n
\r\n
\r\n
\r\n \r\n
\r\n {expanded ? : }\r\n
\r\n
\r\n
\r\n \r\n {expanded && (\r\n
\r\n
\r\n            {JSON.stringify(result.data, null, 2)}\r\n          
\r\n
\r\n )}\r\n \r\n );\r\n}\r\n\r\nfunction AggregationChip({ label, data }) {\r\n const entries = Object.entries(data).slice(0, 3);\r\n \r\n return (\r\n
\r\n {label}:\r\n {entries.map(([key, value], index) => (\r\n \r\n {key} ({value})\r\n {index < entries.length - 1 && ', '}\r\n \r\n ))}\r\n {Object.keys(data).length > 3 && '...'}\r\n
\r\n );\r\n}\r\n\r\nconst inputStyle = {\r\n width: '100%',\r\n padding: '8px 12px',\r\n background: 'var(--bg-elevated)',\r\n border: '1px solid var(--border)',\r\n borderRadius: 'var(--radius-md)',\r\n color: 'var(--text-primary)',\r\n fontSize: '13px',\r\n fontFamily: 'var(--font-mono)',\r\n outline: 'none',\r\n};\r\n\r\nconst labelStyle = {\r\n fontSize: '12px',\r\n color: 'var(--text-muted)',\r\n textTransform: 'uppercase',\r\n letterSpacing: '0.5px',\r\n display: 'flex',\r\n alignItems: 'center',\r\n marginBottom: '6px',\r\n};\r\n\r\nconst chipStyle = {\r\n padding: '4px 12px',\r\n background: 'var(--bg-elevated)',\r\n border: '1px solid var(--border)',\r\n borderRadius: '999px',\r\n fontSize: '12px',\r\n cursor: 'pointer',\r\n transition: 'var(--transition)',\r\n};\r\n\r\nconst iconButtonStyle = {\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n width: '32px',\r\n height: '32px',\r\n background: 'var(--bg-elevated)',\r\n border: '1px solid var(--border)',\r\n borderRadius: 'var(--radius-md)',\r\n color: 'var(--text-primary)',\r\n cursor: 'pointer',\r\n transition: 'var(--transition)',\r\n};\r\n\r\nconst paginationButtonStyle = {\r\n padding: '6px 12px',\r\n background: 'var(--bg-elevated)',\r\n border: '1px solid var(--border)',\r\n borderRadius: 'var(--radius-md)',\r\n color: 'var(--text-primary)',\r\n fontSize: '12px',\r\n cursor: 'pointer',\r\n transition: 'var(--transition)',\r\n};\r\n"],"names":["STORAGE_KEYS","getBrowserStorage","readStoredArray","storage","key","fallback","parsed","writeStoredArray","value","stableStringify","makeId","prefix","encodeSharePayload","payload","serialized","decodeSharePayload","token","AdvancedSearchService","options","type","data","indexed","item","term","baseItem","terms","word","extractStrings","obj","fullKey","code","query","startTime","optimizedQuery","queryPlan","cacheKey","cached","cachedResult","results","items","paginatedResults","searchTime","response","error","searchText","searchTerms","indexedItems","field","direction","b","aValue","bValue","comparison","page","limit","startIndex","endIndex","aggregations","amountCount","text","types","result","entry","indexedTerms","filterCount","nested","meta","historyEntry","name","folder","savedSearch","search","a","id","normalizedName","existing","shareToken","input","alert","cronExpression","from","minute","hour","next","now","counts","count","history","totalSearchTime","sum","partial","suggestions","lowerPartial","asset","total","advancedSearchService","STELLAR_SYNONYMS","SYNONYM_REVERSE","canonical","synonyms","syn","BM25_K1","BM25_B","levenshtein","m","n","dp","_","i","j","tokenise","t","STOP_WORDS","filterStopWords","tokens","SemanticSearchEngine","__publicField","doc","docIdx","tf","stored","docs","N","df","d","originalTerms","synonymsUsed","expanded","direct","reverse","canSyns","best","bestDist","vocabTerm","corrections","c","docLen","vec","rawTf","idx","idfVal","normTf","dot","v","s","x","magA","magB","topK","minScore","expandQuery","correctTypos","feedbackBoosts","queryTerms","typoResults","corrected","allQueryTerms","expansion","queryVec","queryMag","docTokens","docVec","score","feedbackBoost","feedbackBoosted","matchedTerms","explanation","parts","pct","synsUsed","k","corrStr","queryA","queryB","tokA","tokB","vecA","vecB","maxSuggestions","lower","syns","STORAGE_KEY","loadFromStorage","raw","entries","e","saveToStorage","store","composeKey","queryId","documentId","computeBoost","rawScore","RelevanceFeedbackStore","signal","boosts","boost","totalClicks","totalThumbsUp","totalThumbsDown","boostMap","prev","topDocuments","maxAgeDays","cutoff","pruned","globalRelevanceFeedback","normaliseQueryId","keywordMatchCount","documents","useSemanticSearch","initialQuery","searchOptions","feedbackStore","debounceMs","enableImprovementMetric","engineRef","useRef","setQuery","useState","setResults","loading","setLoading","typoCorrections","setTypoCorrections","queryExpansion","setQueryExpansion","relevanceImprovement","setRelevanceImprovement","setSuggestions","indexSize","setIndexSize","useMemo","useEffect","engine","runSearch","debounceTimer","useCallback","q","trimmed","qId","opts","searchResults","rawTerms","actualCorrections","improvement","kwCount","semanticScoreSum","r","sug","recordFeedback","scoreColor","scoreLabel","truncate","max","Highlighted","pattern","jsx","Fragment","regex","part","React","ResultCard","onFeedback","onSelect","setExpanded","feedbackGiven","setFeedbackGiven","handleFeedback","handleClick","jsxs","TrendingUp","iconBtnStyle","Info","ThumbsUp","ThumbsDown","Lightbulb","SemanticSearchPanel","className","onResultSelect","title","placeholder","inputValue","setInputValue","showSuggestions","setShowSuggestions","inputRef","handleInputChange","handleSuggestionClick","handleClear","docId","activeSynonyms","hasResults","hasQuery","improvementPct","meetsTarget","Zap","Search","RefreshCw","X","CheckCircle","AlertCircle","STELLAR_ADDRESS_REGEX","AMOUNT_REGEX","ASSET_REGEX","OPERATION_KEYWORDS","DATE_KEYWORDS","classifyIntent","confidence","lowerQuery","hasConversationalKeyword","keyword","entities","extractEntities","addresses","amounts","amountMatch","amountRegex","assetMatches","dateFunc","operationMatches","keywordTerms","parseNaturalLanguageQuery","context","intent","filters","contextAddresses","buildConversationResponse","summary","followUpQuestions","ConversationalAIInterface","onSubmit","isBusy","resultsSummary","onExport","setInput","messages","setMessages","activeIntent","setActiveIntent","latestAssistantMessage","message","handleSubmit","event","nextMessages","Sparkles","suggestion","followUp","Send","Download","AdvancedSearch","searchQuery","setSearchQuery","setSearchResults","showFilters","setShowFilters","showHistory","setShowHistory","savedSearches","setSavedSearches","savedFolders","setSavedFolders","searchAnalytics","setSearchAnalytics","searchHistory","setSearchHistory","selectedTypes","setSelectedTypes","savedSearchFolder","setSavedSearchFolder","createAlertOnSave","setCreateAlertOnSave","alertCron","setAlertCron","setShareToken","semanticMode","setSemanticMode","setFilters","sort","setSort","pagination","setPagination","semanticDocuments","saved","textParts","loadData","newSuggestions","handleSearch","overrideQuery","activeQuery","hasActiveFilters","buildFilters","auditTrail","builtFilters","clearFilters","saveSearch","loadSavedSearch","selectedSearch","shareSavedSearch","exportResults","blob","url","handleTypeToggle","queryPayload","inputStyle","iconButtonStyle","History","Save","index","chipStyle","Folder","BellRing","SlidersHorizontal","ChevronUp","ChevronDown","labelStyle","Calendar","Tag","Activity","DollarSign","Hash","FileText","Globe","format","Share2","Copy","AggregationChip","SearchResultItem","paginationButtonStyle","getTypeIcon","getTypeColor","label"],"mappings":"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"} \ No newline at end of file diff --git a/dist/assets/Analytics-BCF9lBrz.js b/dist/assets/Analytics-BCF9lBrz.js new file mode 100644 index 00000000..02b51d94 --- /dev/null +++ b/dist/assets/Analytics-BCF9lBrz.js @@ -0,0 +1,3 @@ +import{r as u,j as t}from"./react-vendor-C-OVADYf.js";import{a6 as de,S,a7 as pe,a8 as ue}from"./charts-D9P2NM_R.js";import{aC as O,D as ye,a7 as me,F as ge,aD as he,an as ve,aE as xe,H as be,aF as fe,aG as we}from"./icons-vendor-C7uAdRPq.js";import"./vendor-CdKO02NA.js";import"./deployment-q_dUxQhv.js";import"./stellar-sdk-Cld1ipgo.js";import"./date-vendor-boStncAG.js";import"./charts-vendor-BYXr-dPO.js";const ke={public:"https://horizon.stellar.org",testnet:"https://horizon-testnet.stellar.org"},je={accounts:"/accounts",transactions:"/transactions",operations:"/operations",ledgers:"/ledgers",payments:"/payments"},P=[{id:"metric-total",type:"metric",label:"Metric",dataKey:"metrics"},{id:"chart-activity",type:"chart",label:"Chart",dataKey:"activity"},{id:"table-records",type:"table",label:"Table",dataKey:"rows"}],Se=[{id:"account-activity",name:"Account Activity",description:"Track balances, signer risk, and recent transaction volume for an account.",resource:"accounts",category:"account",tags:["account","activity","risk"],aiHint:"Summarize balances, signer risk, and recent volume for a specific account.",components:[{id:"account-balance",type:"metric",label:"XLM Balance",dataKey:"account.xlmBalance"},{id:"account-activity-chart",type:"chart",label:"Daily Activity",dataKey:"activity"},{id:"account-risk-table",type:"table",label:"Risk Signals",dataKey:"risks"}]},{id:"portfolio-performance",name:"Portfolio Performance",description:"Summarize trustlines, asset counts, and fee movement over time.",resource:"accounts",category:"portfolio",tags:["portfolio","assets","performance"],aiHint:"Highlight asset exposure and fee trends across a portfolio.",components:[{id:"portfolio-assets",type:"metric",label:"Assets",dataKey:"account.totalAssets"},{id:"portfolio-fees",type:"chart",label:"Fee Trend",dataKey:"activity"},{id:"portfolio-summary",type:"table",label:"Portfolio Summary",dataKey:"account"}]},{id:"transaction-analysis",name:"Transaction Analysis",description:"Inspect transaction success rates and operation mix.",resource:"transactions",category:"transactions",tags:["transactions","payments","success"],aiHint:"Inspect success rates and the mix of operations in a transaction stream.",components:[{id:"tx-success-rate",type:"metric",label:"Success Rate",dataKey:"transactions.successRate"},{id:"tx-activity",type:"chart",label:"Transaction Trend",dataKey:"activity"},{id:"tx-breakdown",type:"table",label:"Operation Mix",dataKey:"transactions.opTypeCounts"}]},{id:"network-health",name:"Network Health",description:"Monitor ledger freshness, fees, and close-time health.",resource:"ledgers",category:"network",tags:["network","ledger","health"],aiHint:"Monitor ledger freshness, fee pressure, and network stability.",components:[{id:"network-ledger",type:"metric",label:"Latest Ledger",dataKey:"network.latestLedgerSequence"},{id:"network-close-time",type:"chart",label:"Close Time",dataKey:"activity"},{id:"network-fees",type:"table",label:"Network Fees",dataKey:"network"}]},{id:"asset-allocation",name:"Asset Allocation",description:"Review trustline concentration and balance allocation across assets.",resource:"accounts",category:"portfolio",tags:["asset","allocation","trustline"],aiHint:"Summarize concentration by asset and trustline coverage.",components:[{id:"asset-count",type:"metric",label:"Trustlines",dataKey:"account.trustlineCount"},{id:"asset-chart",type:"chart",label:"Asset Mix",dataKey:"activity"},{id:"asset-table",type:"table",label:"Asset Distribution",dataKey:"account"}]},{id:"signer-risk-review",name:"Signer Risk Review",description:"Focus on signature policy and single-signer exposure.",resource:"accounts",category:"security",tags:["signer","risk","security"],aiHint:"Call out singlesigner exposure and signing policy anomalies.",components:[{id:"signer-metric",type:"metric",label:"Risk Signals",dataKey:"risks.length"},{id:"signer-chart",type:"chart",label:"Risk Timeline",dataKey:"risks"},{id:"signer-table",type:"table",label:"Signer Risks",dataKey:"risks"}]},{id:"fee-efficiency",name:"Fee Efficiency",description:"Compare activity volume against fees to surface efficiency opportunities.",resource:"payments",category:"cost",tags:["fee","cost","efficiency"],aiHint:"Compare transaction volume and fees to estimate efficiency.",components:[{id:"fee-metric",type:"metric",label:"Base Fee",dataKey:"network.baseFee"},{id:"fee-chart",type:"chart",label:"Fee Trend",dataKey:"activity"},{id:"fee-table",type:"table",label:"Fee Summary",dataKey:"network"}]},{id:"payment-velocity",name:"Payment Velocity",description:"Review throughput and cadence of payments over time.",resource:"payments",category:"payments",tags:["payment","velocity","throughput"],aiHint:"Track payment cadence and volume spikes.",components:[{id:"velocity-metric",type:"metric",label:"Payment Count",dataKey:"activity.length"},{id:"velocity-chart",type:"chart",label:"Payment Trend",dataKey:"activity"},{id:"velocity-table",type:"table",label:"Payment Snapshot",dataKey:"activity"}]},{id:"liquidity-watch",name:"Liquidity Watch",description:"Measure available liquidity and reserve pressure for key accounts.",resource:"accounts",category:"liquidity",tags:["liquidity","reserve","balance"],aiHint:"Highlight reserve pressure and balance sufficiency.",components:[{id:"liquidity-metric",type:"metric",label:"Available Balance",dataKey:"account.xlmBalance"},{id:"liquidity-chart",type:"chart",label:"Balance Trend",dataKey:"activity"},{id:"liquidity-table",type:"table",label:"Liquidity Signals",dataKey:"account"}]},{id:"ledger-freshness",name:"Ledger Freshness",description:"Inspect the last ledger close and proximity to current activity.",resource:"ledgers",category:"network",tags:["ledger","freshness","timing"],aiHint:"Compare close-time cadence with activity volume.",components:[{id:"ledger-metric",type:"metric",label:"Latest Ledger",dataKey:"network.latestLedgerSequence"},{id:"ledger-chart",type:"chart",label:"Close Timeline",dataKey:"activity"},{id:"ledger-table",type:"table",label:"Ledger Snapshot",dataKey:"network"}]},{id:"compliance-review",name:"Compliance Review",description:"Surface policy-sensitive activity for audit and review workflows.",resource:"transactions",category:"compliance",tags:["compliance","audit","review"],aiHint:"Summarize reviewable activity that may need policy attention.",components:[{id:"compliance-metric",type:"metric",label:"Review Items",dataKey:"risks.length"},{id:"compliance-chart",type:"chart",label:"Review Trend",dataKey:"activity"},{id:"compliance-table",type:"table",label:"Compliance Signals",dataKey:"risks"}]},{id:"recovery-readiness",name:"Recovery Readiness",description:"Assess how prepared an account is for recovery or incident response.",resource:"accounts",category:"operations",tags:["recovery","incident","prepare"],aiHint:"Highlight account resiliency and operational readiness.",components:[{id:"recovery-metric",type:"metric",label:"Risk Signals",dataKey:"risks.length"},{id:"recovery-chart",type:"chart",label:"Operational Trend",dataKey:"activity"},{id:"recovery-table",type:"table",label:"Recovery Notes",dataKey:"risks"}]},{id:"validator-health",name:"Validator Health",description:"Monitor validator-related network stability indicators.",resource:"ledgers",category:"network",tags:["validator","stability","network"],aiHint:"Review network health cues around validator and ledger performance.",components:[{id:"validator-metric",type:"metric",label:"Latest Ledger",dataKey:"network.latestLedgerSequence"},{id:"validator-chart",type:"chart",label:"Health Trend",dataKey:"activity"},{id:"validator-table",type:"table",label:"Validator Snapshot",dataKey:"network"}]},{id:"market-activity",name:"Market Activity",description:"Capture trading and flow shifts that indicate momentum.",resource:"transactions",category:"market",tags:["market","momentum","flow"],aiHint:"Summarize trend shifts in transaction flow and trading behavior.",components:[{id:"market-metric",type:"metric",label:"Transactions",dataKey:"activity.length"},{id:"market-chart",type:"chart",label:"Flow Trend",dataKey:"activity"},{id:"market-table",type:"table",label:"Market Notes",dataKey:"activity"}]},{id:"trustline-risk",name:"Trustline Risk",description:"Focus on trustline concentration and exposure hotspots.",resource:"accounts",category:"risk",tags:["trustline","exposure","risk"],aiHint:"Surface concentration risk and trustline coverage gaps.",components:[{id:"trustline-metric",type:"metric",label:"Trustlines",dataKey:"account.trustlineCount"},{id:"trustline-chart",type:"chart",label:"Exposure Trend",dataKey:"activity"},{id:"trustline-table",type:"table",label:"Trustline Risks",dataKey:"account"}]},{id:"reserve-management",name:"Reserve Management",description:"Monitor reserve usage and balance sustainability.",resource:"accounts",category:"operations",tags:["reserve","balance","sustainability"],aiHint:"Flag reserve strain and sustainability concerns.",components:[{id:"reserve-metric",type:"metric",label:"Balance",dataKey:"account.xlmBalance"},{id:"reserve-chart",type:"chart",label:"Reserve Trend",dataKey:"activity"},{id:"reserve-table",type:"table",label:"Reserve Snapshot",dataKey:"account"}]},{id:"ops-drift",name:"Operations Drift",description:"Identify changes in operations mix over consecutive windows.",resource:"operations",category:"operations",tags:["operations","drift","change"],aiHint:"Spot drift in the operations mix over time.",components:[{id:"ops-metric",type:"metric",label:"Operations",dataKey:"activity.length"},{id:"ops-chart",type:"chart",label:"Drift Trend",dataKey:"activity"},{id:"ops-table",type:"table",label:"Operations Mix",dataKey:"activity"}]},{id:"asset-flow",name:"Asset Flow",description:"Trace asset movement and transfer patterns across accounts.",resource:"payments",category:"payments",tags:["asset","flow","transfer"],aiHint:"Trace transfer flow and highlight movement hotspots.",components:[{id:"asset-flow-metric",type:"metric",label:"Payments",dataKey:"activity.length"},{id:"asset-flow-chart",type:"chart",label:"Flow Trend",dataKey:"activity"},{id:"asset-flow-table",type:"table",label:"Asset Flow",dataKey:"activity"}]},{id:"activity-forecast",name:"Activity Forecast",description:"Generate a forecast-style snapshot for recurring activity patterns.",resource:"transactions",category:"forecast",tags:["forecast","trend","activity"],aiHint:"Generate a forward-looking review of recurring activity patterns.",components:[{id:"forecast-metric",type:"metric",label:"Trend Score",dataKey:"activity.length"},{id:"forecast-chart",type:"chart",label:"Forecast Trend",dataKey:"activity"},{id:"forecast-table",type:"table",label:"Forecast Notes",dataKey:"activity"}]},{id:"route-coverage",name:"Route Coverage",description:"Review how routing and payment coverage hold up across the network.",resource:"payments",category:"network",tags:["routing","payments","coverage"],aiHint:"Review the breadth of payment routing coverage.",components:[{id:"route-metric",type:"metric",label:"Payments",dataKey:"activity.length"},{id:"route-chart",type:"chart",label:"Coverage Trend",dataKey:"activity"},{id:"route-table",type:"table",label:"Routing Snapshot",dataKey:"activity"}]}],A=Se;function Te(e){const a=Number(e);return Number.isFinite(a)?String(Math.min(Math.max(Math.trunc(a),1),200)):"200"}function D(e,a){return a.split(".").reduce((i,s)=>i?.[s],e)}function N(e){return Array.isArray(e)?e.map((a,i)=>({id:a.id||i+1,...a})):e&&typeof e=="object"?Object.entries(e).map(([a,i])=>i&&typeof i=="object"?{id:a,...i}:{id:a,value:i}):[{id:"value",value:e}]}function Re(e){const a=e==null?"":String(e);return/[",\n]/.test(a)?`"${a.replace(/"/g,'""')}"`:a}function H(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/(^-|-$)/g,"")||"report"}const W="stellar-dev-dashboard-saved-report-templates";let f=[];function E(){if(typeof globalThis>"u")return f;const e=globalThis.localStorage;if(!e)return f;try{const a=e.getItem(W);if(!a)return f;const i=JSON.parse(a);return Array.isArray(i)&&(f=i),f}catch{return f}}function _(){return[...A,...E()]}function K(e){return _().find(a=>a.id===e)||A[0]}function Ce(e){const a=e.trim(),i=a.toLowerCase(),l=[{id:"account-activity",keywords:["account","balance","signer","risk","trustline","review"]},{id:"portfolio-performance",keywords:["portfolio","asset","allocation","holdings","balance"]},{id:"transaction-analysis",keywords:["transaction","payment","operation","volume","flow"]},{id:"network-health",keywords:["network","fee","ledger","validator","health","stability"]}].find(({keywords:c})=>c.some(k=>i.includes(k)))?.id||"account-activity",o=a.match(/\b(G[A-Z2-7]{3,})\b/i),n=["daily","weekly","monthly","quarterly"].find(c=>i.includes(c)),d=[{area:"risks",keywords:["risk","signer","security","compliance"]},{area:"fees",keywords:["fee","cost","expense"]},{area:"assets",keywords:["asset","portfolio","holdings","allocation"]},{area:"volume",keywords:["volume","throughput","flow","velocity"]},{area:"health",keywords:["health","stability","ledger","network"]}].filter(({keywords:c})=>c.some(k=>i.includes(k))).map(({area:c})=>c),w=i.includes("ledger")||i.includes("network")||i.includes("validator")?"ledgers":i.includes("payment")||i.includes("transfer")?"payments":i.includes("operation")?"operations":"accounts";return{templateId:l,accountId:o?.[1],focusAreas:d.length>0?d:["summary"],frequency:n,resource:w,prompt:a}}function Ke(e){const i=[...E().filter(s=>s.id!==e.id),e];if(f=i,typeof globalThis<"u"){const s=globalThis.localStorage;s&&s.setItem(W,JSON.stringify(i))}return e}function q(){return E()}function Ae(e){const a=e.resource,i=je[a];if(!i)throw new Error(`Unsupported Horizon report resource: ${a}`);const s=ke[e.network||"testnet"]||String(e.network||"").replace(/\/$/,"");if(!s)throw new Error("A Horizon base URL or known network is required");const l={cursor:e.cursor||"now",order:e.order||"desc",limit:Te(e.limit)};Object.entries(e.filters||{}).forEach(([w,c])=>{c!==void 0&&c!==""&&(l[w]=String(c))});const n=["transactions","operations","payments"].includes(a)&&e.accountId?`/accounts/${encodeURIComponent(e.accountId||"")}${i}`:i,d=new URLSearchParams(l);return{resource:a,endpoint:n,params:l,url:`${s}${n}?${d.toString()}`}}function $e(e,a,i,s,l){const o=[];if(a.length>0){const n=a[0];o.push(`${n.label} is ${n.value} in the current snapshot.`)}if(s.includes("risks")&&i.length>0){const n=i.filter(d=>d.active===!0||d.risk===!0||d.label?.toLowerCase().includes("risk"));n.length>0&&o.push(`Risk signals are visible across ${n.length} entry${n.length===1?"":"ies"}.`)}return s.includes("fees")&&l.network?.baseFee&&o.push(`The current base fee is ${l.network.baseFee} stroops.`),e.aiHint&&o.push(e.aiHint),o.slice(0,3)}function ze(e,a,i){const s=K(e),l={account:a.account||{},transactions:a.transactions||{},network:a.network||{},activity:a.activity||[],risks:a.risks||[]},o=s.components.filter(y=>y.type==="metric").map(y=>{const g=D(l,y.dataKey),$=typeof g=="number"&&y.dataKey.includes("successRate")?`${(g*100).toFixed(1)}%`:g??"N/A";return{label:y.label,value:$}}),n=s.components.find(y=>y.type==="chart"),d=s.components.find(y=>y.type==="table"),w=N(D(l,n?.dataKey||"activity")),c=N(D(l,d?.dataKey||s.resource)),k=Array.from(new Set(c.flatMap(y=>Object.keys(y)))).slice(0,8),j=i?.focusAreas||[];return{templateId:s.id,generatedAt:new Date().toISOString(),metrics:o,chartData:w,rows:c,columns:k,insights:$e(s,o,c,j,a),summary:i?.request?`AI-generated ${s.name} summary based on: ${i.request}`:`${s.name} summary`,focusAreas:j}}function G(e,a){return JSON.stringify({template:e,data:a},null,2)}function V(e){const a=e.metrics.map(n=>({section:"metric",label:n.label,value:n.value})),i=e.rows.map(n=>({section:"row",...n})),s=[...a,...i],l=Array.from(new Set(s.flatMap(n=>Object.keys(n)))),o=s.map(n=>l.map(d=>Re(n[d])).join(","));return[l.join(","),...o].join(` +`)}function J(e,a){const i=a.metrics.map(n=>`
  • ${n.label}: ${n.value}
  • `).join(""),s=(a.insights||[]).map(n=>`
  • ${n}
  • `).join(""),l=a.columns.map(n=>`${n}`).join(""),o=a.rows.slice(0,25).map(n=>`${a.columns.map(d=>`${n[d]??""}`).join("")}`).join("");return{filename:`${H(e.name)}.pdf.html`,contentType:"text/html",html:`${e.name}

    ${e.name}

    ${e.description}

    Metrics

      ${i}

    Insights

      ${s}

    Data

    ${l}${o}
    `,chartData:a.chartData}}function Z(e){const a=e.trim().split(/\s+/);if(a.length!==5)throw new Error("Report schedules use five-part cron expressions");return{minute:a[0],hour:a[1],dayOfMonth:a[2],month:a[3],dayOfWeek:a[4]}}function B(e,a,i,s){if(e==="*")return a;if(e.startsWith("*/")){const o=Number(e.slice(2));if(!Number.isFinite(o)||o<=0)throw new Error(`Invalid cron step: ${e}`);const n=a+(o-a%o);return n>s?i:n}const l=Number(e);if(!Number.isInteger(l)||ls)throw new Error(`Invalid cron value: ${e}`);return l}function X(e,a=new Date){const i=Z(e),s=new Date(a);return s.setSeconds(0,0),s.setMinutes(s.getMinutes()+1),s.setMinutes(B(i.minute,s.getMinutes(),0,59)),s.setHours(B(i.hour,s.getHours(),0,23)),s.getTime()<=a.getTime()&&s.setDate(s.getDate()+1),s.toISOString()}function Ie(e){return/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e)}function De(e){return!e||/^https:\/\/.+/i.test(e)}function Fe(e){if(Z(e.cron),e.channels.includes("email")&&!e.recipients.every(Ie))throw new Error("Email report schedules require valid recipients");if(e.channels.includes("webhook")&&!De(e.webhookUrl))throw new Error("Webhook report schedules require an HTTPS URL");return{...e,timezone:e.timezone||Intl.DateTimeFormat().resolvedOptions().timeZone,nextRunAt:X(e.cron)}}function He(e,a,i){return e.channels.map(s=>({channel:s,target:s==="email"?e.recipients.join(", "):e.webhookUrl,subject:`${a.name} report`,attachments:[{filename:`${H(a.name)}.json`,contentType:"application/json",body:G(a,i)},{filename:`${H(a.name)}.csv`,contentType:"text/csv",body:V(i)},J(a,i)]}))}const x={width:"100%",minHeight:"36px",borderRadius:"var(--radius-md)",border:"1px solid var(--border)",background:"var(--bg-elevated)",color:"var(--text-primary)",padding:"8px 10px",fontSize:"12px"},b={borderRadius:"var(--radius-md)",border:"1px solid var(--border)",background:"var(--bg-elevated)",color:"var(--text-primary)",padding:"8px 10px",display:"inline-flex",alignItems:"center",gap:"6px",fontSize:"12px",cursor:"pointer"};function F(e,a,i){const s=new Blob([a],{type:i}),l=URL.createObjectURL(s),o=document.createElement("a");o.href=l,o.download=e,o.click(),URL.revokeObjectURL(l)}function U(e){return e==="chart"?t.jsx(be,{size:14}):e==="table"?t.jsx(fe,{size:14}):t.jsx(we,{size:14})}function Ee({analytics:e}){const[a,i]=u.useState(A[0].id),[s,l]=u.useState("transactions"),[o,n]=u.useState(""),[d,w]=u.useState(50),[c,k]=u.useState("0 9 * * 1"),[j,y]=u.useState(""),[g,$]=u.useState(""),[Q,R]=u.useState(A[0].components),[z,Y]=u.useState("Create a weekly account activity report for GABC with emphasis on risks and fees"),[L,ee]=u.useState(q()),p=K(a),h=u.useMemo(()=>Ce(z),[z]),v=u.useMemo(()=>ze(p.id,e||{},{focusAreas:h.focusAreas,request:h.prompt}),[e,h.focusAreas,h.prompt,p.id]),te=u.useMemo(()=>Ae({resource:s,accountId:o||void 0,limit:d,filters:{include_failed:s==="transactions"?"true":void 0}}),[o,d,s]),I=u.useMemo(()=>{try{return Fe({id:`${p.id}-weekly`,reportId:p.id,cron:c,timezone:Intl.DateTimeFormat().resolvedOptions().timeZone,enabled:!0,channels:g?["email","webhook"]:["email"],recipients:j?[j]:[],webhookUrl:g||void 0})}catch{return null}},[c,j,p.id,g]),ae=I?He(I,p,v):[],M=r=>{const m=K(r);i(m.id),l(m.resource),R(m.components)},re=()=>{const r=K(h.templateId);i(r.id),l(r.resource),n(h.accountId||o),R(r.components)},ie=()=>{const r=Ke({...p,id:`${p.id}-saved-${Date.now()}`,name:`${p.name} (Saved)`,description:`${p.description} Saved from the dashboard.`,category:p.category||"custom",tags:[...p.tags||[],"saved"]});return ee(q()),r},se=r=>{r.preventDefault();const m=r.dataTransfer.getData("application/report-component"),T=P.find(C=>C.id===m);T&&R(C=>[...C,{...T,id:`${T.id}-${Date.now()}`,label:`Custom ${T.label}`}])},ne=()=>{F(`${p.id}.json`,G(p,v),"application/json")},oe=()=>{F(`${p.id}.csv`,V(v),"text/csv")},le=()=>{const r=J(p,v);F(r.filename,r.html,r.contentType)};return t.jsxs("div",{style:{background:"var(--bg-card)",border:"1px solid var(--border)",borderRadius:"var(--radius-lg)",padding:"16px",display:"flex",flexDirection:"column",gap:"14px"},children:[t.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",gap:"12px",flexWrap:"wrap"},children:[t.jsxs("div",{children:[t.jsx("div",{style:{fontFamily:"var(--font-display)",fontSize:"15px",fontWeight:700},children:"Custom Reports"}),t.jsx("div",{style:{color:"var(--text-muted)",fontSize:"12px",marginTop:"3px"},children:"Build reusable Stellar analytics reports with exports and scheduled delivery."})]}),t.jsxs("div",{style:{display:"flex",gap:"8px",flexWrap:"wrap"},children:[t.jsxs("button",{type:"button",style:b,onClick:ie,title:"Save current template",children:[t.jsx(O,{size:14})," Save"]}),t.jsxs("button",{type:"button",style:b,onClick:oe,title:"Export CSV",children:[t.jsx(ye,{size:14})," CSV"]}),t.jsxs("button",{type:"button",style:b,onClick:le,title:"Export PDF-ready report",children:[t.jsx(me,{size:14})," PDF"]}),t.jsxs("button",{type:"button",style:b,onClick:ne,title:"Export JSON",children:[t.jsx(ge,{size:14})," JSON"]})]})]}),t.jsxs("div",{style:{display:"grid",gridTemplateColumns:"repeat(auto-fit, minmax(280px, 1fr))",gap:"14px"},children:[t.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:"12px"},children:[t.jsxs("label",{style:{display:"flex",flexDirection:"column",gap:"6px",fontSize:"12px",color:"var(--text-muted)"},children:["Template",t.jsx("select",{value:a,onChange:r=>M(r.target.value),style:x,children:_().map(r=>t.jsx("option",{value:r.id,children:r.name},r.id))})]}),t.jsxs("label",{style:{display:"flex",flexDirection:"column",gap:"6px",fontSize:"12px",color:"var(--text-muted)"},children:["Prompt",t.jsx("textarea",{value:z,onChange:r=>Y(r.target.value),rows:3,style:{...x,minHeight:"80px"}})]}),t.jsx("button",{type:"button",style:b,onClick:re,children:"Generate report from prompt"}),t.jsxs("div",{style:{display:"grid",gridTemplateColumns:"1fr 90px",gap:"8px"},children:[t.jsxs("label",{style:{display:"flex",flexDirection:"column",gap:"6px",fontSize:"12px",color:"var(--text-muted)"},children:["Horizon resource",t.jsxs("select",{value:s,onChange:r=>l(r.target.value),style:x,children:[t.jsx("option",{value:"accounts",children:"Accounts"}),t.jsx("option",{value:"transactions",children:"Transactions"}),t.jsx("option",{value:"operations",children:"Operations"}),t.jsx("option",{value:"payments",children:"Payments"}),t.jsx("option",{value:"ledgers",children:"Ledgers"})]})]}),t.jsxs("label",{style:{display:"flex",flexDirection:"column",gap:"6px",fontSize:"12px",color:"var(--text-muted)"},children:["Limit",t.jsx("input",{type:"number",min:1,max:200,value:d,onChange:r=>w(Number(r.target.value)),style:x})]})]}),t.jsxs("label",{style:{display:"flex",flexDirection:"column",gap:"6px",fontSize:"12px",color:"var(--text-muted)"},children:["Account filter",t.jsx("input",{value:o,onChange:r=>n(r.target.value),placeholder:"G...",style:x})]}),t.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:"8px"},children:[t.jsx("div",{style:{fontSize:"12px",color:"var(--text-muted)"},children:"Component palette"}),t.jsx("div",{style:{display:"grid",gridTemplateColumns:"repeat(3, minmax(0, 1fr))",gap:"8px"},children:P.map(r=>t.jsxs("button",{type:"button",draggable:!0,onDragStart:m=>m.dataTransfer.setData("application/report-component",r.id),onClick:()=>R(m=>[...m,{...r,id:`${r.id}-${Date.now()}`}]),style:b,title:`Add ${r.label}`,children:[U(r.type),r.label]},r.id))})]}),t.jsx("div",{style:{border:"1px solid var(--border)",borderRadius:"var(--radius-md)",padding:"10px",background:"var(--bg-elevated)",color:"var(--text-muted)",fontSize:"11px",wordBreak:"break-all"},children:te.url})]}),t.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:"12px"},children:[t.jsx("div",{onDragOver:r=>r.preventDefault(),onDrop:se,style:{border:"1px dashed var(--border)",borderRadius:"var(--radius-lg)",padding:"12px",minHeight:"155px",display:"grid",gridTemplateColumns:"repeat(auto-fit, minmax(160px, 1fr))",gap:"8px"},children:Q.map((r,m)=>t.jsxs("div",{style:{border:"1px solid var(--border)",borderRadius:"var(--radius-md)",background:"var(--bg-elevated)",padding:"10px",display:"flex",alignItems:"center",justifyContent:"space-between",gap:"8px"},children:[t.jsxs("span",{style:{display:"inline-flex",alignItems:"center",gap:"7px",fontSize:"12px"},children:[U(r.type),r.label]}),t.jsx("button",{type:"button",onClick:()=>R(T=>T.filter((C,ce)=>ce!==m)),style:{...b,padding:"5px 7px"},title:`Remove ${r.label}`,children:"Remove"})]},r.id))}),t.jsx("div",{style:{display:"grid",gridTemplateColumns:"repeat(3, minmax(0, 1fr))",gap:"8px"},children:v.metrics.map(r=>t.jsxs("div",{style:{background:"var(--bg-elevated)",border:"1px solid var(--border)",borderRadius:"var(--radius-md)",padding:"10px"},children:[t.jsx("div",{style:{color:"var(--text-muted)",fontSize:"11px"},children:r.label}),t.jsx("div",{style:{fontFamily:"var(--font-display)",fontWeight:700,marginTop:"6px"},children:r.value})]},r.label))}),v.insights&&v.insights.length>0&&t.jsxs("div",{style:{background:"var(--bg-elevated)",border:"1px solid var(--border)",borderRadius:"var(--radius-md)",padding:"10px"},children:[t.jsx("div",{style:{fontSize:"12px",color:"var(--text-muted)",marginBottom:"6px"},children:"AI insights"}),t.jsx("ul",{style:{margin:0,paddingLeft:"16px",display:"grid",gap:"6px",fontSize:"12px"},children:v.insights.map(r=>t.jsx("li",{children:r},r))})]}),t.jsxs("div",{style:{fontSize:"12px",color:"var(--text-muted)"},children:["Parsed focus: ",h.focusAreas.join(", ")," ",h.accountId?`· account ${h.accountId}`:""]}),L.length>0&&t.jsxs("div",{style:{background:"var(--bg-elevated)",border:"1px solid var(--border)",borderRadius:"var(--radius-md)",padding:"10px"},children:[t.jsx("div",{style:{fontSize:"12px",color:"var(--text-muted)",marginBottom:"6px"},children:"Saved templates"}),t.jsx("div",{style:{display:"grid",gap:"6px"},children:L.map(r=>t.jsx("button",{type:"button",style:{...b,justifyContent:"flex-start"},onClick:()=>M(r.id),children:r.name},r.id))})]}),t.jsxs("div",{style:{display:"grid",gridTemplateColumns:"1fr 1fr",gap:"8px"},children:[t.jsxs("label",{style:{display:"flex",flexDirection:"column",gap:"6px",fontSize:"12px",color:"var(--text-muted)"},children:["Cron",t.jsx("input",{value:c,onChange:r=>k(r.target.value),style:x})]}),t.jsxs("label",{style:{display:"flex",flexDirection:"column",gap:"6px",fontSize:"12px",color:"var(--text-muted)"},children:["Email",t.jsx("input",{value:j,onChange:r=>y(r.target.value),placeholder:"ops@example.com",style:x})]})]}),t.jsxs("label",{style:{display:"flex",flexDirection:"column",gap:"6px",fontSize:"12px",color:"var(--text-muted)"},children:["Webhook",t.jsx("input",{value:g,onChange:r=>$(r.target.value),placeholder:"https://example.com/report-hook",style:x})]}),t.jsxs("div",{style:{display:"flex",gap:"8px",flexWrap:"wrap",color:"var(--text-muted)",fontSize:"12px"},children:[t.jsxs("span",{style:{display:"inline-flex",alignItems:"center",gap:"6px"},children:[t.jsx(he,{size:14})," Next run: ",I?.nextRunAt||X("0 9 * * 1")]}),t.jsxs("span",{style:{display:"inline-flex",alignItems:"center",gap:"6px"},children:[t.jsx(ve,{size:14})," ",ae.find(r=>r.channel==="email")?.attachments.length||3," attachments"]}),t.jsxs("span",{style:{display:"inline-flex",alignItems:"center",gap:"6px"},children:[t.jsx(xe,{size:14})," ",g?"Webhook ready":"Webhook optional"]}),t.jsxs("span",{style:{display:"inline-flex",alignItems:"center",gap:"6px"},children:[t.jsx(O,{size:14})," Cached report preview"]})]})]})]})]})}function Le({signal:e}){const a=e.severity==="high"?"var(--red)":e.severity==="medium"?"var(--amber)":"var(--cyan)";return t.jsx("div",{style:{padding:"10px 12px",borderRadius:"var(--radius-md)",border:`1px solid ${e.active?a:"var(--border)"}`,background:"var(--bg-elevated)",color:e.active?a:"var(--text-muted)",fontSize:"12px"},children:e.label})}function _e(){const e=de(),a=e?.account||{},i=e?.transactions||{},s=e?.network||{},l=e?.risks||[];return t.jsxs("div",{className:"animate-in",style:{display:"flex",flexDirection:"column",gap:"20px"},children:[t.jsx("div",{style:{fontFamily:"var(--font-display)",fontSize:"22px",fontWeight:700},children:"Analytics"}),t.jsxs("div",{style:{display:"grid",gridTemplateColumns:"repeat(4, minmax(0, 1fr))",gap:"12px"},children:[t.jsx(S,{label:"XLM Balance",value:a.xlmBalance?.toFixed?.(2)||"0.00",accent:"var(--cyan)"}),t.jsx(S,{label:"Trustlines",value:a.trustlineCount||0,accent:"var(--amber)"}),t.jsx(S,{label:"Success Rate",value:`${((i.successRate||0)*100).toFixed(1)}%`,accent:"var(--green)"}),t.jsx(S,{label:"Weekly Activity",value:i.weeklyActivity||0,accent:"var(--text-primary)"})]}),t.jsx(pe,{data:e.activity||[]}),t.jsx(Ee,{analytics:e}),t.jsxs("div",{style:{display:"grid",gridTemplateColumns:"repeat(3, minmax(0, 1fr))",gap:"12px"},children:[t.jsx(S,{label:"Latest Ledger",value:s.latestLedgerSequence||"—"}),t.jsx(S,{label:"Base Fee",value:s.baseFee||0}),t.jsx(S,{label:"Avg Close Time",value:`${(s.averageCloseSeconds||0).toFixed(2)}s`})]}),t.jsx(ue,{}),t.jsxs("div",{style:{background:"var(--bg-card)",border:"1px solid var(--border)",borderRadius:"var(--radius-lg)",padding:"14px",display:"flex",flexDirection:"column",gap:"10px"},children:[t.jsx("div",{style:{fontFamily:"var(--font-display)",fontSize:"13px"},children:"Risk Signals"}),t.jsx("div",{style:{display:"grid",gridTemplateColumns:"1fr",gap:"8px"},children:l.map(o=>t.jsx(Le,{signal:o},o.id))})]})]})}export{_e as default}; +//# sourceMappingURL=Analytics-BCF9lBrz.js.map diff --git a/dist/assets/Analytics-BCF9lBrz.js.map b/dist/assets/Analytics-BCF9lBrz.js.map new file mode 100644 index 00000000..57271219 --- /dev/null +++ b/dist/assets/Analytics-BCF9lBrz.js.map @@ -0,0 +1 @@ +{"version":3,"file":"Analytics-BCF9lBrz.js","sources":["../../src/lib/customReports.ts","../../src/components/dashboard/CustomReports.tsx","../../src/components/dashboard/Analytics.tsx"],"sourcesContent":["export type ReportComponentType = \"metric\" | \"chart\" | \"table\";\r\nexport type ReportResource = \"accounts\" | \"transactions\" | \"operations\" | \"ledgers\" | \"payments\";\r\nexport type DeliveryChannel = \"email\" | \"webhook\";\r\n\r\nexport interface ReportComponentDefinition {\r\n id: string;\r\n type: ReportComponentType;\r\n label: string;\r\n dataKey: string;\r\n}\r\n\r\nexport interface ReportTemplate {\r\n id: string;\r\n name: string;\r\n description: string;\r\n resource: ReportResource;\r\n components: ReportComponentDefinition[];\r\n category?: string;\r\n tags?: string[];\r\n aiHint?: string;\r\n}\r\n\r\nexport interface HorizonQueryConfig {\r\n resource: ReportResource;\r\n network?: \"public\" | \"testnet\" | string;\r\n accountId?: string;\r\n cursor?: string;\r\n order?: \"asc\" | \"desc\";\r\n limit?: number;\r\n filters?: Record;\r\n}\r\n\r\nexport interface BuiltHorizonQuery {\r\n resource: ReportResource;\r\n endpoint: string;\r\n params: Record;\r\n url: string;\r\n}\r\n\r\nexport interface ReportDataSet {\r\n account?: Record;\r\n transactions?: Record;\r\n network?: Record;\r\n activity?: Array>;\r\n risks?: Array>;\r\n}\r\n\r\nexport interface TransformedReportData {\r\n templateId: string;\r\n generatedAt: string;\r\n metrics: Array<{ label: string; value: string | number }>;\r\n chartData: Array>;\r\n rows: Array>;\r\n columns: string[];\r\n insights?: string[];\r\n summary?: string;\r\n focusAreas?: string[];\r\n}\r\n\r\nexport interface ParsedReportRequest {\r\n templateId: string;\r\n accountId?: string;\r\n focusAreas: string[];\r\n frequency?: string;\r\n resource: ReportResource;\r\n prompt: string;\r\n}\r\n\r\nexport interface ReportSchedule {\r\n id: string;\r\n reportId: string;\r\n cron: string;\r\n timezone: string;\r\n enabled: boolean;\r\n channels: DeliveryChannel[];\r\n recipients: string[];\r\n webhookUrl?: string;\r\n nextRunAt: string;\r\n}\r\n\r\nconst HORIZON_BASE_URLS: Record = {\r\n public: \"https://horizon.stellar.org\",\r\n testnet: \"https://horizon-testnet.stellar.org\",\r\n};\r\n\r\nconst RESOURCE_ENDPOINTS: Record = {\r\n accounts: \"/accounts\",\r\n transactions: \"/transactions\",\r\n operations: \"/operations\",\r\n ledgers: \"/ledgers\",\r\n payments: \"/payments\",\r\n};\r\n\r\nexport const REPORT_COMPONENT_PALETTE: ReportComponentDefinition[] = [\r\n { id: \"metric-total\", type: \"metric\", label: \"Metric\", dataKey: \"metrics\" },\r\n { id: \"chart-activity\", type: \"chart\", label: \"Chart\", dataKey: \"activity\" },\r\n { id: \"table-records\", type: \"table\", label: \"Table\", dataKey: \"rows\" },\r\n];\r\n\r\nconst REPORT_TEMPLATE_DEFINITIONS: ReportTemplate[] = [\r\n {\r\n id: \"account-activity\",\r\n name: \"Account Activity\",\r\n description: \"Track balances, signer risk, and recent transaction volume for an account.\",\r\n resource: \"accounts\",\r\n category: \"account\",\r\n tags: [\"account\", \"activity\", \"risk\"],\r\n aiHint: \"Summarize balances, signer risk, and recent volume for a specific account.\",\r\n components: [\r\n { id: \"account-balance\", type: \"metric\", label: \"XLM Balance\", dataKey: \"account.xlmBalance\" },\r\n { id: \"account-activity-chart\", type: \"chart\", label: \"Daily Activity\", dataKey: \"activity\" },\r\n { id: \"account-risk-table\", type: \"table\", label: \"Risk Signals\", dataKey: \"risks\" },\r\n ],\r\n },\r\n {\r\n id: \"portfolio-performance\",\r\n name: \"Portfolio Performance\",\r\n description: \"Summarize trustlines, asset counts, and fee movement over time.\",\r\n resource: \"accounts\",\r\n category: \"portfolio\",\r\n tags: [\"portfolio\", \"assets\", \"performance\"],\r\n aiHint: \"Highlight asset exposure and fee trends across a portfolio.\",\r\n components: [\r\n { id: \"portfolio-assets\", type: \"metric\", label: \"Assets\", dataKey: \"account.totalAssets\" },\r\n { id: \"portfolio-fees\", type: \"chart\", label: \"Fee Trend\", dataKey: \"activity\" },\r\n { id: \"portfolio-summary\", type: \"table\", label: \"Portfolio Summary\", dataKey: \"account\" },\r\n ],\r\n },\r\n {\r\n id: \"transaction-analysis\",\r\n name: \"Transaction Analysis\",\r\n description: \"Inspect transaction success rates and operation mix.\",\r\n resource: \"transactions\",\r\n category: \"transactions\",\r\n tags: [\"transactions\", \"payments\", \"success\"],\r\n aiHint: \"Inspect success rates and the mix of operations in a transaction stream.\",\r\n components: [\r\n { id: \"tx-success-rate\", type: \"metric\", label: \"Success Rate\", dataKey: \"transactions.successRate\" },\r\n { id: \"tx-activity\", type: \"chart\", label: \"Transaction Trend\", dataKey: \"activity\" },\r\n { id: \"tx-breakdown\", type: \"table\", label: \"Operation Mix\", dataKey: \"transactions.opTypeCounts\" },\r\n ],\r\n },\r\n {\r\n id: \"network-health\",\r\n name: \"Network Health\",\r\n description: \"Monitor ledger freshness, fees, and close-time health.\",\r\n resource: \"ledgers\",\r\n category: \"network\",\r\n tags: [\"network\", \"ledger\", \"health\"],\r\n aiHint: \"Monitor ledger freshness, fee pressure, and network stability.\",\r\n components: [\r\n { id: \"network-ledger\", type: \"metric\", label: \"Latest Ledger\", dataKey: \"network.latestLedgerSequence\" },\r\n { id: \"network-close-time\", type: \"chart\", label: \"Close Time\", dataKey: \"activity\" },\r\n { id: \"network-fees\", type: \"table\", label: \"Network Fees\", dataKey: \"network\" },\r\n ],\r\n },\r\n {\r\n id: \"asset-allocation\",\r\n name: \"Asset Allocation\",\r\n description: \"Review trustline concentration and balance allocation across assets.\",\r\n resource: \"accounts\",\r\n category: \"portfolio\",\r\n tags: [\"asset\", \"allocation\", \"trustline\"],\r\n aiHint: \"Summarize concentration by asset and trustline coverage.\",\r\n components: [\r\n { id: \"asset-count\", type: \"metric\", label: \"Trustlines\", dataKey: \"account.trustlineCount\" },\r\n { id: \"asset-chart\", type: \"chart\", label: \"Asset Mix\", dataKey: \"activity\" },\r\n { id: \"asset-table\", type: \"table\", label: \"Asset Distribution\", dataKey: \"account\" },\r\n ],\r\n },\r\n {\r\n id: \"signer-risk-review\",\r\n name: \"Signer Risk Review\",\r\n description: \"Focus on signature policy and single-signer exposure.\",\r\n resource: \"accounts\",\r\n category: \"security\",\r\n tags: [\"signer\", \"risk\", \"security\"],\r\n aiHint: \"Call out singlesigner exposure and signing policy anomalies.\",\r\n components: [\r\n { id: \"signer-metric\", type: \"metric\", label: \"Risk Signals\", dataKey: \"risks.length\" },\r\n { id: \"signer-chart\", type: \"chart\", label: \"Risk Timeline\", dataKey: \"risks\" },\r\n { id: \"signer-table\", type: \"table\", label: \"Signer Risks\", dataKey: \"risks\" },\r\n ],\r\n },\r\n {\r\n id: \"fee-efficiency\",\r\n name: \"Fee Efficiency\",\r\n description: \"Compare activity volume against fees to surface efficiency opportunities.\",\r\n resource: \"payments\",\r\n category: \"cost\",\r\n tags: [\"fee\", \"cost\", \"efficiency\"],\r\n aiHint: \"Compare transaction volume and fees to estimate efficiency.\",\r\n components: [\r\n { id: \"fee-metric\", type: \"metric\", label: \"Base Fee\", dataKey: \"network.baseFee\" },\r\n { id: \"fee-chart\", type: \"chart\", label: \"Fee Trend\", dataKey: \"activity\" },\r\n { id: \"fee-table\", type: \"table\", label: \"Fee Summary\", dataKey: \"network\" },\r\n ],\r\n },\r\n {\r\n id: \"payment-velocity\",\r\n name: \"Payment Velocity\",\r\n description: \"Review throughput and cadence of payments over time.\",\r\n resource: \"payments\",\r\n category: \"payments\",\r\n tags: [\"payment\", \"velocity\", \"throughput\"],\r\n aiHint: \"Track payment cadence and volume spikes.\",\r\n components: [\r\n { id: \"velocity-metric\", type: \"metric\", label: \"Payment Count\", dataKey: \"activity.length\" },\r\n { id: \"velocity-chart\", type: \"chart\", label: \"Payment Trend\", dataKey: \"activity\" },\r\n { id: \"velocity-table\", type: \"table\", label: \"Payment Snapshot\", dataKey: \"activity\" },\r\n ],\r\n },\r\n {\r\n id: \"liquidity-watch\",\r\n name: \"Liquidity Watch\",\r\n description: \"Measure available liquidity and reserve pressure for key accounts.\",\r\n resource: \"accounts\",\r\n category: \"liquidity\",\r\n tags: [\"liquidity\", \"reserve\", \"balance\"],\r\n aiHint: \"Highlight reserve pressure and balance sufficiency.\",\r\n components: [\r\n { id: \"liquidity-metric\", type: \"metric\", label: \"Available Balance\", dataKey: \"account.xlmBalance\" },\r\n { id: \"liquidity-chart\", type: \"chart\", label: \"Balance Trend\", dataKey: \"activity\" },\r\n { id: \"liquidity-table\", type: \"table\", label: \"Liquidity Signals\", dataKey: \"account\" },\r\n ],\r\n },\r\n {\r\n id: \"ledger-freshness\",\r\n name: \"Ledger Freshness\",\r\n description: \"Inspect the last ledger close and proximity to current activity.\",\r\n resource: \"ledgers\",\r\n category: \"network\",\r\n tags: [\"ledger\", \"freshness\", \"timing\"],\r\n aiHint: \"Compare close-time cadence with activity volume.\",\r\n components: [\r\n { id: \"ledger-metric\", type: \"metric\", label: \"Latest Ledger\", dataKey: \"network.latestLedgerSequence\" },\r\n { id: \"ledger-chart\", type: \"chart\", label: \"Close Timeline\", dataKey: \"activity\" },\r\n { id: \"ledger-table\", type: \"table\", label: \"Ledger Snapshot\", dataKey: \"network\" },\r\n ],\r\n },\r\n {\r\n id: \"compliance-review\",\r\n name: \"Compliance Review\",\r\n description: \"Surface policy-sensitive activity for audit and review workflows.\",\r\n resource: \"transactions\",\r\n category: \"compliance\",\r\n tags: [\"compliance\", \"audit\", \"review\"],\r\n aiHint: \"Summarize reviewable activity that may need policy attention.\",\r\n components: [\r\n { id: \"compliance-metric\", type: \"metric\", label: \"Review Items\", dataKey: \"risks.length\" },\r\n { id: \"compliance-chart\", type: \"chart\", label: \"Review Trend\", dataKey: \"activity\" },\r\n { id: \"compliance-table\", type: \"table\", label: \"Compliance Signals\", dataKey: \"risks\" },\r\n ],\r\n },\r\n {\r\n id: \"recovery-readiness\",\r\n name: \"Recovery Readiness\",\r\n description: \"Assess how prepared an account is for recovery or incident response.\",\r\n resource: \"accounts\",\r\n category: \"operations\",\r\n tags: [\"recovery\", \"incident\", \"prepare\"],\r\n aiHint: \"Highlight account resiliency and operational readiness.\",\r\n components: [\r\n { id: \"recovery-metric\", type: \"metric\", label: \"Risk Signals\", dataKey: \"risks.length\" },\r\n { id: \"recovery-chart\", type: \"chart\", label: \"Operational Trend\", dataKey: \"activity\" },\r\n { id: \"recovery-table\", type: \"table\", label: \"Recovery Notes\", dataKey: \"risks\" },\r\n ],\r\n },\r\n {\r\n id: \"validator-health\",\r\n name: \"Validator Health\",\r\n description: \"Monitor validator-related network stability indicators.\",\r\n resource: \"ledgers\",\r\n category: \"network\",\r\n tags: [\"validator\", \"stability\", \"network\"],\r\n aiHint: \"Review network health cues around validator and ledger performance.\",\r\n components: [\r\n { id: \"validator-metric\", type: \"metric\", label: \"Latest Ledger\", dataKey: \"network.latestLedgerSequence\" },\r\n { id: \"validator-chart\", type: \"chart\", label: \"Health Trend\", dataKey: \"activity\" },\r\n { id: \"validator-table\", type: \"table\", label: \"Validator Snapshot\", dataKey: \"network\" },\r\n ],\r\n },\r\n {\r\n id: \"market-activity\",\r\n name: \"Market Activity\",\r\n description: \"Capture trading and flow shifts that indicate momentum.\",\r\n resource: \"transactions\",\r\n category: \"market\",\r\n tags: [\"market\", \"momentum\", \"flow\"],\r\n aiHint: \"Summarize trend shifts in transaction flow and trading behavior.\",\r\n components: [\r\n { id: \"market-metric\", type: \"metric\", label: \"Transactions\", dataKey: \"activity.length\" },\r\n { id: \"market-chart\", type: \"chart\", label: \"Flow Trend\", dataKey: \"activity\" },\r\n { id: \"market-table\", type: \"table\", label: \"Market Notes\", dataKey: \"activity\" },\r\n ],\r\n },\r\n {\r\n id: \"trustline-risk\",\r\n name: \"Trustline Risk\",\r\n description: \"Focus on trustline concentration and exposure hotspots.\",\r\n resource: \"accounts\",\r\n category: \"risk\",\r\n tags: [\"trustline\", \"exposure\", \"risk\"],\r\n aiHint: \"Surface concentration risk and trustline coverage gaps.\",\r\n components: [\r\n { id: \"trustline-metric\", type: \"metric\", label: \"Trustlines\", dataKey: \"account.trustlineCount\" },\r\n { id: \"trustline-chart\", type: \"chart\", label: \"Exposure Trend\", dataKey: \"activity\" },\r\n { id: \"trustline-table\", type: \"table\", label: \"Trustline Risks\", dataKey: \"account\" },\r\n ],\r\n },\r\n {\r\n id: \"reserve-management\",\r\n name: \"Reserve Management\",\r\n description: \"Monitor reserve usage and balance sustainability.\",\r\n resource: \"accounts\",\r\n category: \"operations\",\r\n tags: [\"reserve\", \"balance\", \"sustainability\"],\r\n aiHint: \"Flag reserve strain and sustainability concerns.\",\r\n components: [\r\n { id: \"reserve-metric\", type: \"metric\", label: \"Balance\", dataKey: \"account.xlmBalance\" },\r\n { id: \"reserve-chart\", type: \"chart\", label: \"Reserve Trend\", dataKey: \"activity\" },\r\n { id: \"reserve-table\", type: \"table\", label: \"Reserve Snapshot\", dataKey: \"account\" },\r\n ],\r\n },\r\n {\r\n id: \"ops-drift\",\r\n name: \"Operations Drift\",\r\n description: \"Identify changes in operations mix over consecutive windows.\",\r\n resource: \"operations\",\r\n category: \"operations\",\r\n tags: [\"operations\", \"drift\", \"change\"],\r\n aiHint: \"Spot drift in the operations mix over time.\",\r\n components: [\r\n { id: \"ops-metric\", type: \"metric\", label: \"Operations\", dataKey: \"activity.length\" },\r\n { id: \"ops-chart\", type: \"chart\", label: \"Drift Trend\", dataKey: \"activity\" },\r\n { id: \"ops-table\", type: \"table\", label: \"Operations Mix\", dataKey: \"activity\" },\r\n ],\r\n },\r\n {\r\n id: \"asset-flow\",\r\n name: \"Asset Flow\",\r\n description: \"Trace asset movement and transfer patterns across accounts.\",\r\n resource: \"payments\",\r\n category: \"payments\",\r\n tags: [\"asset\", \"flow\", \"transfer\"],\r\n aiHint: \"Trace transfer flow and highlight movement hotspots.\",\r\n components: [\r\n { id: \"asset-flow-metric\", type: \"metric\", label: \"Payments\", dataKey: \"activity.length\" },\r\n { id: \"asset-flow-chart\", type: \"chart\", label: \"Flow Trend\", dataKey: \"activity\" },\r\n { id: \"asset-flow-table\", type: \"table\", label: \"Asset Flow\", dataKey: \"activity\" },\r\n ],\r\n },\r\n {\r\n id: \"activity-forecast\",\r\n name: \"Activity Forecast\",\r\n description: \"Generate a forecast-style snapshot for recurring activity patterns.\",\r\n resource: \"transactions\",\r\n category: \"forecast\",\r\n tags: [\"forecast\", \"trend\", \"activity\"],\r\n aiHint: \"Generate a forward-looking review of recurring activity patterns.\",\r\n components: [\r\n { id: \"forecast-metric\", type: \"metric\", label: \"Trend Score\", dataKey: \"activity.length\" },\r\n { id: \"forecast-chart\", type: \"chart\", label: \"Forecast Trend\", dataKey: \"activity\" },\r\n { id: \"forecast-table\", type: \"table\", label: \"Forecast Notes\", dataKey: \"activity\" },\r\n ],\r\n },\r\n {\r\n id: \"route-coverage\",\r\n name: \"Route Coverage\",\r\n description: \"Review how routing and payment coverage hold up across the network.\",\r\n resource: \"payments\",\r\n category: \"network\",\r\n tags: [\"routing\", \"payments\", \"coverage\"],\r\n aiHint: \"Review the breadth of payment routing coverage.\",\r\n components: [\r\n { id: \"route-metric\", type: \"metric\", label: \"Payments\", dataKey: \"activity.length\" },\r\n { id: \"route-chart\", type: \"chart\", label: \"Coverage Trend\", dataKey: \"activity\" },\r\n { id: \"route-table\", type: \"table\", label: \"Routing Snapshot\", dataKey: \"activity\" },\r\n ],\r\n },\r\n];\r\n\r\nexport const REPORT_TEMPLATES: ReportTemplate[] = REPORT_TEMPLATE_DEFINITIONS;\r\n\r\nfunction normalizeLimit(limit?: number) {\r\n const parsed = Number(limit);\r\n if (!Number.isFinite(parsed)) return \"200\";\r\n return String(Math.min(Math.max(Math.trunc(parsed), 1), 200));\r\n}\r\n\r\nfunction getNestedValue(source: Record, path: string) {\r\n return path.split(\".\").reduce((value, key) => value?.[key], source);\r\n}\r\n\r\nfunction normalizeRowSet(value: any): Array> {\r\n if (Array.isArray(value)) return value.map((entry, index) => ({ id: entry.id || index + 1, ...entry }));\r\n if (value && typeof value === \"object\") {\r\n return Object.entries(value).map(([key, entry]) => {\r\n if (entry && typeof entry === \"object\") return { id: key, ...entry };\r\n return { id: key, value: entry };\r\n });\r\n }\r\n return [{ id: \"value\", value }];\r\n}\r\n\r\nfunction escapeCsvValue(value: any) {\r\n const stringValue = value == null ? \"\" : String(value);\r\n if (!/[\",\\n]/.test(stringValue)) return stringValue;\r\n return `\"${stringValue.replace(/\"/g, '\"\"')}\"`;\r\n}\r\n\r\nfunction sanitizeFilePart(value: string) {\r\n return value.toLowerCase().replace(/[^a-z0-9]+/g, \"-\").replace(/(^-|-$)/g, \"\") || \"report\";\r\n}\r\n\r\nconst SAVED_REPORT_TEMPLATE_STORAGE_KEY = \"stellar-dev-dashboard-saved-report-templates\";\r\nlet savedReportTemplateMemory: ReportTemplate[] = [];\r\n\r\nfunction readSavedReportTemplatesFromStorage(): ReportTemplate[] {\r\n if (typeof globalThis === \"undefined\") return savedReportTemplateMemory;\r\n const storage = (globalThis as typeof globalThis & { localStorage?: Storage }).localStorage;\r\n if (!storage) return savedReportTemplateMemory;\r\n\r\n try {\r\n const rawValue = storage.getItem(SAVED_REPORT_TEMPLATE_STORAGE_KEY);\r\n if (!rawValue) return savedReportTemplateMemory;\r\n const parsed = JSON.parse(rawValue);\r\n if (!Array.isArray(parsed)) return savedReportTemplateMemory;\r\n savedReportTemplateMemory = parsed as ReportTemplate[];\r\n return savedReportTemplateMemory;\r\n } catch {\r\n return savedReportTemplateMemory;\r\n }\r\n}\r\n\r\nexport function getAllReportTemplates() {\r\n return [...REPORT_TEMPLATES, ...readSavedReportTemplatesFromStorage()];\r\n}\r\n\r\nexport function getReportTemplate(templateId: string) {\r\n return getAllReportTemplates().find((template) => template.id === templateId) || REPORT_TEMPLATES[0];\r\n}\r\n\r\nexport function parseNaturalLanguageRequest(request: string): ParsedReportRequest {\r\n const normalizedRequest = request.trim();\r\n const lower = normalizedRequest.toLowerCase();\r\n\r\n const templateIds: Array<{ id: string; keywords: string[] }> = [\r\n { id: \"account-activity\", keywords: [\"account\", \"balance\", \"signer\", \"risk\", \"trustline\", \"review\"] },\r\n { id: \"portfolio-performance\", keywords: [\"portfolio\", \"asset\", \"allocation\", \"holdings\", \"balance\"] },\r\n { id: \"transaction-analysis\", keywords: [\"transaction\", \"payment\", \"operation\", \"volume\", \"flow\"] },\r\n { id: \"network-health\", keywords: [\"network\", \"fee\", \"ledger\", \"validator\", \"health\", \"stability\"] },\r\n ];\r\n\r\n const templateId = templateIds.find(({ keywords }) => keywords.some((keyword) => lower.includes(keyword)))?.id || \"account-activity\";\r\n const accountIdMatch = normalizedRequest.match(/\\b(G[A-Z2-7]{3,})\\b/i);\r\n const frequency = [\"daily\", \"weekly\", \"monthly\", \"quarterly\"].find((candidate) => lower.includes(candidate));\r\n const focusAreas = [\r\n { area: \"risks\", keywords: [\"risk\", \"signer\", \"security\", \"compliance\"] },\r\n { area: \"fees\", keywords: [\"fee\", \"cost\", \"expense\"] },\r\n { area: \"assets\", keywords: [\"asset\", \"portfolio\", \"holdings\", \"allocation\"] },\r\n { area: \"volume\", keywords: [\"volume\", \"throughput\", \"flow\", \"velocity\"] },\r\n { area: \"health\", keywords: [\"health\", \"stability\", \"ledger\", \"network\"] },\r\n ]\r\n .filter(({ keywords }) => keywords.some((keyword) => lower.includes(keyword)))\r\n .map(({ area }) => area);\r\n\r\n const resource: ReportResource = lower.includes(\"ledger\") || lower.includes(\"network\") || lower.includes(\"validator\")\r\n ? \"ledgers\"\r\n : lower.includes(\"payment\") || lower.includes(\"transfer\")\r\n ? \"payments\"\r\n : lower.includes(\"operation\")\r\n ? \"operations\"\r\n : \"accounts\";\r\n\r\n return {\r\n templateId,\r\n accountId: accountIdMatch?.[1],\r\n focusAreas: focusAreas.length > 0 ? focusAreas : [\"summary\"],\r\n frequency,\r\n resource,\r\n prompt: normalizedRequest,\r\n };\r\n}\r\n\r\nexport function saveReportTemplate(template: ReportTemplate) {\r\n const stored = readSavedReportTemplatesFromStorage();\r\n const nextTemplates = [...stored.filter((item) => item.id !== template.id), template];\r\n savedReportTemplateMemory = nextTemplates;\r\n\r\n if (typeof globalThis !== \"undefined\") {\r\n const storage = (globalThis as typeof globalThis & { localStorage?: Storage }).localStorage;\r\n if (storage) {\r\n storage.setItem(SAVED_REPORT_TEMPLATE_STORAGE_KEY, JSON.stringify(nextTemplates));\r\n }\r\n }\r\n\r\n return template;\r\n}\r\n\r\nexport function loadSavedReportTemplates() {\r\n return readSavedReportTemplatesFromStorage();\r\n}\r\n\r\nexport function buildHorizonQuery(config: HorizonQueryConfig): BuiltHorizonQuery {\r\n const resource = config.resource;\r\n const endpoint = RESOURCE_ENDPOINTS[resource];\r\n if (!endpoint) {\r\n throw new Error(`Unsupported Horizon report resource: ${resource}`);\r\n }\r\n\r\n const baseUrl = HORIZON_BASE_URLS[config.network || \"testnet\"] || String(config.network || \"\").replace(/\\/$/, \"\");\r\n if (!baseUrl) {\r\n throw new Error(\"A Horizon base URL or known network is required\");\r\n }\r\n\r\n const params: Record = {\r\n cursor: config.cursor || \"now\",\r\n order: config.order || \"desc\",\r\n limit: normalizeLimit(config.limit),\r\n };\r\n\r\n Object.entries(config.filters || {}).forEach(([key, value]) => {\r\n if (value !== undefined && value !== \"\") params[key] = String(value);\r\n });\r\n\r\n const accountScoped = [\"transactions\", \"operations\", \"payments\"].includes(resource) && config.accountId;\r\n const path = accountScoped ? `/accounts/${encodeURIComponent(config.accountId || \"\")}${endpoint}` : endpoint;\r\n const search = new URLSearchParams(params);\r\n\r\n return {\r\n resource,\r\n endpoint: path,\r\n params,\r\n url: `${baseUrl}${path}?${search.toString()}`,\r\n };\r\n}\r\n\r\nfunction buildNarrativeInsights(\r\n template: ReportTemplate,\r\n metrics: Array<{ label: string; value: string | number }>,\r\n rows: Array>,\r\n focusAreas: string[],\r\n dataSet: ReportDataSet,\r\n) {\r\n const insights: string[] = [];\r\n\r\n if (metrics.length > 0) {\r\n const firstMetric = metrics[0];\r\n insights.push(`${firstMetric.label} is ${firstMetric.value} in the current snapshot.`);\r\n }\r\n\r\n if (focusAreas.includes(\"risks\") && rows.length > 0) {\r\n const activeSignals = rows.filter((row) => row.active === true || row.risk === true || row.label?.toLowerCase().includes(\"risk\"));\r\n if (activeSignals.length > 0) {\r\n insights.push(`Risk signals are visible across ${activeSignals.length} entry${activeSignals.length === 1 ? \"\" : \"ies\"}.`);\r\n }\r\n }\r\n\r\n if (focusAreas.includes(\"fees\") && dataSet.network?.baseFee) {\r\n insights.push(`The current base fee is ${dataSet.network.baseFee} stroops.`);\r\n }\r\n\r\n if (template.aiHint) {\r\n insights.push(template.aiHint);\r\n }\r\n\r\n return insights.slice(0, 3);\r\n}\r\n\r\nexport function transformReportData(\r\n templateId: string,\r\n dataSet: ReportDataSet,\r\n options?: { focusAreas?: string[]; request?: string },\r\n): TransformedReportData {\r\n const template = getReportTemplate(templateId);\r\n const source = {\r\n account: dataSet.account || {},\r\n transactions: dataSet.transactions || {},\r\n network: dataSet.network || {},\r\n activity: dataSet.activity || [],\r\n risks: dataSet.risks || [],\r\n };\r\n\r\n const metrics = template.components\r\n .filter((component) => component.type === \"metric\")\r\n .map((component) => {\r\n const value = getNestedValue(source, component.dataKey);\r\n const normalized = typeof value === \"number\" && component.dataKey.includes(\"successRate\")\r\n ? `${(value * 100).toFixed(1)}%`\r\n : value ?? \"N/A\";\r\n return { label: component.label, value: normalized };\r\n });\r\n\r\n const chartComponent = template.components.find((component) => component.type === \"chart\");\r\n const tableComponent = template.components.find((component) => component.type === \"table\");\r\n const chartData = normalizeRowSet(getNestedValue(source, chartComponent?.dataKey || \"activity\"));\r\n const rows = normalizeRowSet(getNestedValue(source, tableComponent?.dataKey || template.resource));\r\n const columns = Array.from(new Set(rows.flatMap((row) => Object.keys(row)))).slice(0, 8);\r\n const focusAreas = options?.focusAreas || [];\r\n\r\n return {\r\n templateId: template.id,\r\n generatedAt: new Date().toISOString(),\r\n metrics,\r\n chartData,\r\n rows,\r\n columns,\r\n insights: buildNarrativeInsights(template, metrics, rows, focusAreas, dataSet),\r\n summary: options?.request ? `AI-generated ${template.name} summary based on: ${options.request}` : `${template.name} summary`,\r\n focusAreas,\r\n };\r\n}\r\n\r\nexport function createReportCache(ttlMs = 5 * 60 * 1000) {\r\n const entries = new Map();\r\n\r\n return {\r\n get(key: string) {\r\n const entry = entries.get(key);\r\n if (!entry) return undefined;\r\n if (entry.expiresAt <= Date.now()) {\r\n entries.delete(key);\r\n return undefined;\r\n }\r\n return entry.value;\r\n },\r\n set(key: string, value: any) {\r\n entries.set(key, { value, expiresAt: Date.now() + ttlMs });\r\n return value;\r\n },\r\n remember(key: string, factory: () => any) {\r\n const cached = this.get(key);\r\n if (cached !== undefined) return cached;\r\n return this.set(key, factory());\r\n },\r\n clear() {\r\n entries.clear();\r\n },\r\n size() {\r\n return entries.size;\r\n },\r\n };\r\n}\r\n\r\nexport function exportReportAsJson(template: ReportTemplate, data: TransformedReportData) {\r\n return JSON.stringify({ template, data }, null, 2);\r\n}\r\n\r\nexport function exportReportAsCsv(data: TransformedReportData) {\r\n const metricRows: Array> = data.metrics.map((metric) => ({\r\n section: \"metric\",\r\n label: metric.label,\r\n value: metric.value,\r\n }));\r\n const tableRows: Array> = data.rows.map((row) => ({\r\n section: \"row\",\r\n ...row,\r\n }));\r\n const rows: Array> = [...metricRows, ...tableRows];\r\n const headers = Array.from(new Set(rows.flatMap((row) => Object.keys(row))));\r\n const body = rows.map((row) => headers.map((header) => escapeCsvValue(row[header])).join(\",\"));\r\n return [headers.join(\",\"), ...body].join(\"\\n\");\r\n}\r\n\r\nexport function createPdfReportPayload(template: ReportTemplate, data: TransformedReportData) {\r\n const metricHtml = data.metrics\r\n .map((metric) => `
  • ${metric.label}: ${metric.value}
  • `)\r\n .join(\"\");\r\n const insightHtml = (data.insights || []).map((insight) => `
  • ${insight}
  • `).join(\"\");\r\n const tableHead = data.columns.map((column) => `${column}`).join(\"\");\r\n const tableBody = data.rows\r\n .slice(0, 25)\r\n .map((row) => `${data.columns.map((column) => `${row[column] ?? \"\"}`).join(\"\")}`)\r\n .join(\"\");\r\n\r\n return {\r\n filename: `${sanitizeFilePart(template.name)}.pdf.html`,\r\n contentType: \"text/html\",\r\n html: `${template.name}

    ${template.name}

    ${template.description}

    Metrics

      ${metricHtml}

    Insights

      ${insightHtml}

    Data

    ${tableHead}${tableBody}
    `,\r\n chartData: data.chartData,\r\n };\r\n}\r\n\r\nexport function parseCronSchedule(expression: string) {\r\n const parts = expression.trim().split(/\\s+/);\r\n if (parts.length !== 5) {\r\n throw new Error(\"Report schedules use five-part cron expressions\");\r\n }\r\n\r\n return {\r\n minute: parts[0],\r\n hour: parts[1],\r\n dayOfMonth: parts[2],\r\n month: parts[3],\r\n dayOfWeek: parts[4],\r\n };\r\n}\r\n\r\nfunction resolveCronPart(part: string, current: number, min: number, max: number) {\r\n if (part === \"*\") return current;\r\n if (part.startsWith(\"*/\")) {\r\n const step = Number(part.slice(2));\r\n if (!Number.isFinite(step) || step <= 0) throw new Error(`Invalid cron step: ${part}`);\r\n const next = current + (step - (current % step));\r\n return next > max ? min : next;\r\n }\r\n const exact = Number(part);\r\n if (!Number.isInteger(exact) || exact < min || exact > max) {\r\n throw new Error(`Invalid cron value: ${part}`);\r\n }\r\n return exact;\r\n}\r\n\r\nexport function getNextRunPreview(expression: string, from = new Date()) {\r\n const cron = parseCronSchedule(expression);\r\n const next = new Date(from);\r\n next.setSeconds(0, 0);\r\n next.setMinutes(next.getMinutes() + 1);\r\n next.setMinutes(resolveCronPart(cron.minute, next.getMinutes(), 0, 59));\r\n next.setHours(resolveCronPart(cron.hour, next.getHours(), 0, 23));\r\n\r\n if (next.getTime() <= from.getTime()) {\r\n next.setDate(next.getDate() + 1);\r\n }\r\n\r\n return next.toISOString();\r\n}\r\n\r\nfunction isEmail(value: string) {\r\n return /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(value);\r\n}\r\n\r\nfunction isWebhook(value?: string) {\r\n return !value || /^https:\\/\\/.+/i.test(value);\r\n}\r\n\r\nexport function createReportSchedule(input: Omit): ReportSchedule {\r\n parseCronSchedule(input.cron);\r\n if (input.channels.includes(\"email\") && !input.recipients.every(isEmail)) {\r\n throw new Error(\"Email report schedules require valid recipients\");\r\n }\r\n if (input.channels.includes(\"webhook\") && !isWebhook(input.webhookUrl)) {\r\n throw new Error(\"Webhook report schedules require an HTTPS URL\");\r\n }\r\n\r\n return {\r\n ...input,\r\n timezone: input.timezone || Intl.DateTimeFormat().resolvedOptions().timeZone,\r\n nextRunAt: getNextRunPreview(input.cron),\r\n };\r\n}\r\n\r\nexport function buildDeliveryPlan(schedule: ReportSchedule, template: ReportTemplate, data: TransformedReportData) {\r\n return schedule.channels.map((channel) => ({\r\n channel,\r\n target: channel === \"email\" ? schedule.recipients.join(\", \") : schedule.webhookUrl,\r\n subject: `${template.name} report`,\r\n attachments: [\r\n { filename: `${sanitizeFilePart(template.name)}.json`, contentType: \"application/json\", body: exportReportAsJson(template, data) },\r\n { filename: `${sanitizeFilePart(template.name)}.csv`, contentType: \"text/csv\", body: exportReportAsCsv(data) },\r\n createPdfReportPayload(template, data),\r\n ],\r\n }));\r\n}\r\n","import React, { useMemo, useState } from \"react\";\r\nimport {\r\n BarChart3,\r\n CalendarClock,\r\n Download,\r\n FileJson,\r\n FileText,\r\n Gauge,\r\n Mail,\r\n Save,\r\n Table2,\r\n Webhook,\r\n} from \"lucide-react\";\r\nimport {\r\n buildDeliveryPlan,\r\n buildHorizonQuery,\r\n createPdfReportPayload,\r\n createReportSchedule,\r\n exportReportAsCsv,\r\n exportReportAsJson,\r\n getAllReportTemplates,\r\n getNextRunPreview,\r\n getReportTemplate,\r\n loadSavedReportTemplates,\r\n parseNaturalLanguageRequest,\r\n REPORT_COMPONENT_PALETTE,\r\n REPORT_TEMPLATES,\r\n saveReportTemplate,\r\n transformReportData,\r\n type ReportComponentDefinition,\r\n type ReportResource,\r\n} from \"../../lib/customReports\";\r\n\r\ninterface CustomReportsProps {\r\n analytics: any;\r\n}\r\n\r\nconst fieldStyle: React.CSSProperties = {\r\n width: \"100%\",\r\n minHeight: \"36px\",\r\n borderRadius: \"var(--radius-md)\",\r\n border: \"1px solid var(--border)\",\r\n background: \"var(--bg-elevated)\",\r\n color: \"var(--text-primary)\",\r\n padding: \"8px 10px\",\r\n fontSize: \"12px\",\r\n};\r\n\r\nconst buttonStyle: React.CSSProperties = {\r\n borderRadius: \"var(--radius-md)\",\r\n border: \"1px solid var(--border)\",\r\n background: \"var(--bg-elevated)\",\r\n color: \"var(--text-primary)\",\r\n padding: \"8px 10px\",\r\n display: \"inline-flex\",\r\n alignItems: \"center\",\r\n gap: \"6px\",\r\n fontSize: \"12px\",\r\n cursor: \"pointer\",\r\n};\r\n\r\nfunction downloadText(filename: string, content: string, type: string) {\r\n const blob = new Blob([content], { type });\r\n const url = URL.createObjectURL(blob);\r\n const link = document.createElement(\"a\");\r\n link.href = url;\r\n link.download = filename;\r\n link.click();\r\n URL.revokeObjectURL(url);\r\n}\r\n\r\nfunction componentIcon(type: ReportComponentDefinition[\"type\"]) {\r\n if (type === \"chart\") return ;\r\n if (type === \"table\") return ;\r\n return ;\r\n}\r\n\r\nexport default function CustomReports({ analytics }: CustomReportsProps) {\r\n const [templateId, setTemplateId] = useState(REPORT_TEMPLATES[0].id);\r\n const [resource, setResource] = useState(\"transactions\");\r\n const [accountId, setAccountId] = useState(\"\");\r\n const [limit, setLimit] = useState(50);\r\n const [cron, setCron] = useState(\"0 9 * * 1\");\r\n const [email, setEmail] = useState(\"\");\r\n const [webhookUrl, setWebhookUrl] = useState(\"\");\r\n const [components, setComponents] = useState(REPORT_TEMPLATES[0].components);\r\n const [requestText, setRequestText] = useState(\"Create a weekly account activity report for GABC with emphasis on risks and fees\");\r\n const [savedTemplates, setSavedTemplates] = useState(loadSavedReportTemplates());\r\n\r\n const template = getReportTemplate(templateId);\r\n const parsedRequest = useMemo(() => parseNaturalLanguageRequest(requestText), [requestText]);\r\n const reportData = useMemo(\r\n () => transformReportData(template.id, analytics || {}, { focusAreas: parsedRequest.focusAreas, request: parsedRequest.prompt }),\r\n [analytics, parsedRequest.focusAreas, parsedRequest.prompt, template.id],\r\n );\r\n const query = useMemo(\r\n () =>\r\n buildHorizonQuery({\r\n resource,\r\n accountId: accountId || undefined,\r\n limit,\r\n filters: { include_failed: resource === \"transactions\" ? \"true\" : undefined },\r\n }),\r\n [accountId, limit, resource],\r\n );\r\n const schedule = useMemo(() => {\r\n try {\r\n return createReportSchedule({\r\n id: `${template.id}-weekly`,\r\n reportId: template.id,\r\n cron,\r\n timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,\r\n enabled: true,\r\n channels: webhookUrl ? [\"email\", \"webhook\"] : [\"email\"],\r\n recipients: email ? [email] : [],\r\n webhookUrl: webhookUrl || undefined,\r\n });\r\n } catch {\r\n return null;\r\n }\r\n }, [cron, email, template.id, webhookUrl]);\r\n const deliveryPlan = schedule ? buildDeliveryPlan(schedule, template, reportData) : [];\r\n\r\n const handleTemplateChange = (nextTemplateId: string) => {\r\n const nextTemplate = getReportTemplate(nextTemplateId);\r\n setTemplateId(nextTemplate.id);\r\n setResource(nextTemplate.resource);\r\n setComponents(nextTemplate.components);\r\n };\r\n\r\n const handleRequestApply = () => {\r\n const nextTemplate = getReportTemplate(parsedRequest.templateId);\r\n setTemplateId(nextTemplate.id);\r\n setResource(nextTemplate.resource);\r\n setAccountId(parsedRequest.accountId || accountId);\r\n setComponents(nextTemplate.components);\r\n };\r\n\r\n const handleSaveTemplate = () => {\r\n const saved = saveReportTemplate({\r\n ...template,\r\n id: `${template.id}-saved-${Date.now()}`,\r\n name: `${template.name} (Saved)`,\r\n description: `${template.description} Saved from the dashboard.`,\r\n category: template.category || \"custom\",\r\n tags: [...(template.tags || []), \"saved\"],\r\n });\r\n setSavedTemplates(loadSavedReportTemplates());\r\n return saved;\r\n };\r\n\r\n const handleDrop = (event: React.DragEvent) => {\r\n event.preventDefault();\r\n const droppedId = event.dataTransfer.getData(\"application/report-component\");\r\n const dropped = REPORT_COMPONENT_PALETTE.find((component) => component.id === droppedId);\r\n if (!dropped) return;\r\n setComponents((current) => [\r\n ...current,\r\n { ...dropped, id: `${dropped.id}-${Date.now()}`, label: `Custom ${dropped.label}` },\r\n ]);\r\n };\r\n\r\n const exportJson = () => {\r\n downloadText(`${template.id}.json`, exportReportAsJson(template, reportData), \"application/json\");\r\n };\r\n\r\n const exportCsv = () => {\r\n downloadText(`${template.id}.csv`, exportReportAsCsv(reportData), \"text/csv\");\r\n };\r\n\r\n const exportPdf = () => {\r\n const payload = createPdfReportPayload(template, reportData);\r\n downloadText(payload.filename, payload.html, payload.contentType);\r\n };\r\n\r\n return (\r\n \r\n
    \r\n
    \r\n
    \r\n Custom Reports\r\n
    \r\n
    \r\n Build reusable Stellar analytics reports with exports and scheduled delivery.\r\n
    \r\n
    \r\n
    \r\n \r\n \r\n \r\n \r\n
    \r\n
    \r\n\r\n
    \r\n
    \r\n \r\n\r\n