@cofhe/react 0.0.0-alpha-20260707074148 → 0.0.0-alpha-20260721113524
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -18,11 +18,11 @@ pnpm add @cofhe/react @cofhe/sdk
|
|
|
18
18
|
import { CofheProvider } from '@cofhe/react';
|
|
19
19
|
import { createCofheClient } from '@cofhe/sdk/web';
|
|
20
20
|
|
|
21
|
-
const
|
|
21
|
+
const cofheClient = createCofheClient(config);
|
|
22
22
|
|
|
23
23
|
function App() {
|
|
24
24
|
return (
|
|
25
|
-
<CofheProvider
|
|
25
|
+
<CofheProvider cofheClient={cofheClient}>
|
|
26
26
|
<YourApp />
|
|
27
27
|
</CofheProvider>
|
|
28
28
|
);
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/runner/work/cofhesdk/cofhesdk/packages/react/dist/index.cjs","../src/index.ts","../src/hooks/useCofheDecryptionActivity.ts"],"names":[],"mappings":"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AA;AAEuC,IAAA;AACR,IAAA;AAGgB,IAAA;AACtB,IAAA;AACX,MAAA;AAC2C,MAAA;AAC7B,MAAA;AACS,MAAA;AAC+B,MAAA;AACpE,IAAA;AAOK,IAAA;AACuC,MAAA;AAC2B,MAAA;AAC3D,MAAA;AACL,QAAA;AAC2C,QAAA;AAC9C,QAAA;AACa,QAAA;AACiC,UAAA;AACI,UAAA;AAClD,QAAA;AACD,MAAA;AACH,IAAA;AAGsC,IAAA;AACxB,MAAA;AACiD,MAAA;AACd,MAAA;AACD,MAAA;AAIhC,MAAA;AAQmB,MAAA;AAC7B,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACI,MAAA;AACO,QAAA;AACe,QAAA;AACZ,QAAA;AACC,QAAA;AACgB,QAAA;AACQ,QAAA;AACD,QAAA;AACP,QAAA;AACjB,UAAA;AACqC,UAAA;AAC9C,QAAA;AAC8B,UAAA;AACoB,UAAA;AACzD,QAAA;AACgD,MAAA;AAEtC,QAAA;AAC2B,QAAA;AACvC,MAAA;AAEkB,MAAA;AACV,MAAA;AACC,QAAA;AACC,QAAA;AACwB,QAAA;AAChC,QAAA;AACe,QAAA;AACA,QAAA;AACK,QAAA;AACG,QAAA;AAChB,QAAA;AACP,QAAA;AACA,QAAA;AACA,QAAA;AACW,QAAA;AACC,QAAA;AACZ,QAAA;AACD,MAAA;AACH,IAAA;AAGmC,IAAA;AACb,MAAA;AAKZ,MAAA;AAMA,MAAA;AACY,QAAA;AACV,QAAA;AACe,QAAA;AACf,QAAA;AACS,QAAA;AACA,QAAA;AACK,QAAA;AACG,QAAA;AAClB,QAAA;AACP,QAAA;AACa,QAAA;AACF,QAAA;AACG,QAAA;AACf,MAAA;AACH,IAAA;AAGiD,IAAA;AACY,MAAA;AAC7D,IAAA;AAEe,IAAA;AACD,MAAA;AAC+B,MAAA;AACU,MAAA;AACJ,MAAA;AACI,MAAA;AACU,MAAA;AACjE,IAAA;AAGgD,IAAA;AACrC,MAAA;AACF,MAAA;AACA,MAAA;AACE,MAAA;AACH,MAAA;AACE,MAAA;AACJ,MAAA;AACN,IAAA;AACqD,IAAA;AAEc,IAAA;AACC,IAAA;AAEP,EAAA;AAElC,EAAA;AAC/B;AFtFwE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"/home/runner/work/cofhesdk/cofhesdk/packages/react/dist/index.cjs","sourcesContent":[null,"// Providers\nexport { CofheProvider, useCofheContext } from './providers/index';\n\n// Hooks\nexport {\n ETH_ADDRESS_LOWERCASE,\n getCofheTokenClaimUnshieldedCallArgs,\n getCofheTokenShieldCallArgs,\n getCofheTokenUnshieldCallArgs,\n useCofheActivePermit,\n useCofheAllPermits,\n useCofheClient,\n useCofheConnection,\n useCofheEnabled,\n useCofheEncrypt,\n useCofhePublicClient,\n useCofheRemovePermit,\n useCofheSelectPermit,\n useCofheSimulateWriteContract,\n useCofheStatuses,\n useCofheTokenClaimable,\n useCofheTokenClaims,\n useCofheTokenApprove,\n useCofheTokenClaimUnshielded,\n useCofheTokenDecryptedBalance,\n useCofheTokenPublicBalance,\n useCofheTokenLists,\n useCofheToken,\n useCofheTokens,\n useCofheTokensClaimable,\n useCofheTokenShield,\n useCofheTokensWithExistingEncryptedBalances,\n useCofheTokenTransactions,\n useCofheTokenTransfer,\n useResolvedCofheToken,\n useCofheTransactions,\n addCofheTransaction,\n useCofheTokenUnshield,\n useCofheWalletClient,\n useCofheWriteContract,\n useCoingeckoContractMarketChartRange,\n useCoingeckoUsdPrice,\n useTokenAllowance,\n useTokensWithPublicBalances,\n useTransactionReceiptsByHash,\n type ClaimableAmountByTokenAddress,\n type CoingeckoMarketChartPoint,\n type Erc20Pair,\n type UnshieldClaim,\n type UnshieldClaimsSummary,\n type UnshieldClaimsSummaryByTokenAddress,\n type UseCoingeckoContractMarketChartRangeInput,\n type UseCoingeckoContractMarketChartRangeOptions,\n type UseCoingeckoUsdPriceInput,\n type UseCoingeckoUsdPriceOptions,\n type UseCofheTokenTransactionsInput,\n type UseCofheTokenTransactionsResult,\n type UseTransactionReceiptsByHashInput,\n type AddCofheTransactionInput,\n} from '@/hooks/index';\n\nexport { useCofheEncryptAndWriteContract } from '@/hooks/useCofheEncryptAndWriteContract';\nexport { useCofheReadContractAndDecrypt } from '@/hooks/useCofheReadContractAndDecrypt';\n\n// Utils\nexport {\n FheTypesList,\n formatRelativeTime,\n getBlockExplorerAddressUrl,\n getBlockExplorerTokenUrl,\n getBlockExplorerTxUrl,\n getBlockExplorerUrl,\n isEthPair,\n isWrappedEthToken,\n truncateHash,\n} from './utils/index';\n\n// Stores\nexport { useCustomTokensStore } from './stores/customTokensStore';\n\nexport {\n actionToString,\n isCustomTransactionActionType,\n statusToString,\n transactionMatchesToken,\n TransactionActionType,\n TransactionStatus,\n useTransactionStore,\n type Transaction,\n type BuiltInTransactionActionType,\n type CustomTransactionActionType,\n type JsonValue,\n type NewTransaction,\n type TransactionActionString,\n type TransactionStatusString,\n type TransactionStore,\n} from './stores/transactionStore';\n\nexport { createCofheConfig } from './config';\nexport type { CofheReactLogger, CofheReactLoggerMethod } from './config';\n\n// Types\nexport type {\n CofheClientConfig,\n CofheContextValue,\n CofheProviderProps,\n TransactionRenderer,\n TransactionRendererProps,\n TransactionRenderers,\n} from './types/index';\n\nexport { createCofheClient } from '@cofhe/sdk/web';\n\nexport { useCofheCreatePermit } from '@/hooks/permits/useCofheCreatePermit';\nexport { useCofheNavigateToCreatePermit } from '@/hooks/permits/useCofheNavigateToCreatePermit';\nexport { useCofheAutoConnect } from '@/hooks/useCofheAutoConnect';\nexport { CofheFloatingButtonProvider, sortCofheStatuses } from './components/index';\nexport { COFHE_STATUS_IDS, CofheStatusActionIntents } from './components/CofheFloatingButton/types';\n\nexport type { CofheConfigWithReact as CofhesdkConfigWithReact } from './config';\n\nexport type { CofheStatus, CofheStatusActionIntent, CofheStatusId } from './components/CofheFloatingButton/types';\nexport type { ConfidentialToken } from './types/token';\n\nexport type { CofheDecryptMeta, CofheQueryMeta } from './meta';\n\nexport { useCofheDecryptionActivity } from '@/hooks/useCofheDecryptionActivity';\nexport type {\n DecryptionActivityRow,\n DecryptionActivityResult,\n DecryptionActivityCategory,\n UseCofheDecryptionActivityOptions,\n FetchStageState,\n DecryptStageState,\n PermitState,\n} from '@/hooks/useCofheDecryptionActivity';\n\nexport { useInternalQueryClient } from './providers/index';\n\n// Type bridges for cross-repo / multi-instance viem peer dependency scenarios\nexport { asCofhePublicClient, tryAsCofhePublicClient, asCofheWalletClient, tryAsCofheWalletClient } from './utils/viemClientBridge';\nexport type {\n PublicClientLike as CofhePublicClientLike,\n WalletClientLike as CofheWalletClientLike,\n} from './utils/viemClientBridge';\n\n// Block-aware cache invalidation primitives.\n//\n// These are the building blocks behind the SDK's own \"wait until the serving RPC\n// node has the mined block before returning a read\" behaviour. They are exported\n// so consumers (e.g. a wagmi-based app) can build the same reliability into their\n// own reads + post-tx invalidation, sharing THIS module's single invalidation-\n// context store — so an invalidation registered here is honoured by both the\n// SDK's confidential reads and the consumer's own block-aware queries.\nexport {\n invalidateQueriesWithContext,\n withInvalidationContext,\n findMatchingInvalidationContext,\n consumeInvalidationContext,\n type InvalidationContextQueryFilters,\n type QueryFunctionWithInvalidationContext,\n} from './utils/invalidationContext';\nexport {\n maybeWaitUntilRpcAware,\n maybeWaitUntilRpcAwareAndReadContract,\n type WaitUntilRpcAwareAndReadContractOptions,\n type ReadContractResult,\n} from './utils/waitUntilRpcAwareAndReadContract';\nexport { resolveReceiptBlockHash } from './utils/resolveReceiptBlockHash';\nexport { useInvalidationContextStore, type InvalidationContextEntry } from './stores/invalidationContextStore';\n","import { useCallback, useEffect, useMemo, useReducer, useRef } from 'react';\nimport { useInternalQueryClient } from '@/providers';\nimport { useCofheAccount, useCofheChainId } from './useCofheConnection';\nimport { useCofheActivePermit } from './useCofhePermits';\nimport type { CofheQueryMeta } from '@/meta';\n\n// ============================================================================\n// Decryption activity — the lifecycle view of confidential reads + decryptions.\n// ============================================================================\n//\n// A confidential value is a two-stage pipeline, both stages living as react-query\n// queries on the SDK's internal QueryClient:\n// A) FETCH — read the ciphertext handle on-chain (`cofheReadContract`),\n// whose data carries the `ctHash`.\n// B) DECRYPT— decrypt that handle off-chain (`decryptCiphertext`, keyed\n// BY the ctHash).\n//\n// This hook observes the cache, correlates the two stages by ctHash, and returns\n// one row per confidential value with a recognizable contract/method/label (from\n// each query's `meta`) — surfacing states a plain error/loading flag can't:\n// • \"blocked\" — gated off by a missing/invalid permit (never runs, never errors)\n// • \"stale\" — fetched, but the decrypt is pending far too long / never lands\n// Consumers render the rows; no query-key parsing or side registries required.\n\nconst DEFAULT_STALE_MS = 25_000;\nconst nowSec = () => Math.floor(Date.now() / 1000);\n\n/** 'idle' = a read/decrypt query exists but is disabled/never-ran (fetchStatus 'idle'), vs 'pending' (in flight). */\nexport type FetchStageState = 'ok' | 'pending' | 'idle' | 'error' | 'empty';\nexport type DecryptStageState = 'ok' | 'pending' | 'idle' | 'stale' | 'error' | 'blocked' | 'absent';\nexport type PermitState = 'valid' | 'expired' | 'unsigned' | 'none';\n/** Coarse bucket for filtering: something wrong / decrypted / nothing conclusive. */\nexport type DecryptionActivityCategory = 'error' | 'success' | 'idle';\n\nexport interface DecryptionActivityRow {\n key: string;\n /** Canonical decimal ctHash, when known. */\n ctHash?: string;\n /** 0x…-shortened ctHash for display. */\n ctHashShort?: string;\n /** The originating query metadata (contract / method / label / consumer fields). */\n meta?: CofheQueryMeta;\n /** Convenience shortcuts pulled from meta. */\n chainId?: number;\n address?: string;\n functionName?: string;\n label?: string;\n fetch: FetchStageState;\n decrypt: DecryptStageState;\n category: DecryptionActivityCategory;\n /** Why the row is blocked, e.g. \"permit none\". */\n blockedReason?: string;\n /** How long the decrypt has been pending, ms (drives \"stale\"). */\n pendingMs?: number;\n updatedAt: number;\n /** Whether re-running is possible (false for gated/idle reads with nothing enabled). */\n canRetry: boolean;\n /** Re-run this value's read and/or decrypt. */\n retry: () => void;\n}\n\nexport interface DecryptionActivityResult {\n rows: DecryptionActivityRow[];\n counts: { total: number; ok: number; pending: number; stale: number; blocked: number; error: number };\n permit: { state: PermitState; expiresInSec?: number };\n /** Wipe the whole SDK query cache; mounted reads/decryptions refetch from scratch. */\n clearCache: () => void;\n}\n\nexport interface UseCofheDecryptionActivityOptions {\n /** How long a decrypt may stay pending before it's reported \"stale\" (default 25s). */\n staleMs?: number;\n}\n\n// Minimal structural view of a cached query — enough to classify without depending\n// on react-query's concrete generic types.\ninterface QueryLike {\n queryKey: unknown;\n queryHash: string;\n meta?: CofheQueryMeta;\n state: { status: 'pending' | 'error' | 'success'; fetchStatus?: string; data?: unknown; dataUpdatedAt?: number };\n}\ninterface CacheLike {\n getAll: () => QueryLike[];\n subscribe: (cb: () => void) => () => void;\n}\ninterface ClientLike {\n getQueryCache: () => CacheLike;\n refetchQueries: (filters: { queryKey: unknown; exact?: boolean }) => Promise<unknown>;\n clear: () => void;\n}\n\nfunction normalizeCt(x: unknown): string | undefined {\n if (x === null || x === undefined) return undefined;\n try {\n return BigInt(x as string | number | bigint).toString();\n } catch {\n const s = String(x);\n return s && s !== '[object Object]' ? s : undefined;\n }\n}\n\n// A ctHash of 0 is not a real handle: reads return it for an absent/encrypted-zero\n// value and the decrypt is gated on `ctHash > 0n`, so treat it as \"no handle\".\nfunction isZeroCt(ct: string | undefined): boolean {\n if (!ct) return false;\n try {\n return BigInt(ct) === 0n;\n } catch {\n return false;\n }\n}\n\nfunction shortCt(decimal: string): string {\n try {\n const hex = BigInt(decimal).toString(16);\n return hex.length > 10 ? `0x${hex.slice(0, 6)}…${hex.slice(-4)}` : `0x${hex}`;\n } catch {\n return decimal;\n }\n}\n\nfunction extractCtHash(data: unknown): string | undefined {\n if (data === null || data === undefined) return undefined;\n if (typeof data === 'bigint') return normalizeCt(data);\n if (typeof data === 'object' && data !== null && 'ctHash' in (data as Record<string, unknown>)) {\n return normalizeCt((data as { ctHash: unknown }).ctHash);\n }\n return undefined;\n}\n\n// The read key bakes the transient activePermitHash + enabled flags into its tail,\n// so the SAME value gets a fresh cache entry each time a permit appears/rotates.\n// Its stable identity is [prefix, chainId, address, fn, args] (indices 0-4).\nfunction stableReadKey(k: unknown[]): string {\n try {\n return JSON.stringify(k.slice(0, 5));\n } catch {\n return String(k[1]) + '|' + String(k[2]) + '|' + String(k[3]);\n }\n}\n\n// Progress of a read: ran (success/error) > in flight > idle/never-ran.\nfunction readProgress(q: QueryLike): number {\n if (q.state.status === 'success' || q.state.status === 'error') return 2;\n if (q.state.fetchStatus === 'fetching') return 1;\n return 0;\n}\nfunction isFresherRead(candidate: QueryLike, current: QueryLike): boolean {\n const pc = readProgress(candidate);\n const pk = readProgress(current);\n if (pc !== pk) return pc > pk;\n return (candidate.state.dataUpdatedAt ?? 0) > (current.state.dataUpdatedAt ?? 0);\n}\n\nfunction categoryFor(fetch: FetchStageState, decrypt: DecryptStageState): DecryptionActivityCategory {\n if (fetch === 'error' || decrypt === 'error' || decrypt === 'blocked' || decrypt === 'stale') return 'error';\n if (decrypt === 'ok') return 'success';\n return 'idle';\n}\n\n/**\n * Observe the ctHash-fetch → decrypt pipeline on the SDK's QueryClient, correlated\n * by ctHash and cross-referenced against the active permit. Must be used inside the\n * Cofhe provider.\n */\nexport function useCofheDecryptionActivity(options?: UseCofheDecryptionActivityOptions): DecryptionActivityResult {\n const staleMs = options?.staleMs ?? DEFAULT_STALE_MS;\n const queryClient = useInternalQueryClient() as unknown as ClientLike;\n const account = useCofheAccount();\n const chainId = useCofheChainId();\n const active = useCofheActivePermit();\n const permitObj = active?.permit;\n\n // Track when each decrypt first went pending, so \"stale\" is real elapsed time\n // (react-query doesn't expose a fetch-start timestamp for a never-resolved query).\n const pendingSinceRef = useRef(new Map<string, number>());\n\n // Re-render on cache changes AND on a slow tick (staleness is time-based, not\n // event-driven — a query sitting pending emits no cache events).\n //\n // Coalesce cache events to one bump per animation frame. `cache.subscribe` fires\n // synchronously on EVERY cache event (including observer option/result updates),\n // and a consumer re-render can itself emit fresh cache events — an unbounded\n // bump→render→event→bump storm that pins the main thread and starves unrelated\n // updates (e.g. a route change never commits). One bump per frame keeps the view\n // live while capping re-renders so the loop can't run away.\n const [version, bump] = useReducer((n: number) => n + 1, 0);\n useEffect(() => {\n const cache = queryClient.getQueryCache();\n let scheduled = false;\n const schedule = () => {\n if (scheduled) return;\n scheduled = true;\n const run = () => {\n scheduled = false;\n bump();\n };\n if (typeof requestAnimationFrame === 'function') requestAnimationFrame(run);\n else setTimeout(run, 16);\n };\n const unsub = cache.subscribe(schedule);\n const tick = setInterval(bump, 5_000);\n return () => {\n unsub();\n clearInterval(tick);\n };\n }, [queryClient]);\n\n const clearCache = useCallback(() => queryClient.clear(), [queryClient]);\n\n const data = useMemo(() => {\n const cache = queryClient.getQueryCache();\n const queries = cache.getAll();\n const now = Date.now();\n\n const refetch = (key: unknown) => void queryClient.refetchQueries({ queryKey: key, exact: true });\n\n const permitState: PermitState = !permitObj\n ? 'none'\n : !permitObj.issuerSignature || permitObj.issuerSignature === '0x'\n ? 'unsigned'\n : permitObj.expiration <= nowSec()\n ? 'expired'\n : 'valid';\n const permitValid = permitState === 'valid';\n\n // Index decrypt queries by ctHash (source contract + label come from meta).\n const decryptByCt = new Map<\n string,\n { state: 'ok' | 'pending' | 'idle' | 'error'; pendingMs?: number; key?: unknown; meta?: CofheQueryMeta }\n >();\n const seenPending = new Set<string>();\n for (const q of queries) {\n const k = q.queryKey;\n if (!Array.isArray(k) || k[0] !== 'decryptCiphertext') continue;\n const ct = normalizeCt(k[1]);\n if (!ct || isZeroCt(ct)) continue;\n const base = { key: q.queryKey, meta: q.meta };\n if (q.state.status === 'success') {\n decryptByCt.set(ct, { state: 'ok', ...base });\n pendingSinceRef.current.delete(ct);\n } else if (q.state.status === 'error') {\n decryptByCt.set(ct, { state: 'error', ...base });\n pendingSinceRef.current.delete(ct);\n } else if (q.state.fetchStatus === 'fetching') {\n seenPending.add(ct);\n let since = pendingSinceRef.current.get(ct);\n if (since === undefined) {\n since = now;\n pendingSinceRef.current.set(ct, since);\n }\n decryptByCt.set(ct, { state: 'pending', pendingMs: now - since, ...base });\n } else {\n // status 'pending' but fetchStatus 'idle' → disabled / never ran.\n pendingSinceRef.current.delete(ct);\n decryptByCt.set(ct, { state: 'idle', ...base });\n }\n }\n\n const rows: DecryptionActivityRow[] = [];\n const usedCt = new Set<string>();\n\n // Collapse per-permit/enabled key rotations to one entry per value.\n const readByValue = new Map<string, QueryLike>();\n for (const q of queries) {\n const k = q.queryKey;\n if (!Array.isArray(k) || k[0] !== 'cofheReadContract') continue;\n const id = stableReadKey(k);\n const existing = readByValue.get(id);\n if (!existing || isFresherRead(q, existing)) readByValue.set(id, q);\n }\n\n const pushRow = (\n row: Omit<DecryptionActivityRow, 'category' | 'canRetry' | 'retry'> & {\n fetchKey?: unknown;\n decryptKey?: unknown;\n }\n ) => {\n const { fetchKey, decryptKey, ...rest } = row;\n const canRetry = rest.fetch !== 'idle' && (fetchKey !== undefined || decryptKey !== undefined);\n rows.push({\n ...rest,\n category: categoryFor(rest.fetch, rest.decrypt),\n canRetry,\n retry: () => {\n if (fetchKey !== undefined) refetch(fetchKey);\n if (decryptKey !== undefined) refetch(decryptKey);\n },\n });\n };\n\n // One row per confidential value; attach its decrypt stage by ctHash.\n for (const q of readByValue.values()) {\n const m = q.meta;\n const ctRaw = q.state.status === 'success' ? extractCtHash(q.state.data) : undefined;\n const ct = ctRaw && !isZeroCt(ctRaw) ? ctRaw : undefined;\n const fetchInFlight = q.state.fetchStatus === 'fetching';\n const fetchState: FetchStageState =\n q.state.status === 'error'\n ? 'error'\n : q.state.status === 'pending'\n ? fetchInFlight\n ? 'pending'\n : 'idle'\n : ct\n ? 'ok'\n : 'empty';\n\n let decrypt: DecryptStageState = 'absent';\n let blockedReason: string | undefined;\n let pendingMs: number | undefined;\n let decryptKey: unknown;\n let decryptMeta: CofheQueryMeta | undefined;\n if (ct) {\n usedCt.add(ct);\n const d = decryptByCt.get(ct);\n decryptKey = d?.key;\n decryptMeta = d?.meta;\n if (d?.state === 'ok') decrypt = 'ok';\n else if (d?.state === 'error') decrypt = 'error';\n else if (d?.state === 'idle') decrypt = 'idle';\n else if (d?.state === 'pending') {\n pendingMs = d.pendingMs;\n decrypt = (d.pendingMs ?? 0) > staleMs ? 'stale' : 'pending';\n } else {\n decrypt = permitValid ? 'absent' : 'blocked';\n if (!permitValid) blockedReason = `permit ${permitState}`;\n }\n } else if (fetchState === 'idle' && !permitValid) {\n // The read is gated off (no valid permit) — blocked before any ctHash.\n decrypt = 'blocked';\n blockedReason = `permit ${permitState}`;\n }\n\n const meta = m ?? decryptMeta;\n pushRow({\n key: q.queryHash,\n ctHash: ct,\n ctHashShort: ct ? shortCt(ct) : undefined,\n meta,\n chainId: meta?.chainId,\n address: meta?.address,\n functionName: meta?.functionName,\n label: meta?.consumer?.label,\n fetch: fetchState,\n decrypt,\n blockedReason,\n pendingMs,\n updatedAt: now,\n fetchKey: q.queryKey,\n decryptKey,\n });\n }\n\n // Orphan decrypts (a ctHash being decrypted with no fetch query in cache).\n for (const [ct, d] of decryptByCt) {\n if (usedCt.has(ct)) continue;\n const decrypt: DecryptStageState =\n d.state === 'ok'\n ? 'ok'\n : d.state === 'error'\n ? 'error'\n : d.state === 'idle'\n ? 'idle'\n : (d.pendingMs ?? 0) > staleMs\n ? 'stale'\n : 'pending';\n pushRow({\n key: `decrypt:${ct}`,\n ctHash: ct,\n ctHashShort: shortCt(ct),\n meta: d.meta,\n chainId: d.meta?.chainId,\n address: d.meta?.address,\n functionName: d.meta?.functionName,\n label: d.meta?.consumer?.label,\n fetch: 'ok',\n decrypt,\n pendingMs: d.pendingMs,\n updatedAt: now,\n decryptKey: d.key,\n });\n }\n\n // Drop ctHashes we no longer see, so the pending-since map can't grow unbounded.\n for (const ct of pendingSinceRef.current.keys()) {\n if (!seenPending.has(ct)) pendingSinceRef.current.delete(ct);\n }\n\n const counts = {\n total: rows.length,\n ok: rows.filter((r) => r.decrypt === 'ok').length,\n pending: rows.filter((r) => r.decrypt === 'pending').length,\n stale: rows.filter((r) => r.decrypt === 'stale').length,\n blocked: rows.filter((r) => r.decrypt === 'blocked').length,\n error: rows.filter((r) => r.decrypt === 'error' || r.fetch === 'error').length,\n };\n\n // Most actionable first: blocked/stale/error, then pending, then done.\n const rank: Record<DecryptStageState, number> = {\n blocked: 0,\n stale: 1,\n error: 2,\n pending: 3,\n idle: 4,\n absent: 5,\n ok: 6,\n };\n rows.sort((a, b) => rank[a.decrypt] - rank[b.decrypt]);\n\n const expiresInSec = permitObj ? permitObj.expiration - nowSec() : undefined;\n return { rows, permit: { state: permitState, expiresInSec }, counts };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [queryClient, account, chainId, permitObj, staleMs, version]);\n\n return { ...data, clearCache };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/cofhesdk/cofhesdk/packages/react/dist/index.cjs","../src/index.ts","../src/hooks/useCofheDecryptionActivity.ts"],"names":[],"mappings":"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AA;AAEuC,IAAA;AACR,IAAA;AAGgB,IAAA;AACtB,IAAA;AACX,MAAA;AAC2C,MAAA;AAC7B,MAAA;AACS,MAAA;AAC+B,MAAA;AACpE,IAAA;AAOK,IAAA;AACuC,MAAA;AAC2B,MAAA;AAC3D,MAAA;AACL,QAAA;AAC2C,QAAA;AAC9C,QAAA;AACa,QAAA;AACiC,UAAA;AACI,UAAA;AAClD,QAAA;AACD,MAAA;AACH,IAAA;AAGsC,IAAA;AACxB,MAAA;AACiD,MAAA;AACd,MAAA;AACD,MAAA;AAIhC,MAAA;AAQmB,MAAA;AAC7B,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACI,MAAA;AACO,QAAA;AACe,QAAA;AACZ,QAAA;AACC,QAAA;AACgB,QAAA;AACQ,QAAA;AACD,QAAA;AACP,QAAA;AACjB,UAAA;AACqC,UAAA;AAC9C,QAAA;AAC8B,UAAA;AACoB,UAAA;AACzD,QAAA;AACgD,MAAA;AAEtC,QAAA;AAC2B,QAAA;AACvC,MAAA;AAEkB,MAAA;AACV,MAAA;AACC,QAAA;AACC,QAAA;AACwB,QAAA;AAChC,QAAA;AACe,QAAA;AACA,QAAA;AACK,QAAA;AACG,QAAA;AAChB,QAAA;AACP,QAAA;AACA,QAAA;AACA,QAAA;AACW,QAAA;AACC,QAAA;AACZ,QAAA;AACD,MAAA;AACH,IAAA;AAGmC,IAAA;AACb,MAAA;AAKZ,MAAA;AAMA,MAAA;AACY,QAAA;AACV,QAAA;AACe,QAAA;AACf,QAAA;AACS,QAAA;AACA,QAAA;AACK,QAAA;AACG,QAAA;AAClB,QAAA;AACP,QAAA;AACa,QAAA;AACF,QAAA;AACG,QAAA;AACf,MAAA;AACH,IAAA;AAGiD,IAAA;AACY,MAAA;AAC7D,IAAA;AAEe,IAAA;AACD,MAAA;AAC+B,MAAA;AACU,MAAA;AACJ,MAAA;AACI,MAAA;AACU,MAAA;AACjE,IAAA;AAGgD,IAAA;AACrC,MAAA;AACF,MAAA;AACA,MAAA;AACE,MAAA;AACH,MAAA;AACE,MAAA;AACJ,MAAA;AACN,IAAA;AACqD,IAAA;AAEc,IAAA;AACC,IAAA;AAEP,EAAA;AAElC,EAAA;AAC/B;AFtFwE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"/home/runner/work/cofhesdk/cofhesdk/packages/react/dist/index.cjs","sourcesContent":[null,"// Providers\nexport { CofheProvider, useCofheContext } from './providers/index';\n\n// Hooks\nexport {\n ETH_ADDRESS_LOWERCASE,\n getCofheTokenClaimUnshieldedCallArgs,\n getCofheTokenShieldCallArgs,\n getCofheTokenUnshieldCallArgs,\n useCofheActivePermit,\n useCofheAllPermits,\n useCofheClient,\n useCofheConnection,\n useCofheEnabled,\n useCofheEncrypt,\n useCofhePublicClient,\n useCofheRemovePermit,\n useCofheSelectPermit,\n useCofheSimulateWriteContract,\n useCofheStatuses,\n useCofheTokenClaimable,\n useCofheTokenClaims,\n useCofheTokenApprove,\n useCofheTokenClaimUnshielded,\n useCofheTokenDecryptedBalance,\n useCofheTokenPublicBalance,\n useCofheTokenLists,\n useCofheToken,\n useCofheTokens,\n useCofheTokensClaimable,\n useCofheTokenShield,\n useCofheTokensWithExistingEncryptedBalances,\n useCofheTokenTransactions,\n useCofheTokenTransfer,\n useResolvedCofheToken,\n useCofheTransactions,\n addCofheTransaction,\n useCofheTokenUnshield,\n useCofheWalletClient,\n useCofheWriteContract,\n useCoingeckoContractMarketChartRange,\n useCoingeckoUsdPrice,\n useTokenAllowance,\n useTokensWithPublicBalances,\n useTransactionReceiptsByHash,\n type ClaimableAmountByTokenAddress,\n type CoingeckoMarketChartPoint,\n type Erc20Pair,\n type UnshieldClaim,\n type UnshieldClaimsSummary,\n type UnshieldClaimsSummaryByTokenAddress,\n type UseCoingeckoContractMarketChartRangeInput,\n type UseCoingeckoContractMarketChartRangeOptions,\n type UseCoingeckoUsdPriceInput,\n type UseCoingeckoUsdPriceOptions,\n type UseCofheTokenTransactionsInput,\n type UseCofheTokenTransactionsResult,\n type UseTransactionReceiptsByHashInput,\n type AddCofheTransactionInput,\n} from '@/hooks/index';\n\nexport { useCofheEncryptAndWriteContract } from '@/hooks/useCofheEncryptAndWriteContract';\nexport { useCofheReadContractAndDecrypt } from '@/hooks/useCofheReadContractAndDecrypt';\n\n// Utils\nexport {\n FheTypesList,\n formatRelativeTime,\n getBlockExplorerAddressUrl,\n getBlockExplorerTokenUrl,\n getBlockExplorerTxUrl,\n getBlockExplorerUrl,\n isEthPair,\n isWrappedEthToken,\n truncateHash,\n} from './utils/index';\n\n// Stores\nexport { useCustomTokensStore } from './stores/customTokensStore';\n\nexport {\n actionToString,\n isCustomTransactionActionType,\n statusToString,\n transactionMatchesToken,\n TransactionActionType,\n TransactionStatus,\n useTransactionStore,\n type Transaction,\n type BuiltInTransactionActionType,\n type CustomTransactionActionType,\n type JsonValue,\n type NewTransaction,\n type TransactionActionString,\n type TransactionStatusString,\n type TransactionStore,\n} from './stores/transactionStore';\n\nexport { createCofheConfig } from './config';\nexport type { CofheReactLogger, CofheReactLoggerMethod } from './config';\n\n// Types\nexport type {\n CofheClientConfig,\n CofheContextValue,\n CofheProviderProps,\n TransactionRenderer,\n TransactionRendererProps,\n TransactionRenderers,\n} from './types/index';\n\nexport { createCofheClient } from '@cofhe/sdk/web';\n\nexport { useCofheCreatePermit } from '@/hooks/permits/useCofheCreatePermit';\nexport { useCofheNavigateToCreatePermit } from '@/hooks/permits/useCofheNavigateToCreatePermit';\nexport { useCofheAutoConnect } from '@/hooks/useCofheAutoConnect';\nexport { CofheFloatingButtonProvider, sortCofheStatuses } from './components/index';\nexport { COFHE_STATUS_IDS, CofheStatusActionIntents } from './components/CofheFloatingButton/types';\n\nexport type { CofheConfigWithReact as CofhesdkConfigWithReact } from './config';\n\nexport type { CofheStatus, CofheStatusActionIntent, CofheStatusId } from './components/CofheFloatingButton/types';\nexport type { ConfidentialToken } from './types/token';\n\nexport type { CofheDecryptMeta, CofheQueryMeta } from './meta';\n\nexport { useCofheDecryptionActivity } from '@/hooks/useCofheDecryptionActivity';\nexport type {\n DecryptionActivityRow,\n DecryptionActivityResult,\n DecryptionActivityCategory,\n UseCofheDecryptionActivityOptions,\n FetchStageState,\n DecryptStageState,\n PermitState,\n} from '@/hooks/useCofheDecryptionActivity';\n\nexport { useInternalQueryClient } from './providers/index';\n\n// Type bridges for cross-repo / multi-instance viem peer dependency scenarios\nexport {\n asCofhePublicClient,\n tryAsCofhePublicClient,\n asCofheWalletClient,\n tryAsCofheWalletClient,\n} from './utils/viemClientBridge';\nexport type {\n PublicClientLike as CofhePublicClientLike,\n WalletClientLike as CofheWalletClientLike,\n} from './utils/viemClientBridge';\n\n// Block-aware cache invalidation primitives.\n//\n// These are the building blocks behind the SDK's own \"wait until the serving RPC\n// node has the mined block before returning a read\" behaviour. They are exported\n// so consumers (e.g. a wagmi-based app) can build the same reliability into their\n// own reads + post-tx invalidation, sharing THIS module's single invalidation-\n// context store — so an invalidation registered here is honoured by both the\n// SDK's confidential reads and the consumer's own block-aware queries.\nexport {\n invalidateQueriesWithContext,\n withInvalidationContext,\n findMatchingInvalidationContext,\n consumeInvalidationContext,\n type InvalidationContextQueryFilters,\n type QueryFunctionWithInvalidationContext,\n} from './utils/invalidationContext';\nexport {\n maybeWaitUntilRpcAware,\n maybeWaitUntilRpcAwareAndReadContract,\n type WaitUntilRpcAwareAndReadContractOptions,\n type ReadContractResult,\n} from './utils/waitUntilRpcAwareAndReadContract';\nexport { resolveReceiptBlockHash } from './utils/resolveReceiptBlockHash';\nexport { useInvalidationContextStore, type InvalidationContextEntry } from './stores/invalidationContextStore';\n","import { useCallback, useEffect, useMemo, useReducer, useRef } from 'react';\nimport { useInternalQueryClient } from '@/providers';\nimport { useCofheAccount, useCofheChainId } from './useCofheConnection';\nimport { useCofheActivePermit } from './useCofhePermits';\nimport type { CofheQueryMeta } from '@/meta';\n\n// ============================================================================\n// Decryption activity — the lifecycle view of confidential reads + decryptions.\n// ============================================================================\n//\n// A confidential value is a two-stage pipeline, both stages living as react-query\n// queries on the SDK's internal QueryClient:\n// A) FETCH — read the ciphertext handle on-chain (`cofheReadContract`),\n// whose data carries the `ctHash`.\n// B) DECRYPT— decrypt that handle off-chain (`decryptCiphertext`, keyed\n// BY the ctHash).\n//\n// This hook observes the cache, correlates the two stages by ctHash, and returns\n// one row per confidential value with a recognizable contract/method/label (from\n// each query's `meta`) — surfacing states a plain error/loading flag can't:\n// • \"blocked\" — gated off by a missing/invalid permit (never runs, never errors)\n// • \"stale\" — fetched, but the decrypt is pending far too long / never lands\n// Consumers render the rows; no query-key parsing or side registries required.\n\nconst DEFAULT_STALE_MS = 25_000;\nconst nowSec = () => Math.floor(Date.now() / 1000);\n\n/** 'idle' = a read/decrypt query exists but is disabled/never-ran (fetchStatus 'idle'), vs 'pending' (in flight). */\nexport type FetchStageState = 'ok' | 'pending' | 'idle' | 'error' | 'empty';\nexport type DecryptStageState = 'ok' | 'pending' | 'idle' | 'stale' | 'error' | 'blocked' | 'absent';\nexport type PermitState = 'valid' | 'expired' | 'unsigned' | 'none';\n/** Coarse bucket for filtering: something wrong / decrypted / nothing conclusive. */\nexport type DecryptionActivityCategory = 'error' | 'success' | 'idle';\n\nexport interface DecryptionActivityRow {\n key: string;\n /** Canonical decimal ctHash, when known. */\n ctHash?: string;\n /** 0x…-shortened ctHash for display. */\n ctHashShort?: string;\n /** The originating query metadata (contract / method / label / consumer fields). */\n meta?: CofheQueryMeta;\n /** Convenience shortcuts pulled from meta. */\n chainId?: number;\n address?: string;\n functionName?: string;\n label?: string;\n fetch: FetchStageState;\n decrypt: DecryptStageState;\n category: DecryptionActivityCategory;\n /** Why the row is blocked, e.g. \"permit none\". */\n blockedReason?: string;\n /** How long the decrypt has been pending, ms (drives \"stale\"). */\n pendingMs?: number;\n updatedAt: number;\n /** Whether re-running is possible (false for gated/idle reads with nothing enabled). */\n canRetry: boolean;\n /** Re-run this value's read and/or decrypt. */\n retry: () => void;\n}\n\nexport interface DecryptionActivityResult {\n rows: DecryptionActivityRow[];\n counts: { total: number; ok: number; pending: number; stale: number; blocked: number; error: number };\n permit: { state: PermitState; expiresInSec?: number };\n /** Wipe the whole SDK query cache; mounted reads/decryptions refetch from scratch. */\n clearCache: () => void;\n}\n\nexport interface UseCofheDecryptionActivityOptions {\n /** How long a decrypt may stay pending before it's reported \"stale\" (default 25s). */\n staleMs?: number;\n}\n\n// Minimal structural view of a cached query — enough to classify without depending\n// on react-query's concrete generic types.\ninterface QueryLike {\n queryKey: unknown;\n queryHash: string;\n meta?: CofheQueryMeta;\n state: { status: 'pending' | 'error' | 'success'; fetchStatus?: string; data?: unknown; dataUpdatedAt?: number };\n}\ninterface CacheLike {\n getAll: () => QueryLike[];\n subscribe: (cb: () => void) => () => void;\n}\ninterface ClientLike {\n getQueryCache: () => CacheLike;\n refetchQueries: (filters: { queryKey: unknown; exact?: boolean }) => Promise<unknown>;\n clear: () => void;\n}\n\nfunction normalizeCt(x: unknown): string | undefined {\n if (x === null || x === undefined) return undefined;\n try {\n return BigInt(x as string | number | bigint).toString();\n } catch {\n const s = String(x);\n return s && s !== '[object Object]' ? s : undefined;\n }\n}\n\n// A ctHash of 0 is not a real handle: reads return it for an absent/encrypted-zero\n// value and the decrypt is gated on `ctHash > 0n`, so treat it as \"no handle\".\nfunction isZeroCt(ct: string | undefined): boolean {\n if (!ct) return false;\n try {\n return BigInt(ct) === 0n;\n } catch {\n return false;\n }\n}\n\nfunction shortCt(decimal: string): string {\n try {\n const hex = BigInt(decimal).toString(16);\n return hex.length > 10 ? `0x${hex.slice(0, 6)}…${hex.slice(-4)}` : `0x${hex}`;\n } catch {\n return decimal;\n }\n}\n\nfunction extractCtHash(data: unknown): string | undefined {\n if (data === null || data === undefined) return undefined;\n if (typeof data === 'bigint') return normalizeCt(data);\n if (typeof data === 'object' && data !== null && 'ctHash' in (data as Record<string, unknown>)) {\n return normalizeCt((data as { ctHash: unknown }).ctHash);\n }\n return undefined;\n}\n\n// The read key bakes the transient activePermitHash + enabled flags into its tail,\n// so the SAME value gets a fresh cache entry each time a permit appears/rotates.\n// Its stable identity is [prefix, chainId, address, fn, args] (indices 0-4).\nfunction stableReadKey(k: unknown[]): string {\n try {\n return JSON.stringify(k.slice(0, 5));\n } catch {\n return String(k[1]) + '|' + String(k[2]) + '|' + String(k[3]);\n }\n}\n\n// Progress of a read: ran (success/error) > in flight > idle/never-ran.\nfunction readProgress(q: QueryLike): number {\n if (q.state.status === 'success' || q.state.status === 'error') return 2;\n if (q.state.fetchStatus === 'fetching') return 1;\n return 0;\n}\nfunction isFresherRead(candidate: QueryLike, current: QueryLike): boolean {\n const pc = readProgress(candidate);\n const pk = readProgress(current);\n if (pc !== pk) return pc > pk;\n return (candidate.state.dataUpdatedAt ?? 0) > (current.state.dataUpdatedAt ?? 0);\n}\n\nfunction categoryFor(fetch: FetchStageState, decrypt: DecryptStageState): DecryptionActivityCategory {\n if (fetch === 'error' || decrypt === 'error' || decrypt === 'blocked' || decrypt === 'stale') return 'error';\n if (decrypt === 'ok') return 'success';\n return 'idle';\n}\n\n/**\n * Observe the ctHash-fetch → decrypt pipeline on the SDK's QueryClient, correlated\n * by ctHash and cross-referenced against the active permit. Must be used inside the\n * Cofhe provider.\n */\nexport function useCofheDecryptionActivity(options?: UseCofheDecryptionActivityOptions): DecryptionActivityResult {\n const staleMs = options?.staleMs ?? DEFAULT_STALE_MS;\n const queryClient = useInternalQueryClient() as unknown as ClientLike;\n const account = useCofheAccount();\n const chainId = useCofheChainId();\n const active = useCofheActivePermit();\n const permitObj = active?.permit;\n\n // Track when each decrypt first went pending, so \"stale\" is real elapsed time\n // (react-query doesn't expose a fetch-start timestamp for a never-resolved query).\n const pendingSinceRef = useRef(new Map<string, number>());\n\n // Re-render on cache changes AND on a slow tick (staleness is time-based, not\n // event-driven — a query sitting pending emits no cache events).\n //\n // Coalesce cache events to one bump per animation frame. `cache.subscribe` fires\n // synchronously on EVERY cache event (including observer option/result updates),\n // and a consumer re-render can itself emit fresh cache events — an unbounded\n // bump→render→event→bump storm that pins the main thread and starves unrelated\n // updates (e.g. a route change never commits). One bump per frame keeps the view\n // live while capping re-renders so the loop can't run away.\n const [version, bump] = useReducer((n: number) => n + 1, 0);\n useEffect(() => {\n const cache = queryClient.getQueryCache();\n let scheduled = false;\n const schedule = () => {\n if (scheduled) return;\n scheduled = true;\n const run = () => {\n scheduled = false;\n bump();\n };\n if (typeof requestAnimationFrame === 'function') requestAnimationFrame(run);\n else setTimeout(run, 16);\n };\n const unsub = cache.subscribe(schedule);\n const tick = setInterval(bump, 5_000);\n return () => {\n unsub();\n clearInterval(tick);\n };\n }, [queryClient]);\n\n const clearCache = useCallback(() => queryClient.clear(), [queryClient]);\n\n const data = useMemo(() => {\n const cache = queryClient.getQueryCache();\n const queries = cache.getAll();\n const now = Date.now();\n\n const refetch = (key: unknown) => void queryClient.refetchQueries({ queryKey: key, exact: true });\n\n const permitState: PermitState = !permitObj\n ? 'none'\n : !permitObj.issuerSignature || permitObj.issuerSignature === '0x'\n ? 'unsigned'\n : permitObj.expiration <= nowSec()\n ? 'expired'\n : 'valid';\n const permitValid = permitState === 'valid';\n\n // Index decrypt queries by ctHash (source contract + label come from meta).\n const decryptByCt = new Map<\n string,\n { state: 'ok' | 'pending' | 'idle' | 'error'; pendingMs?: number; key?: unknown; meta?: CofheQueryMeta }\n >();\n const seenPending = new Set<string>();\n for (const q of queries) {\n const k = q.queryKey;\n if (!Array.isArray(k) || k[0] !== 'decryptCiphertext') continue;\n const ct = normalizeCt(k[1]);\n if (!ct || isZeroCt(ct)) continue;\n const base = { key: q.queryKey, meta: q.meta };\n if (q.state.status === 'success') {\n decryptByCt.set(ct, { state: 'ok', ...base });\n pendingSinceRef.current.delete(ct);\n } else if (q.state.status === 'error') {\n decryptByCt.set(ct, { state: 'error', ...base });\n pendingSinceRef.current.delete(ct);\n } else if (q.state.fetchStatus === 'fetching') {\n seenPending.add(ct);\n let since = pendingSinceRef.current.get(ct);\n if (since === undefined) {\n since = now;\n pendingSinceRef.current.set(ct, since);\n }\n decryptByCt.set(ct, { state: 'pending', pendingMs: now - since, ...base });\n } else {\n // status 'pending' but fetchStatus 'idle' → disabled / never ran.\n pendingSinceRef.current.delete(ct);\n decryptByCt.set(ct, { state: 'idle', ...base });\n }\n }\n\n const rows: DecryptionActivityRow[] = [];\n const usedCt = new Set<string>();\n\n // Collapse per-permit/enabled key rotations to one entry per value.\n const readByValue = new Map<string, QueryLike>();\n for (const q of queries) {\n const k = q.queryKey;\n if (!Array.isArray(k) || k[0] !== 'cofheReadContract') continue;\n const id = stableReadKey(k);\n const existing = readByValue.get(id);\n if (!existing || isFresherRead(q, existing)) readByValue.set(id, q);\n }\n\n const pushRow = (\n row: Omit<DecryptionActivityRow, 'category' | 'canRetry' | 'retry'> & {\n fetchKey?: unknown;\n decryptKey?: unknown;\n }\n ) => {\n const { fetchKey, decryptKey, ...rest } = row;\n const canRetry = rest.fetch !== 'idle' && (fetchKey !== undefined || decryptKey !== undefined);\n rows.push({\n ...rest,\n category: categoryFor(rest.fetch, rest.decrypt),\n canRetry,\n retry: () => {\n if (fetchKey !== undefined) refetch(fetchKey);\n if (decryptKey !== undefined) refetch(decryptKey);\n },\n });\n };\n\n // One row per confidential value; attach its decrypt stage by ctHash.\n for (const q of readByValue.values()) {\n const m = q.meta;\n const ctRaw = q.state.status === 'success' ? extractCtHash(q.state.data) : undefined;\n const ct = ctRaw && !isZeroCt(ctRaw) ? ctRaw : undefined;\n const fetchInFlight = q.state.fetchStatus === 'fetching';\n const fetchState: FetchStageState =\n q.state.status === 'error'\n ? 'error'\n : q.state.status === 'pending'\n ? fetchInFlight\n ? 'pending'\n : 'idle'\n : ct\n ? 'ok'\n : 'empty';\n\n let decrypt: DecryptStageState = 'absent';\n let blockedReason: string | undefined;\n let pendingMs: number | undefined;\n let decryptKey: unknown;\n let decryptMeta: CofheQueryMeta | undefined;\n if (ct) {\n usedCt.add(ct);\n const d = decryptByCt.get(ct);\n decryptKey = d?.key;\n decryptMeta = d?.meta;\n if (d?.state === 'ok') decrypt = 'ok';\n else if (d?.state === 'error') decrypt = 'error';\n else if (d?.state === 'idle') decrypt = 'idle';\n else if (d?.state === 'pending') {\n pendingMs = d.pendingMs;\n decrypt = (d.pendingMs ?? 0) > staleMs ? 'stale' : 'pending';\n } else {\n decrypt = permitValid ? 'absent' : 'blocked';\n if (!permitValid) blockedReason = `permit ${permitState}`;\n }\n } else if (fetchState === 'idle' && !permitValid) {\n // The read is gated off (no valid permit) — blocked before any ctHash.\n decrypt = 'blocked';\n blockedReason = `permit ${permitState}`;\n }\n\n const meta = m ?? decryptMeta;\n pushRow({\n key: q.queryHash,\n ctHash: ct,\n ctHashShort: ct ? shortCt(ct) : undefined,\n meta,\n chainId: meta?.chainId,\n address: meta?.address,\n functionName: meta?.functionName,\n label: meta?.consumer?.label,\n fetch: fetchState,\n decrypt,\n blockedReason,\n pendingMs,\n updatedAt: now,\n fetchKey: q.queryKey,\n decryptKey,\n });\n }\n\n // Orphan decrypts (a ctHash being decrypted with no fetch query in cache).\n for (const [ct, d] of decryptByCt) {\n if (usedCt.has(ct)) continue;\n const decrypt: DecryptStageState =\n d.state === 'ok'\n ? 'ok'\n : d.state === 'error'\n ? 'error'\n : d.state === 'idle'\n ? 'idle'\n : (d.pendingMs ?? 0) > staleMs\n ? 'stale'\n : 'pending';\n pushRow({\n key: `decrypt:${ct}`,\n ctHash: ct,\n ctHashShort: shortCt(ct),\n meta: d.meta,\n chainId: d.meta?.chainId,\n address: d.meta?.address,\n functionName: d.meta?.functionName,\n label: d.meta?.consumer?.label,\n fetch: 'ok',\n decrypt,\n pendingMs: d.pendingMs,\n updatedAt: now,\n decryptKey: d.key,\n });\n }\n\n // Drop ctHashes we no longer see, so the pending-since map can't grow unbounded.\n for (const ct of pendingSinceRef.current.keys()) {\n if (!seenPending.has(ct)) pendingSinceRef.current.delete(ct);\n }\n\n const counts = {\n total: rows.length,\n ok: rows.filter((r) => r.decrypt === 'ok').length,\n pending: rows.filter((r) => r.decrypt === 'pending').length,\n stale: rows.filter((r) => r.decrypt === 'stale').length,\n blocked: rows.filter((r) => r.decrypt === 'blocked').length,\n error: rows.filter((r) => r.decrypt === 'error' || r.fetch === 'error').length,\n };\n\n // Most actionable first: blocked/stale/error, then pending, then done.\n const rank: Record<DecryptStageState, number> = {\n blocked: 0,\n stale: 1,\n error: 2,\n pending: 3,\n idle: 4,\n absent: 5,\n ok: 6,\n };\n rows.sort((a, b) => rank[a.decrypt] - rank[b.decrypt]);\n\n const expiresInSec = permitObj ? permitObj.expiration - nowSec() : undefined;\n return { rows, permit: { state: permitState, expiresInSec }, counts };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [queryClient, account, chainId, permitObj, staleMs, version]);\n\n return { ...data, clearCache };\n}\n"]}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/hooks/useCofheDecryptionActivity.ts"],"sourcesContent":["// Providers\nexport { CofheProvider, useCofheContext } from './providers/index';\n\n// Hooks\nexport {\n ETH_ADDRESS_LOWERCASE,\n getCofheTokenClaimUnshieldedCallArgs,\n getCofheTokenShieldCallArgs,\n getCofheTokenUnshieldCallArgs,\n useCofheActivePermit,\n useCofheAllPermits,\n useCofheClient,\n useCofheConnection,\n useCofheEnabled,\n useCofheEncrypt,\n useCofhePublicClient,\n useCofheRemovePermit,\n useCofheSelectPermit,\n useCofheSimulateWriteContract,\n useCofheStatuses,\n useCofheTokenClaimable,\n useCofheTokenClaims,\n useCofheTokenApprove,\n useCofheTokenClaimUnshielded,\n useCofheTokenDecryptedBalance,\n useCofheTokenPublicBalance,\n useCofheTokenLists,\n useCofheToken,\n useCofheTokens,\n useCofheTokensClaimable,\n useCofheTokenShield,\n useCofheTokensWithExistingEncryptedBalances,\n useCofheTokenTransactions,\n useCofheTokenTransfer,\n useResolvedCofheToken,\n useCofheTransactions,\n addCofheTransaction,\n useCofheTokenUnshield,\n useCofheWalletClient,\n useCofheWriteContract,\n useCoingeckoContractMarketChartRange,\n useCoingeckoUsdPrice,\n useTokenAllowance,\n useTokensWithPublicBalances,\n useTransactionReceiptsByHash,\n type ClaimableAmountByTokenAddress,\n type CoingeckoMarketChartPoint,\n type Erc20Pair,\n type UnshieldClaim,\n type UnshieldClaimsSummary,\n type UnshieldClaimsSummaryByTokenAddress,\n type UseCoingeckoContractMarketChartRangeInput,\n type UseCoingeckoContractMarketChartRangeOptions,\n type UseCoingeckoUsdPriceInput,\n type UseCoingeckoUsdPriceOptions,\n type UseCofheTokenTransactionsInput,\n type UseCofheTokenTransactionsResult,\n type UseTransactionReceiptsByHashInput,\n type AddCofheTransactionInput,\n} from '@/hooks/index';\n\nexport { useCofheEncryptAndWriteContract } from '@/hooks/useCofheEncryptAndWriteContract';\nexport { useCofheReadContractAndDecrypt } from '@/hooks/useCofheReadContractAndDecrypt';\n\n// Utils\nexport {\n FheTypesList,\n formatRelativeTime,\n getBlockExplorerAddressUrl,\n getBlockExplorerTokenUrl,\n getBlockExplorerTxUrl,\n getBlockExplorerUrl,\n isEthPair,\n isWrappedEthToken,\n truncateHash,\n} from './utils/index';\n\n// Stores\nexport { useCustomTokensStore } from './stores/customTokensStore';\n\nexport {\n actionToString,\n isCustomTransactionActionType,\n statusToString,\n transactionMatchesToken,\n TransactionActionType,\n TransactionStatus,\n useTransactionStore,\n type Transaction,\n type BuiltInTransactionActionType,\n type CustomTransactionActionType,\n type JsonValue,\n type NewTransaction,\n type TransactionActionString,\n type TransactionStatusString,\n type TransactionStore,\n} from './stores/transactionStore';\n\nexport { createCofheConfig } from './config';\nexport type { CofheReactLogger, CofheReactLoggerMethod } from './config';\n\n// Types\nexport type {\n CofheClientConfig,\n CofheContextValue,\n CofheProviderProps,\n TransactionRenderer,\n TransactionRendererProps,\n TransactionRenderers,\n} from './types/index';\n\nexport { createCofheClient } from '@cofhe/sdk/web';\n\nexport { useCofheCreatePermit } from '@/hooks/permits/useCofheCreatePermit';\nexport { useCofheNavigateToCreatePermit } from '@/hooks/permits/useCofheNavigateToCreatePermit';\nexport { useCofheAutoConnect } from '@/hooks/useCofheAutoConnect';\nexport { CofheFloatingButtonProvider, sortCofheStatuses } from './components/index';\nexport { COFHE_STATUS_IDS, CofheStatusActionIntents } from './components/CofheFloatingButton/types';\n\nexport type { CofheConfigWithReact as CofhesdkConfigWithReact } from './config';\n\nexport type { CofheStatus, CofheStatusActionIntent, CofheStatusId } from './components/CofheFloatingButton/types';\nexport type { ConfidentialToken } from './types/token';\n\nexport type { CofheDecryptMeta, CofheQueryMeta } from './meta';\n\nexport { useCofheDecryptionActivity } from '@/hooks/useCofheDecryptionActivity';\nexport type {\n DecryptionActivityRow,\n DecryptionActivityResult,\n DecryptionActivityCategory,\n UseCofheDecryptionActivityOptions,\n FetchStageState,\n DecryptStageState,\n PermitState,\n} from '@/hooks/useCofheDecryptionActivity';\n\nexport { useInternalQueryClient } from './providers/index';\n\n// Type bridges for cross-repo / multi-instance viem peer dependency scenarios\nexport { asCofhePublicClient, tryAsCofhePublicClient, asCofheWalletClient, tryAsCofheWalletClient } from './utils/viemClientBridge';\nexport type {\n PublicClientLike as CofhePublicClientLike,\n WalletClientLike as CofheWalletClientLike,\n} from './utils/viemClientBridge';\n\n// Block-aware cache invalidation primitives.\n//\n// These are the building blocks behind the SDK's own \"wait until the serving RPC\n// node has the mined block before returning a read\" behaviour. They are exported\n// so consumers (e.g. a wagmi-based app) can build the same reliability into their\n// own reads + post-tx invalidation, sharing THIS module's single invalidation-\n// context store — so an invalidation registered here is honoured by both the\n// SDK's confidential reads and the consumer's own block-aware queries.\nexport {\n invalidateQueriesWithContext,\n withInvalidationContext,\n findMatchingInvalidationContext,\n consumeInvalidationContext,\n type InvalidationContextQueryFilters,\n type QueryFunctionWithInvalidationContext,\n} from './utils/invalidationContext';\nexport {\n maybeWaitUntilRpcAware,\n maybeWaitUntilRpcAwareAndReadContract,\n type WaitUntilRpcAwareAndReadContractOptions,\n type ReadContractResult,\n} from './utils/waitUntilRpcAwareAndReadContract';\nexport { resolveReceiptBlockHash } from './utils/resolveReceiptBlockHash';\nexport { useInvalidationContextStore, type InvalidationContextEntry } from './stores/invalidationContextStore';\n","import { useCallback, useEffect, useMemo, useReducer, useRef } from 'react';\nimport { useInternalQueryClient } from '@/providers';\nimport { useCofheAccount, useCofheChainId } from './useCofheConnection';\nimport { useCofheActivePermit } from './useCofhePermits';\nimport type { CofheQueryMeta } from '@/meta';\n\n// ============================================================================\n// Decryption activity — the lifecycle view of confidential reads + decryptions.\n// ============================================================================\n//\n// A confidential value is a two-stage pipeline, both stages living as react-query\n// queries on the SDK's internal QueryClient:\n// A) FETCH — read the ciphertext handle on-chain (`cofheReadContract`),\n// whose data carries the `ctHash`.\n// B) DECRYPT— decrypt that handle off-chain (`decryptCiphertext`, keyed\n// BY the ctHash).\n//\n// This hook observes the cache, correlates the two stages by ctHash, and returns\n// one row per confidential value with a recognizable contract/method/label (from\n// each query's `meta`) — surfacing states a plain error/loading flag can't:\n// • \"blocked\" — gated off by a missing/invalid permit (never runs, never errors)\n// • \"stale\" — fetched, but the decrypt is pending far too long / never lands\n// Consumers render the rows; no query-key parsing or side registries required.\n\nconst DEFAULT_STALE_MS = 25_000;\nconst nowSec = () => Math.floor(Date.now() / 1000);\n\n/** 'idle' = a read/decrypt query exists but is disabled/never-ran (fetchStatus 'idle'), vs 'pending' (in flight). */\nexport type FetchStageState = 'ok' | 'pending' | 'idle' | 'error' | 'empty';\nexport type DecryptStageState = 'ok' | 'pending' | 'idle' | 'stale' | 'error' | 'blocked' | 'absent';\nexport type PermitState = 'valid' | 'expired' | 'unsigned' | 'none';\n/** Coarse bucket for filtering: something wrong / decrypted / nothing conclusive. */\nexport type DecryptionActivityCategory = 'error' | 'success' | 'idle';\n\nexport interface DecryptionActivityRow {\n key: string;\n /** Canonical decimal ctHash, when known. */\n ctHash?: string;\n /** 0x…-shortened ctHash for display. */\n ctHashShort?: string;\n /** The originating query metadata (contract / method / label / consumer fields). */\n meta?: CofheQueryMeta;\n /** Convenience shortcuts pulled from meta. */\n chainId?: number;\n address?: string;\n functionName?: string;\n label?: string;\n fetch: FetchStageState;\n decrypt: DecryptStageState;\n category: DecryptionActivityCategory;\n /** Why the row is blocked, e.g. \"permit none\". */\n blockedReason?: string;\n /** How long the decrypt has been pending, ms (drives \"stale\"). */\n pendingMs?: number;\n updatedAt: number;\n /** Whether re-running is possible (false for gated/idle reads with nothing enabled). */\n canRetry: boolean;\n /** Re-run this value's read and/or decrypt. */\n retry: () => void;\n}\n\nexport interface DecryptionActivityResult {\n rows: DecryptionActivityRow[];\n counts: { total: number; ok: number; pending: number; stale: number; blocked: number; error: number };\n permit: { state: PermitState; expiresInSec?: number };\n /** Wipe the whole SDK query cache; mounted reads/decryptions refetch from scratch. */\n clearCache: () => void;\n}\n\nexport interface UseCofheDecryptionActivityOptions {\n /** How long a decrypt may stay pending before it's reported \"stale\" (default 25s). */\n staleMs?: number;\n}\n\n// Minimal structural view of a cached query — enough to classify without depending\n// on react-query's concrete generic types.\ninterface QueryLike {\n queryKey: unknown;\n queryHash: string;\n meta?: CofheQueryMeta;\n state: { status: 'pending' | 'error' | 'success'; fetchStatus?: string; data?: unknown; dataUpdatedAt?: number };\n}\ninterface CacheLike {\n getAll: () => QueryLike[];\n subscribe: (cb: () => void) => () => void;\n}\ninterface ClientLike {\n getQueryCache: () => CacheLike;\n refetchQueries: (filters: { queryKey: unknown; exact?: boolean }) => Promise<unknown>;\n clear: () => void;\n}\n\nfunction normalizeCt(x: unknown): string | undefined {\n if (x === null || x === undefined) return undefined;\n try {\n return BigInt(x as string | number | bigint).toString();\n } catch {\n const s = String(x);\n return s && s !== '[object Object]' ? s : undefined;\n }\n}\n\n// A ctHash of 0 is not a real handle: reads return it for an absent/encrypted-zero\n// value and the decrypt is gated on `ctHash > 0n`, so treat it as \"no handle\".\nfunction isZeroCt(ct: string | undefined): boolean {\n if (!ct) return false;\n try {\n return BigInt(ct) === 0n;\n } catch {\n return false;\n }\n}\n\nfunction shortCt(decimal: string): string {\n try {\n const hex = BigInt(decimal).toString(16);\n return hex.length > 10 ? `0x${hex.slice(0, 6)}…${hex.slice(-4)}` : `0x${hex}`;\n } catch {\n return decimal;\n }\n}\n\nfunction extractCtHash(data: unknown): string | undefined {\n if (data === null || data === undefined) return undefined;\n if (typeof data === 'bigint') return normalizeCt(data);\n if (typeof data === 'object' && data !== null && 'ctHash' in (data as Record<string, unknown>)) {\n return normalizeCt((data as { ctHash: unknown }).ctHash);\n }\n return undefined;\n}\n\n// The read key bakes the transient activePermitHash + enabled flags into its tail,\n// so the SAME value gets a fresh cache entry each time a permit appears/rotates.\n// Its stable identity is [prefix, chainId, address, fn, args] (indices 0-4).\nfunction stableReadKey(k: unknown[]): string {\n try {\n return JSON.stringify(k.slice(0, 5));\n } catch {\n return String(k[1]) + '|' + String(k[2]) + '|' + String(k[3]);\n }\n}\n\n// Progress of a read: ran (success/error) > in flight > idle/never-ran.\nfunction readProgress(q: QueryLike): number {\n if (q.state.status === 'success' || q.state.status === 'error') return 2;\n if (q.state.fetchStatus === 'fetching') return 1;\n return 0;\n}\nfunction isFresherRead(candidate: QueryLike, current: QueryLike): boolean {\n const pc = readProgress(candidate);\n const pk = readProgress(current);\n if (pc !== pk) return pc > pk;\n return (candidate.state.dataUpdatedAt ?? 0) > (current.state.dataUpdatedAt ?? 0);\n}\n\nfunction categoryFor(fetch: FetchStageState, decrypt: DecryptStageState): DecryptionActivityCategory {\n if (fetch === 'error' || decrypt === 'error' || decrypt === 'blocked' || decrypt === 'stale') return 'error';\n if (decrypt === 'ok') return 'success';\n return 'idle';\n}\n\n/**\n * Observe the ctHash-fetch → decrypt pipeline on the SDK's QueryClient, correlated\n * by ctHash and cross-referenced against the active permit. Must be used inside the\n * Cofhe provider.\n */\nexport function useCofheDecryptionActivity(options?: UseCofheDecryptionActivityOptions): DecryptionActivityResult {\n const staleMs = options?.staleMs ?? DEFAULT_STALE_MS;\n const queryClient = useInternalQueryClient() as unknown as ClientLike;\n const account = useCofheAccount();\n const chainId = useCofheChainId();\n const active = useCofheActivePermit();\n const permitObj = active?.permit;\n\n // Track when each decrypt first went pending, so \"stale\" is real elapsed time\n // (react-query doesn't expose a fetch-start timestamp for a never-resolved query).\n const pendingSinceRef = useRef(new Map<string, number>());\n\n // Re-render on cache changes AND on a slow tick (staleness is time-based, not\n // event-driven — a query sitting pending emits no cache events).\n //\n // Coalesce cache events to one bump per animation frame. `cache.subscribe` fires\n // synchronously on EVERY cache event (including observer option/result updates),\n // and a consumer re-render can itself emit fresh cache events — an unbounded\n // bump→render→event→bump storm that pins the main thread and starves unrelated\n // updates (e.g. a route change never commits). One bump per frame keeps the view\n // live while capping re-renders so the loop can't run away.\n const [version, bump] = useReducer((n: number) => n + 1, 0);\n useEffect(() => {\n const cache = queryClient.getQueryCache();\n let scheduled = false;\n const schedule = () => {\n if (scheduled) return;\n scheduled = true;\n const run = () => {\n scheduled = false;\n bump();\n };\n if (typeof requestAnimationFrame === 'function') requestAnimationFrame(run);\n else setTimeout(run, 16);\n };\n const unsub = cache.subscribe(schedule);\n const tick = setInterval(bump, 5_000);\n return () => {\n unsub();\n clearInterval(tick);\n };\n }, [queryClient]);\n\n const clearCache = useCallback(() => queryClient.clear(), [queryClient]);\n\n const data = useMemo(() => {\n const cache = queryClient.getQueryCache();\n const queries = cache.getAll();\n const now = Date.now();\n\n const refetch = (key: unknown) => void queryClient.refetchQueries({ queryKey: key, exact: true });\n\n const permitState: PermitState = !permitObj\n ? 'none'\n : !permitObj.issuerSignature || permitObj.issuerSignature === '0x'\n ? 'unsigned'\n : permitObj.expiration <= nowSec()\n ? 'expired'\n : 'valid';\n const permitValid = permitState === 'valid';\n\n // Index decrypt queries by ctHash (source contract + label come from meta).\n const decryptByCt = new Map<\n string,\n { state: 'ok' | 'pending' | 'idle' | 'error'; pendingMs?: number; key?: unknown; meta?: CofheQueryMeta }\n >();\n const seenPending = new Set<string>();\n for (const q of queries) {\n const k = q.queryKey;\n if (!Array.isArray(k) || k[0] !== 'decryptCiphertext') continue;\n const ct = normalizeCt(k[1]);\n if (!ct || isZeroCt(ct)) continue;\n const base = { key: q.queryKey, meta: q.meta };\n if (q.state.status === 'success') {\n decryptByCt.set(ct, { state: 'ok', ...base });\n pendingSinceRef.current.delete(ct);\n } else if (q.state.status === 'error') {\n decryptByCt.set(ct, { state: 'error', ...base });\n pendingSinceRef.current.delete(ct);\n } else if (q.state.fetchStatus === 'fetching') {\n seenPending.add(ct);\n let since = pendingSinceRef.current.get(ct);\n if (since === undefined) {\n since = now;\n pendingSinceRef.current.set(ct, since);\n }\n decryptByCt.set(ct, { state: 'pending', pendingMs: now - since, ...base });\n } else {\n // status 'pending' but fetchStatus 'idle' → disabled / never ran.\n pendingSinceRef.current.delete(ct);\n decryptByCt.set(ct, { state: 'idle', ...base });\n }\n }\n\n const rows: DecryptionActivityRow[] = [];\n const usedCt = new Set<string>();\n\n // Collapse per-permit/enabled key rotations to one entry per value.\n const readByValue = new Map<string, QueryLike>();\n for (const q of queries) {\n const k = q.queryKey;\n if (!Array.isArray(k) || k[0] !== 'cofheReadContract') continue;\n const id = stableReadKey(k);\n const existing = readByValue.get(id);\n if (!existing || isFresherRead(q, existing)) readByValue.set(id, q);\n }\n\n const pushRow = (\n row: Omit<DecryptionActivityRow, 'category' | 'canRetry' | 'retry'> & {\n fetchKey?: unknown;\n decryptKey?: unknown;\n }\n ) => {\n const { fetchKey, decryptKey, ...rest } = row;\n const canRetry = rest.fetch !== 'idle' && (fetchKey !== undefined || decryptKey !== undefined);\n rows.push({\n ...rest,\n category: categoryFor(rest.fetch, rest.decrypt),\n canRetry,\n retry: () => {\n if (fetchKey !== undefined) refetch(fetchKey);\n if (decryptKey !== undefined) refetch(decryptKey);\n },\n });\n };\n\n // One row per confidential value; attach its decrypt stage by ctHash.\n for (const q of readByValue.values()) {\n const m = q.meta;\n const ctRaw = q.state.status === 'success' ? extractCtHash(q.state.data) : undefined;\n const ct = ctRaw && !isZeroCt(ctRaw) ? ctRaw : undefined;\n const fetchInFlight = q.state.fetchStatus === 'fetching';\n const fetchState: FetchStageState =\n q.state.status === 'error'\n ? 'error'\n : q.state.status === 'pending'\n ? fetchInFlight\n ? 'pending'\n : 'idle'\n : ct\n ? 'ok'\n : 'empty';\n\n let decrypt: DecryptStageState = 'absent';\n let blockedReason: string | undefined;\n let pendingMs: number | undefined;\n let decryptKey: unknown;\n let decryptMeta: CofheQueryMeta | undefined;\n if (ct) {\n usedCt.add(ct);\n const d = decryptByCt.get(ct);\n decryptKey = d?.key;\n decryptMeta = d?.meta;\n if (d?.state === 'ok') decrypt = 'ok';\n else if (d?.state === 'error') decrypt = 'error';\n else if (d?.state === 'idle') decrypt = 'idle';\n else if (d?.state === 'pending') {\n pendingMs = d.pendingMs;\n decrypt = (d.pendingMs ?? 0) > staleMs ? 'stale' : 'pending';\n } else {\n decrypt = permitValid ? 'absent' : 'blocked';\n if (!permitValid) blockedReason = `permit ${permitState}`;\n }\n } else if (fetchState === 'idle' && !permitValid) {\n // The read is gated off (no valid permit) — blocked before any ctHash.\n decrypt = 'blocked';\n blockedReason = `permit ${permitState}`;\n }\n\n const meta = m ?? decryptMeta;\n pushRow({\n key: q.queryHash,\n ctHash: ct,\n ctHashShort: ct ? shortCt(ct) : undefined,\n meta,\n chainId: meta?.chainId,\n address: meta?.address,\n functionName: meta?.functionName,\n label: meta?.consumer?.label,\n fetch: fetchState,\n decrypt,\n blockedReason,\n pendingMs,\n updatedAt: now,\n fetchKey: q.queryKey,\n decryptKey,\n });\n }\n\n // Orphan decrypts (a ctHash being decrypted with no fetch query in cache).\n for (const [ct, d] of decryptByCt) {\n if (usedCt.has(ct)) continue;\n const decrypt: DecryptStageState =\n d.state === 'ok'\n ? 'ok'\n : d.state === 'error'\n ? 'error'\n : d.state === 'idle'\n ? 'idle'\n : (d.pendingMs ?? 0) > staleMs\n ? 'stale'\n : 'pending';\n pushRow({\n key: `decrypt:${ct}`,\n ctHash: ct,\n ctHashShort: shortCt(ct),\n meta: d.meta,\n chainId: d.meta?.chainId,\n address: d.meta?.address,\n functionName: d.meta?.functionName,\n label: d.meta?.consumer?.label,\n fetch: 'ok',\n decrypt,\n pendingMs: d.pendingMs,\n updatedAt: now,\n decryptKey: d.key,\n });\n }\n\n // Drop ctHashes we no longer see, so the pending-since map can't grow unbounded.\n for (const ct of pendingSinceRef.current.keys()) {\n if (!seenPending.has(ct)) pendingSinceRef.current.delete(ct);\n }\n\n const counts = {\n total: rows.length,\n ok: rows.filter((r) => r.decrypt === 'ok').length,\n pending: rows.filter((r) => r.decrypt === 'pending').length,\n stale: rows.filter((r) => r.decrypt === 'stale').length,\n blocked: rows.filter((r) => r.decrypt === 'blocked').length,\n error: rows.filter((r) => r.decrypt === 'error' || r.fetch === 'error').length,\n };\n\n // Most actionable first: blocked/stale/error, then pending, then done.\n const rank: Record<DecryptStageState, number> = {\n blocked: 0,\n stale: 1,\n error: 2,\n pending: 3,\n idle: 4,\n absent: 5,\n ok: 6,\n };\n rows.sort((a, b) => rank[a.decrypt] - rank[b.decrypt]);\n\n const expiresInSec = permitObj ? permitObj.expiration - nowSec() : undefined;\n return { rows, permit: { state: permitState, expiresInSec }, counts };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [queryClient, account, chainId, permitObj, staleMs, version]);\n\n return { ...data, clearCache };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/hooks/useCofheDecryptionActivity.ts"],"sourcesContent":["// Providers\nexport { CofheProvider, useCofheContext } from './providers/index';\n\n// Hooks\nexport {\n ETH_ADDRESS_LOWERCASE,\n getCofheTokenClaimUnshieldedCallArgs,\n getCofheTokenShieldCallArgs,\n getCofheTokenUnshieldCallArgs,\n useCofheActivePermit,\n useCofheAllPermits,\n useCofheClient,\n useCofheConnection,\n useCofheEnabled,\n useCofheEncrypt,\n useCofhePublicClient,\n useCofheRemovePermit,\n useCofheSelectPermit,\n useCofheSimulateWriteContract,\n useCofheStatuses,\n useCofheTokenClaimable,\n useCofheTokenClaims,\n useCofheTokenApprove,\n useCofheTokenClaimUnshielded,\n useCofheTokenDecryptedBalance,\n useCofheTokenPublicBalance,\n useCofheTokenLists,\n useCofheToken,\n useCofheTokens,\n useCofheTokensClaimable,\n useCofheTokenShield,\n useCofheTokensWithExistingEncryptedBalances,\n useCofheTokenTransactions,\n useCofheTokenTransfer,\n useResolvedCofheToken,\n useCofheTransactions,\n addCofheTransaction,\n useCofheTokenUnshield,\n useCofheWalletClient,\n useCofheWriteContract,\n useCoingeckoContractMarketChartRange,\n useCoingeckoUsdPrice,\n useTokenAllowance,\n useTokensWithPublicBalances,\n useTransactionReceiptsByHash,\n type ClaimableAmountByTokenAddress,\n type CoingeckoMarketChartPoint,\n type Erc20Pair,\n type UnshieldClaim,\n type UnshieldClaimsSummary,\n type UnshieldClaimsSummaryByTokenAddress,\n type UseCoingeckoContractMarketChartRangeInput,\n type UseCoingeckoContractMarketChartRangeOptions,\n type UseCoingeckoUsdPriceInput,\n type UseCoingeckoUsdPriceOptions,\n type UseCofheTokenTransactionsInput,\n type UseCofheTokenTransactionsResult,\n type UseTransactionReceiptsByHashInput,\n type AddCofheTransactionInput,\n} from '@/hooks/index';\n\nexport { useCofheEncryptAndWriteContract } from '@/hooks/useCofheEncryptAndWriteContract';\nexport { useCofheReadContractAndDecrypt } from '@/hooks/useCofheReadContractAndDecrypt';\n\n// Utils\nexport {\n FheTypesList,\n formatRelativeTime,\n getBlockExplorerAddressUrl,\n getBlockExplorerTokenUrl,\n getBlockExplorerTxUrl,\n getBlockExplorerUrl,\n isEthPair,\n isWrappedEthToken,\n truncateHash,\n} from './utils/index';\n\n// Stores\nexport { useCustomTokensStore } from './stores/customTokensStore';\n\nexport {\n actionToString,\n isCustomTransactionActionType,\n statusToString,\n transactionMatchesToken,\n TransactionActionType,\n TransactionStatus,\n useTransactionStore,\n type Transaction,\n type BuiltInTransactionActionType,\n type CustomTransactionActionType,\n type JsonValue,\n type NewTransaction,\n type TransactionActionString,\n type TransactionStatusString,\n type TransactionStore,\n} from './stores/transactionStore';\n\nexport { createCofheConfig } from './config';\nexport type { CofheReactLogger, CofheReactLoggerMethod } from './config';\n\n// Types\nexport type {\n CofheClientConfig,\n CofheContextValue,\n CofheProviderProps,\n TransactionRenderer,\n TransactionRendererProps,\n TransactionRenderers,\n} from './types/index';\n\nexport { createCofheClient } from '@cofhe/sdk/web';\n\nexport { useCofheCreatePermit } from '@/hooks/permits/useCofheCreatePermit';\nexport { useCofheNavigateToCreatePermit } from '@/hooks/permits/useCofheNavigateToCreatePermit';\nexport { useCofheAutoConnect } from '@/hooks/useCofheAutoConnect';\nexport { CofheFloatingButtonProvider, sortCofheStatuses } from './components/index';\nexport { COFHE_STATUS_IDS, CofheStatusActionIntents } from './components/CofheFloatingButton/types';\n\nexport type { CofheConfigWithReact as CofhesdkConfigWithReact } from './config';\n\nexport type { CofheStatus, CofheStatusActionIntent, CofheStatusId } from './components/CofheFloatingButton/types';\nexport type { ConfidentialToken } from './types/token';\n\nexport type { CofheDecryptMeta, CofheQueryMeta } from './meta';\n\nexport { useCofheDecryptionActivity } from '@/hooks/useCofheDecryptionActivity';\nexport type {\n DecryptionActivityRow,\n DecryptionActivityResult,\n DecryptionActivityCategory,\n UseCofheDecryptionActivityOptions,\n FetchStageState,\n DecryptStageState,\n PermitState,\n} from '@/hooks/useCofheDecryptionActivity';\n\nexport { useInternalQueryClient } from './providers/index';\n\n// Type bridges for cross-repo / multi-instance viem peer dependency scenarios\nexport {\n asCofhePublicClient,\n tryAsCofhePublicClient,\n asCofheWalletClient,\n tryAsCofheWalletClient,\n} from './utils/viemClientBridge';\nexport type {\n PublicClientLike as CofhePublicClientLike,\n WalletClientLike as CofheWalletClientLike,\n} from './utils/viemClientBridge';\n\n// Block-aware cache invalidation primitives.\n//\n// These are the building blocks behind the SDK's own \"wait until the serving RPC\n// node has the mined block before returning a read\" behaviour. They are exported\n// so consumers (e.g. a wagmi-based app) can build the same reliability into their\n// own reads + post-tx invalidation, sharing THIS module's single invalidation-\n// context store — so an invalidation registered here is honoured by both the\n// SDK's confidential reads and the consumer's own block-aware queries.\nexport {\n invalidateQueriesWithContext,\n withInvalidationContext,\n findMatchingInvalidationContext,\n consumeInvalidationContext,\n type InvalidationContextQueryFilters,\n type QueryFunctionWithInvalidationContext,\n} from './utils/invalidationContext';\nexport {\n maybeWaitUntilRpcAware,\n maybeWaitUntilRpcAwareAndReadContract,\n type WaitUntilRpcAwareAndReadContractOptions,\n type ReadContractResult,\n} from './utils/waitUntilRpcAwareAndReadContract';\nexport { resolveReceiptBlockHash } from './utils/resolveReceiptBlockHash';\nexport { useInvalidationContextStore, type InvalidationContextEntry } from './stores/invalidationContextStore';\n","import { useCallback, useEffect, useMemo, useReducer, useRef } from 'react';\nimport { useInternalQueryClient } from '@/providers';\nimport { useCofheAccount, useCofheChainId } from './useCofheConnection';\nimport { useCofheActivePermit } from './useCofhePermits';\nimport type { CofheQueryMeta } from '@/meta';\n\n// ============================================================================\n// Decryption activity — the lifecycle view of confidential reads + decryptions.\n// ============================================================================\n//\n// A confidential value is a two-stage pipeline, both stages living as react-query\n// queries on the SDK's internal QueryClient:\n// A) FETCH — read the ciphertext handle on-chain (`cofheReadContract`),\n// whose data carries the `ctHash`.\n// B) DECRYPT— decrypt that handle off-chain (`decryptCiphertext`, keyed\n// BY the ctHash).\n//\n// This hook observes the cache, correlates the two stages by ctHash, and returns\n// one row per confidential value with a recognizable contract/method/label (from\n// each query's `meta`) — surfacing states a plain error/loading flag can't:\n// • \"blocked\" — gated off by a missing/invalid permit (never runs, never errors)\n// • \"stale\" — fetched, but the decrypt is pending far too long / never lands\n// Consumers render the rows; no query-key parsing or side registries required.\n\nconst DEFAULT_STALE_MS = 25_000;\nconst nowSec = () => Math.floor(Date.now() / 1000);\n\n/** 'idle' = a read/decrypt query exists but is disabled/never-ran (fetchStatus 'idle'), vs 'pending' (in flight). */\nexport type FetchStageState = 'ok' | 'pending' | 'idle' | 'error' | 'empty';\nexport type DecryptStageState = 'ok' | 'pending' | 'idle' | 'stale' | 'error' | 'blocked' | 'absent';\nexport type PermitState = 'valid' | 'expired' | 'unsigned' | 'none';\n/** Coarse bucket for filtering: something wrong / decrypted / nothing conclusive. */\nexport type DecryptionActivityCategory = 'error' | 'success' | 'idle';\n\nexport interface DecryptionActivityRow {\n key: string;\n /** Canonical decimal ctHash, when known. */\n ctHash?: string;\n /** 0x…-shortened ctHash for display. */\n ctHashShort?: string;\n /** The originating query metadata (contract / method / label / consumer fields). */\n meta?: CofheQueryMeta;\n /** Convenience shortcuts pulled from meta. */\n chainId?: number;\n address?: string;\n functionName?: string;\n label?: string;\n fetch: FetchStageState;\n decrypt: DecryptStageState;\n category: DecryptionActivityCategory;\n /** Why the row is blocked, e.g. \"permit none\". */\n blockedReason?: string;\n /** How long the decrypt has been pending, ms (drives \"stale\"). */\n pendingMs?: number;\n updatedAt: number;\n /** Whether re-running is possible (false for gated/idle reads with nothing enabled). */\n canRetry: boolean;\n /** Re-run this value's read and/or decrypt. */\n retry: () => void;\n}\n\nexport interface DecryptionActivityResult {\n rows: DecryptionActivityRow[];\n counts: { total: number; ok: number; pending: number; stale: number; blocked: number; error: number };\n permit: { state: PermitState; expiresInSec?: number };\n /** Wipe the whole SDK query cache; mounted reads/decryptions refetch from scratch. */\n clearCache: () => void;\n}\n\nexport interface UseCofheDecryptionActivityOptions {\n /** How long a decrypt may stay pending before it's reported \"stale\" (default 25s). */\n staleMs?: number;\n}\n\n// Minimal structural view of a cached query — enough to classify without depending\n// on react-query's concrete generic types.\ninterface QueryLike {\n queryKey: unknown;\n queryHash: string;\n meta?: CofheQueryMeta;\n state: { status: 'pending' | 'error' | 'success'; fetchStatus?: string; data?: unknown; dataUpdatedAt?: number };\n}\ninterface CacheLike {\n getAll: () => QueryLike[];\n subscribe: (cb: () => void) => () => void;\n}\ninterface ClientLike {\n getQueryCache: () => CacheLike;\n refetchQueries: (filters: { queryKey: unknown; exact?: boolean }) => Promise<unknown>;\n clear: () => void;\n}\n\nfunction normalizeCt(x: unknown): string | undefined {\n if (x === null || x === undefined) return undefined;\n try {\n return BigInt(x as string | number | bigint).toString();\n } catch {\n const s = String(x);\n return s && s !== '[object Object]' ? s : undefined;\n }\n}\n\n// A ctHash of 0 is not a real handle: reads return it for an absent/encrypted-zero\n// value and the decrypt is gated on `ctHash > 0n`, so treat it as \"no handle\".\nfunction isZeroCt(ct: string | undefined): boolean {\n if (!ct) return false;\n try {\n return BigInt(ct) === 0n;\n } catch {\n return false;\n }\n}\n\nfunction shortCt(decimal: string): string {\n try {\n const hex = BigInt(decimal).toString(16);\n return hex.length > 10 ? `0x${hex.slice(0, 6)}…${hex.slice(-4)}` : `0x${hex}`;\n } catch {\n return decimal;\n }\n}\n\nfunction extractCtHash(data: unknown): string | undefined {\n if (data === null || data === undefined) return undefined;\n if (typeof data === 'bigint') return normalizeCt(data);\n if (typeof data === 'object' && data !== null && 'ctHash' in (data as Record<string, unknown>)) {\n return normalizeCt((data as { ctHash: unknown }).ctHash);\n }\n return undefined;\n}\n\n// The read key bakes the transient activePermitHash + enabled flags into its tail,\n// so the SAME value gets a fresh cache entry each time a permit appears/rotates.\n// Its stable identity is [prefix, chainId, address, fn, args] (indices 0-4).\nfunction stableReadKey(k: unknown[]): string {\n try {\n return JSON.stringify(k.slice(0, 5));\n } catch {\n return String(k[1]) + '|' + String(k[2]) + '|' + String(k[3]);\n }\n}\n\n// Progress of a read: ran (success/error) > in flight > idle/never-ran.\nfunction readProgress(q: QueryLike): number {\n if (q.state.status === 'success' || q.state.status === 'error') return 2;\n if (q.state.fetchStatus === 'fetching') return 1;\n return 0;\n}\nfunction isFresherRead(candidate: QueryLike, current: QueryLike): boolean {\n const pc = readProgress(candidate);\n const pk = readProgress(current);\n if (pc !== pk) return pc > pk;\n return (candidate.state.dataUpdatedAt ?? 0) > (current.state.dataUpdatedAt ?? 0);\n}\n\nfunction categoryFor(fetch: FetchStageState, decrypt: DecryptStageState): DecryptionActivityCategory {\n if (fetch === 'error' || decrypt === 'error' || decrypt === 'blocked' || decrypt === 'stale') return 'error';\n if (decrypt === 'ok') return 'success';\n return 'idle';\n}\n\n/**\n * Observe the ctHash-fetch → decrypt pipeline on the SDK's QueryClient, correlated\n * by ctHash and cross-referenced against the active permit. Must be used inside the\n * Cofhe provider.\n */\nexport function useCofheDecryptionActivity(options?: UseCofheDecryptionActivityOptions): DecryptionActivityResult {\n const staleMs = options?.staleMs ?? DEFAULT_STALE_MS;\n const queryClient = useInternalQueryClient() as unknown as ClientLike;\n const account = useCofheAccount();\n const chainId = useCofheChainId();\n const active = useCofheActivePermit();\n const permitObj = active?.permit;\n\n // Track when each decrypt first went pending, so \"stale\" is real elapsed time\n // (react-query doesn't expose a fetch-start timestamp for a never-resolved query).\n const pendingSinceRef = useRef(new Map<string, number>());\n\n // Re-render on cache changes AND on a slow tick (staleness is time-based, not\n // event-driven — a query sitting pending emits no cache events).\n //\n // Coalesce cache events to one bump per animation frame. `cache.subscribe` fires\n // synchronously on EVERY cache event (including observer option/result updates),\n // and a consumer re-render can itself emit fresh cache events — an unbounded\n // bump→render→event→bump storm that pins the main thread and starves unrelated\n // updates (e.g. a route change never commits). One bump per frame keeps the view\n // live while capping re-renders so the loop can't run away.\n const [version, bump] = useReducer((n: number) => n + 1, 0);\n useEffect(() => {\n const cache = queryClient.getQueryCache();\n let scheduled = false;\n const schedule = () => {\n if (scheduled) return;\n scheduled = true;\n const run = () => {\n scheduled = false;\n bump();\n };\n if (typeof requestAnimationFrame === 'function') requestAnimationFrame(run);\n else setTimeout(run, 16);\n };\n const unsub = cache.subscribe(schedule);\n const tick = setInterval(bump, 5_000);\n return () => {\n unsub();\n clearInterval(tick);\n };\n }, [queryClient]);\n\n const clearCache = useCallback(() => queryClient.clear(), [queryClient]);\n\n const data = useMemo(() => {\n const cache = queryClient.getQueryCache();\n const queries = cache.getAll();\n const now = Date.now();\n\n const refetch = (key: unknown) => void queryClient.refetchQueries({ queryKey: key, exact: true });\n\n const permitState: PermitState = !permitObj\n ? 'none'\n : !permitObj.issuerSignature || permitObj.issuerSignature === '0x'\n ? 'unsigned'\n : permitObj.expiration <= nowSec()\n ? 'expired'\n : 'valid';\n const permitValid = permitState === 'valid';\n\n // Index decrypt queries by ctHash (source contract + label come from meta).\n const decryptByCt = new Map<\n string,\n { state: 'ok' | 'pending' | 'idle' | 'error'; pendingMs?: number; key?: unknown; meta?: CofheQueryMeta }\n >();\n const seenPending = new Set<string>();\n for (const q of queries) {\n const k = q.queryKey;\n if (!Array.isArray(k) || k[0] !== 'decryptCiphertext') continue;\n const ct = normalizeCt(k[1]);\n if (!ct || isZeroCt(ct)) continue;\n const base = { key: q.queryKey, meta: q.meta };\n if (q.state.status === 'success') {\n decryptByCt.set(ct, { state: 'ok', ...base });\n pendingSinceRef.current.delete(ct);\n } else if (q.state.status === 'error') {\n decryptByCt.set(ct, { state: 'error', ...base });\n pendingSinceRef.current.delete(ct);\n } else if (q.state.fetchStatus === 'fetching') {\n seenPending.add(ct);\n let since = pendingSinceRef.current.get(ct);\n if (since === undefined) {\n since = now;\n pendingSinceRef.current.set(ct, since);\n }\n decryptByCt.set(ct, { state: 'pending', pendingMs: now - since, ...base });\n } else {\n // status 'pending' but fetchStatus 'idle' → disabled / never ran.\n pendingSinceRef.current.delete(ct);\n decryptByCt.set(ct, { state: 'idle', ...base });\n }\n }\n\n const rows: DecryptionActivityRow[] = [];\n const usedCt = new Set<string>();\n\n // Collapse per-permit/enabled key rotations to one entry per value.\n const readByValue = new Map<string, QueryLike>();\n for (const q of queries) {\n const k = q.queryKey;\n if (!Array.isArray(k) || k[0] !== 'cofheReadContract') continue;\n const id = stableReadKey(k);\n const existing = readByValue.get(id);\n if (!existing || isFresherRead(q, existing)) readByValue.set(id, q);\n }\n\n const pushRow = (\n row: Omit<DecryptionActivityRow, 'category' | 'canRetry' | 'retry'> & {\n fetchKey?: unknown;\n decryptKey?: unknown;\n }\n ) => {\n const { fetchKey, decryptKey, ...rest } = row;\n const canRetry = rest.fetch !== 'idle' && (fetchKey !== undefined || decryptKey !== undefined);\n rows.push({\n ...rest,\n category: categoryFor(rest.fetch, rest.decrypt),\n canRetry,\n retry: () => {\n if (fetchKey !== undefined) refetch(fetchKey);\n if (decryptKey !== undefined) refetch(decryptKey);\n },\n });\n };\n\n // One row per confidential value; attach its decrypt stage by ctHash.\n for (const q of readByValue.values()) {\n const m = q.meta;\n const ctRaw = q.state.status === 'success' ? extractCtHash(q.state.data) : undefined;\n const ct = ctRaw && !isZeroCt(ctRaw) ? ctRaw : undefined;\n const fetchInFlight = q.state.fetchStatus === 'fetching';\n const fetchState: FetchStageState =\n q.state.status === 'error'\n ? 'error'\n : q.state.status === 'pending'\n ? fetchInFlight\n ? 'pending'\n : 'idle'\n : ct\n ? 'ok'\n : 'empty';\n\n let decrypt: DecryptStageState = 'absent';\n let blockedReason: string | undefined;\n let pendingMs: number | undefined;\n let decryptKey: unknown;\n let decryptMeta: CofheQueryMeta | undefined;\n if (ct) {\n usedCt.add(ct);\n const d = decryptByCt.get(ct);\n decryptKey = d?.key;\n decryptMeta = d?.meta;\n if (d?.state === 'ok') decrypt = 'ok';\n else if (d?.state === 'error') decrypt = 'error';\n else if (d?.state === 'idle') decrypt = 'idle';\n else if (d?.state === 'pending') {\n pendingMs = d.pendingMs;\n decrypt = (d.pendingMs ?? 0) > staleMs ? 'stale' : 'pending';\n } else {\n decrypt = permitValid ? 'absent' : 'blocked';\n if (!permitValid) blockedReason = `permit ${permitState}`;\n }\n } else if (fetchState === 'idle' && !permitValid) {\n // The read is gated off (no valid permit) — blocked before any ctHash.\n decrypt = 'blocked';\n blockedReason = `permit ${permitState}`;\n }\n\n const meta = m ?? decryptMeta;\n pushRow({\n key: q.queryHash,\n ctHash: ct,\n ctHashShort: ct ? shortCt(ct) : undefined,\n meta,\n chainId: meta?.chainId,\n address: meta?.address,\n functionName: meta?.functionName,\n label: meta?.consumer?.label,\n fetch: fetchState,\n decrypt,\n blockedReason,\n pendingMs,\n updatedAt: now,\n fetchKey: q.queryKey,\n decryptKey,\n });\n }\n\n // Orphan decrypts (a ctHash being decrypted with no fetch query in cache).\n for (const [ct, d] of decryptByCt) {\n if (usedCt.has(ct)) continue;\n const decrypt: DecryptStageState =\n d.state === 'ok'\n ? 'ok'\n : d.state === 'error'\n ? 'error'\n : d.state === 'idle'\n ? 'idle'\n : (d.pendingMs ?? 0) > staleMs\n ? 'stale'\n : 'pending';\n pushRow({\n key: `decrypt:${ct}`,\n ctHash: ct,\n ctHashShort: shortCt(ct),\n meta: d.meta,\n chainId: d.meta?.chainId,\n address: d.meta?.address,\n functionName: d.meta?.functionName,\n label: d.meta?.consumer?.label,\n fetch: 'ok',\n decrypt,\n pendingMs: d.pendingMs,\n updatedAt: now,\n decryptKey: d.key,\n });\n }\n\n // Drop ctHashes we no longer see, so the pending-since map can't grow unbounded.\n for (const ct of pendingSinceRef.current.keys()) {\n if (!seenPending.has(ct)) pendingSinceRef.current.delete(ct);\n }\n\n const counts = {\n total: rows.length,\n ok: rows.filter((r) => r.decrypt === 'ok').length,\n pending: rows.filter((r) => r.decrypt === 'pending').length,\n stale: rows.filter((r) => r.decrypt === 'stale').length,\n blocked: rows.filter((r) => r.decrypt === 'blocked').length,\n error: rows.filter((r) => r.decrypt === 'error' || r.fetch === 'error').length,\n };\n\n // Most actionable first: blocked/stale/error, then pending, then done.\n const rank: Record<DecryptStageState, number> = {\n blocked: 0,\n stale: 1,\n error: 2,\n pending: 3,\n idle: 4,\n absent: 5,\n ok: 6,\n };\n rows.sort((a, b) => rank[a.decrypt] - rank[b.decrypt]);\n\n const expiresInSec = permitObj ? permitObj.expiration - nowSec() : undefined;\n return { rows, permit: { state: permitState, expiresInSec }, counts };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [queryClient, account, chainId, permitObj, staleMs, version]);\n\n return { ...data, clearCache };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+GA,SAAS,yBAAyB;;;AC/GlC,SAAS,aAAa,WAAW,SAAS,YAAY,cAAc;AAwBpE,IAAM,mBAAmB;AACzB,IAAM,SAAS,MAAM,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AAmEjD,SAAS,YAAY,GAAgC;AACnD,MAAI,MAAM,QAAQ,MAAM,OAAW,QAAO;AAC1C,MAAI;AACF,WAAO,OAAO,CAA6B,EAAE,SAAS;AAAA,EACxD,QAAQ;AACN,UAAM,IAAI,OAAO,CAAC;AAClB,WAAO,KAAK,MAAM,oBAAoB,IAAI;AAAA,EAC5C;AACF;AAIA,SAAS,SAAS,IAAiC;AACjD,MAAI,CAAC,GAAI,QAAO;AAChB,MAAI;AACF,WAAO,OAAO,EAAE,MAAM;AAAA,EACxB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,QAAQ,SAAyB;AACxC,MAAI;AACF,UAAM,MAAM,OAAO,OAAO,EAAE,SAAS,EAAE;AACvC,WAAO,IAAI,SAAS,KAAK,KAAK,IAAI,MAAM,GAAG,CAAC,CAAC,SAAI,IAAI,MAAM,EAAE,CAAC,KAAK,KAAK,GAAG;AAAA,EAC7E,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,cAAc,MAAmC;AACxD,MAAI,SAAS,QAAQ,SAAS,OAAW,QAAO;AAChD,MAAI,OAAO,SAAS,SAAU,QAAO,YAAY,IAAI;AACrD,MAAI,OAAO,SAAS,YAAY,SAAS,QAAQ,YAAa,MAAkC;AAC9F,WAAO,YAAa,KAA6B,MAAM;AAAA,EACzD;AACA,SAAO;AACT;AAKA,SAAS,cAAc,GAAsB;AAC3C,MAAI;AACF,WAAO,KAAK,UAAU,EAAE,MAAM,GAAG,CAAC,CAAC;AAAA,EACrC,QAAQ;AACN,WAAO,OAAO,EAAE,CAAC,CAAC,IAAI,MAAM,OAAO,EAAE,CAAC,CAAC,IAAI,MAAM,OAAO,EAAE,CAAC,CAAC;AAAA,EAC9D;AACF;AAGA,SAAS,aAAa,GAAsB;AAC1C,MAAI,EAAE,MAAM,WAAW,aAAa,EAAE,MAAM,WAAW,QAAS,QAAO;AACvE,MAAI,EAAE,MAAM,gBAAgB,WAAY,QAAO;AAC/C,SAAO;AACT;AACA,SAAS,cAAc,WAAsB,SAA6B;AACxE,QAAM,KAAK,aAAa,SAAS;AACjC,QAAM,KAAK,aAAa,OAAO;AAC/B,MAAI,OAAO,GAAI,QAAO,KAAK;AAC3B,UAAQ,UAAU,MAAM,iBAAiB,MAAM,QAAQ,MAAM,iBAAiB;AAChF;AAEA,SAAS,YAAY,OAAwB,SAAwD;AACnG,MAAI,UAAU,WAAW,YAAY,WAAW,YAAY,aAAa,YAAY,QAAS,QAAO;AACrG,MAAI,YAAY,KAAM,QAAO;AAC7B,SAAO;AACT;AAOO,SAAS,2BAA2B,SAAuE;AAChH,QAAM,UAAU,SAAS,WAAW;AACpC,QAAM,cAAc,uBAAuB;AAC3C,QAAM,UAAU,gBAAgB;AAChC,QAAM,UAAU,gBAAgB;AAChC,QAAM,SAAS,qBAAqB;AACpC,QAAM,YAAY,QAAQ;AAI1B,QAAM,kBAAkB,OAAO,oBAAI,IAAoB,CAAC;AAWxD,QAAM,CAAC,SAAS,IAAI,IAAI,WAAW,CAAC,MAAc,IAAI,GAAG,CAAC;AAC1D,YAAU,MAAM;AACd,UAAM,QAAQ,YAAY,cAAc;AACxC,QAAI,YAAY;AAChB,UAAM,WAAW,MAAM;AACrB,UAAI,UAAW;AACf,kBAAY;AACZ,YAAM,MAAM,MAAM;AAChB,oBAAY;AACZ,aAAK;AAAA,MACP;AACA,UAAI,OAAO,0BAA0B,WAAY,uBAAsB,GAAG;AAAA,UACrE,YAAW,KAAK,EAAE;AAAA,IACzB;AACA,UAAM,QAAQ,MAAM,UAAU,QAAQ;AACtC,UAAM,OAAO,YAAY,MAAM,GAAK;AACpC,WAAO,MAAM;AACX,YAAM;AACN,oBAAc,IAAI;AAAA,IACpB;AAAA,EACF,GAAG,CAAC,WAAW,CAAC;AAEhB,QAAM,aAAa,YAAY,MAAM,YAAY,MAAM,GAAG,CAAC,WAAW,CAAC;AAEvE,QAAM,OAAO,QAAQ,MAAM;AACzB,UAAM,QAAQ,YAAY,cAAc;AACxC,UAAM,UAAU,MAAM,OAAO;AAC7B,UAAM,MAAM,KAAK,IAAI;AAErB,UAAM,UAAU,CAAC,QAAiB,KAAK,YAAY,eAAe,EAAE,UAAU,KAAK,OAAO,KAAK,CAAC;AAEhG,UAAM,cAA2B,CAAC,YAC9B,SACA,CAAC,UAAU,mBAAmB,UAAU,oBAAoB,OAC1D,aACA,UAAU,cAAc,OAAO,IAC7B,YACA;AACR,UAAM,cAAc,gBAAgB;AAGpC,UAAM,cAAc,oBAAI,IAGtB;AACF,UAAM,cAAc,oBAAI,IAAY;AACpC,eAAW,KAAK,SAAS;AACvB,YAAM,IAAI,EAAE;AACZ,UAAI,CAAC,MAAM,QAAQ,CAAC,KAAK,EAAE,CAAC,MAAM,oBAAqB;AACvD,YAAM,KAAK,YAAY,EAAE,CAAC,CAAC;AAC3B,UAAI,CAAC,MAAM,SAAS,EAAE,EAAG;AACzB,YAAM,OAAO,EAAE,KAAK,EAAE,UAAU,MAAM,EAAE,KAAK;AAC7C,UAAI,EAAE,MAAM,WAAW,WAAW;AAChC,oBAAY,IAAI,IAAI,EAAE,OAAO,MAAM,GAAG,KAAK,CAAC;AAC5C,wBAAgB,QAAQ,OAAO,EAAE;AAAA,MACnC,WAAW,EAAE,MAAM,WAAW,SAAS;AACrC,oBAAY,IAAI,IAAI,EAAE,OAAO,SAAS,GAAG,KAAK,CAAC;AAC/C,wBAAgB,QAAQ,OAAO,EAAE;AAAA,MACnC,WAAW,EAAE,MAAM,gBAAgB,YAAY;AAC7C,oBAAY,IAAI,EAAE;AAClB,YAAI,QAAQ,gBAAgB,QAAQ,IAAI,EAAE;AAC1C,YAAI,UAAU,QAAW;AACvB,kBAAQ;AACR,0BAAgB,QAAQ,IAAI,IAAI,KAAK;AAAA,QACvC;AACA,oBAAY,IAAI,IAAI,EAAE,OAAO,WAAW,WAAW,MAAM,OAAO,GAAG,KAAK,CAAC;AAAA,MAC3E,OAAO;AAEL,wBAAgB,QAAQ,OAAO,EAAE;AACjC,oBAAY,IAAI,IAAI,EAAE,OAAO,QAAQ,GAAG,KAAK,CAAC;AAAA,MAChD;AAAA,IACF;AAEA,UAAM,OAAgC,CAAC;AACvC,UAAM,SAAS,oBAAI,IAAY;AAG/B,UAAM,cAAc,oBAAI,IAAuB;AAC/C,eAAW,KAAK,SAAS;AACvB,YAAM,IAAI,EAAE;AACZ,UAAI,CAAC,MAAM,QAAQ,CAAC,KAAK,EAAE,CAAC,MAAM,oBAAqB;AACvD,YAAM,KAAK,cAAc,CAAC;AAC1B,YAAM,WAAW,YAAY,IAAI,EAAE;AACnC,UAAI,CAAC,YAAY,cAAc,GAAG,QAAQ,EAAG,aAAY,IAAI,IAAI,CAAC;AAAA,IACpE;AAEA,UAAM,UAAU,CACd,QAIG;AACH,YAAM,EAAE,UAAU,YAAY,GAAG,KAAK,IAAI;AAC1C,YAAM,WAAW,KAAK,UAAU,WAAW,aAAa,UAAa,eAAe;AACpF,WAAK,KAAK;AAAA,QACR,GAAG;AAAA,QACH,UAAU,YAAY,KAAK,OAAO,KAAK,OAAO;AAAA,QAC9C;AAAA,QACA,OAAO,MAAM;AACX,cAAI,aAAa,OAAW,SAAQ,QAAQ;AAC5C,cAAI,eAAe,OAAW,SAAQ,UAAU;AAAA,QAClD;AAAA,MACF,CAAC;AAAA,IACH;AAGA,eAAW,KAAK,YAAY,OAAO,GAAG;AACpC,YAAM,IAAI,EAAE;AACZ,YAAM,QAAQ,EAAE,MAAM,WAAW,YAAY,cAAc,EAAE,MAAM,IAAI,IAAI;AAC3E,YAAM,KAAK,SAAS,CAAC,SAAS,KAAK,IAAI,QAAQ;AAC/C,YAAM,gBAAgB,EAAE,MAAM,gBAAgB;AAC9C,YAAM,aACJ,EAAE,MAAM,WAAW,UACf,UACA,EAAE,MAAM,WAAW,YACjB,gBACE,YACA,SACF,KACE,OACA;AAEV,UAAI,UAA6B;AACjC,UAAI;AACJ,UAAI;AACJ,UAAI;AACJ,UAAI;AACJ,UAAI,IAAI;AACN,eAAO,IAAI,EAAE;AACb,cAAM,IAAI,YAAY,IAAI,EAAE;AAC5B,qBAAa,GAAG;AAChB,sBAAc,GAAG;AACjB,YAAI,GAAG,UAAU,KAAM,WAAU;AAAA,iBACxB,GAAG,UAAU,QAAS,WAAU;AAAA,iBAChC,GAAG,UAAU,OAAQ,WAAU;AAAA,iBAC/B,GAAG,UAAU,WAAW;AAC/B,sBAAY,EAAE;AACd,qBAAW,EAAE,aAAa,KAAK,UAAU,UAAU;AAAA,QACrD,OAAO;AACL,oBAAU,cAAc,WAAW;AACnC,cAAI,CAAC,YAAa,iBAAgB,UAAU,WAAW;AAAA,QACzD;AAAA,MACF,WAAW,eAAe,UAAU,CAAC,aAAa;AAEhD,kBAAU;AACV,wBAAgB,UAAU,WAAW;AAAA,MACvC;AAEA,YAAM,OAAO,KAAK;AAClB,cAAQ;AAAA,QACN,KAAK,EAAE;AAAA,QACP,QAAQ;AAAA,QACR,aAAa,KAAK,QAAQ,EAAE,IAAI;AAAA,QAChC;AAAA,QACA,SAAS,MAAM;AAAA,QACf,SAAS,MAAM;AAAA,QACf,cAAc,MAAM;AAAA,QACpB,OAAO,MAAM,UAAU;AAAA,QACvB,OAAO;AAAA,QACP;AAAA,QACA;AAAA,QACA;AAAA,QACA,WAAW;AAAA,QACX,UAAU,EAAE;AAAA,QACZ;AAAA,MACF,CAAC;AAAA,IACH;AAGA,eAAW,CAAC,IAAI,CAAC,KAAK,aAAa;AACjC,UAAI,OAAO,IAAI,EAAE,EAAG;AACpB,YAAM,UACJ,EAAE,UAAU,OACR,OACA,EAAE,UAAU,UACV,UACA,EAAE,UAAU,SACV,UACC,EAAE,aAAa,KAAK,UACnB,UACA;AACZ,cAAQ;AAAA,QACN,KAAK,WAAW,EAAE;AAAA,QAClB,QAAQ;AAAA,QACR,aAAa,QAAQ,EAAE;AAAA,QACvB,MAAM,EAAE;AAAA,QACR,SAAS,EAAE,MAAM;AAAA,QACjB,SAAS,EAAE,MAAM;AAAA,QACjB,cAAc,EAAE,MAAM;AAAA,QACtB,OAAO,EAAE,MAAM,UAAU;AAAA,QACzB,OAAO;AAAA,QACP;AAAA,QACA,WAAW,EAAE;AAAA,QACb,WAAW;AAAA,QACX,YAAY,EAAE;AAAA,MAChB,CAAC;AAAA,IACH;AAGA,eAAW,MAAM,gBAAgB,QAAQ,KAAK,GAAG;AAC/C,UAAI,CAAC,YAAY,IAAI,EAAE,EAAG,iBAAgB,QAAQ,OAAO,EAAE;AAAA,IAC7D;AAEA,UAAM,SAAS;AAAA,MACb,OAAO,KAAK;AAAA,MACZ,IAAI,KAAK,OAAO,CAAC,MAAM,EAAE,YAAY,IAAI,EAAE;AAAA,MAC3C,SAAS,KAAK,OAAO,CAAC,MAAM,EAAE,YAAY,SAAS,EAAE;AAAA,MACrD,OAAO,KAAK,OAAO,CAAC,MAAM,EAAE,YAAY,OAAO,EAAE;AAAA,MACjD,SAAS,KAAK,OAAO,CAAC,MAAM,EAAE,YAAY,SAAS,EAAE;AAAA,MACrD,OAAO,KAAK,OAAO,CAAC,MAAM,EAAE,YAAY,WAAW,EAAE,UAAU,OAAO,EAAE;AAAA,IAC1E;AAGA,UAAM,OAA0C;AAAA,MAC9C,SAAS;AAAA,MACT,OAAO;AAAA,MACP,OAAO;AAAA,MACP,SAAS;AAAA,MACT,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,IAAI;AAAA,IACN;AACA,SAAK,KAAK,CAAC,GAAG,MAAM,KAAK,EAAE,OAAO,IAAI,KAAK,EAAE,OAAO,CAAC;AAErD,UAAM,eAAe,YAAY,UAAU,aAAa,OAAO,IAAI;AACnE,WAAO,EAAE,MAAM,QAAQ,EAAE,OAAO,aAAa,aAAa,GAAG,OAAO;AAAA,EAEtE,GAAG,CAAC,aAAa,SAAS,SAAS,WAAW,SAAS,OAAO,CAAC;AAE/D,SAAO,EAAE,GAAG,MAAM,WAAW;AAC/B;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cofhe/react",
|
|
3
|
-
"version": "0.0.0-alpha-
|
|
3
|
+
"version": "0.0.0-alpha-20260721113524",
|
|
4
4
|
"main": "./dist/index.cjs",
|
|
5
5
|
"module": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -47,8 +47,8 @@
|
|
|
47
47
|
"tsup": "8.5.0",
|
|
48
48
|
"typescript": "5.5.4",
|
|
49
49
|
"vitest": "3.2.4",
|
|
50
|
-
"@cofhe/
|
|
51
|
-
"@cofhe/
|
|
50
|
+
"@cofhe/tsconfig": "0.1.2",
|
|
51
|
+
"@cofhe/eslint-config": "0.2.1"
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
54
|
"@fhenixprotocol/cofhe-errors": "1.0.2",
|
|
@@ -65,8 +65,8 @@
|
|
|
65
65
|
"tailwind-merge": "2.6.0",
|
|
66
66
|
"zod": "4.1.12",
|
|
67
67
|
"zustand": "5.0.13",
|
|
68
|
-
"@cofhe/abi": "0.0.0-alpha-
|
|
69
|
-
"@cofhe/sdk": "0.0.0-alpha-
|
|
68
|
+
"@cofhe/abi": "0.0.0-alpha-20260721113524",
|
|
69
|
+
"@cofhe/sdk": "0.0.0-alpha-20260721113524"
|
|
70
70
|
},
|
|
71
71
|
"peerDependencies": {
|
|
72
72
|
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
|