@pyefi/sdk 0.1.4 → 0.1.5

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/dist/react.js CHANGED
@@ -1,14 +1,18 @@
1
1
  import {
2
2
  createApyStore,
3
3
  createBalanceStore,
4
+ createLockupStore,
4
5
  createMarketStore,
6
+ createValidatorStore,
5
7
  createWalletStore,
6
8
  fetchBalances,
7
9
  fetchExchangeBalances,
8
10
  fetchUserStakeAccounts,
9
11
  getPyeConfig,
10
- parseOrderBook
11
- } from "./chunk-62OCHHT7.js";
12
+ parseOrderBook,
13
+ readCachedWalletBalances,
14
+ writeCachedWalletBalances
15
+ } from "./chunk-GXXXUTDQ.js";
12
16
 
13
17
  // src/react/providers.tsx
14
18
  import { createContext, useContext, useRef } from "react";
@@ -74,8 +78,38 @@ function useApyStore(selector) {
74
78
  }
75
79
  return useStore(store, selector);
76
80
  }
81
+ var ValidatorStoreContext = createContext(null);
82
+ function ValidatorStoreProvider({ children }) {
83
+ const storeRef = useRef(void 0);
84
+ if (!storeRef.current) {
85
+ storeRef.current = createValidatorStore();
86
+ }
87
+ return /* @__PURE__ */ jsx(ValidatorStoreContext.Provider, { value: storeRef.current, children });
88
+ }
89
+ function useValidatorStore(selector) {
90
+ const store = useContext(ValidatorStoreContext);
91
+ if (!store) {
92
+ throw new Error("useValidatorStore must be used within ValidatorStoreProvider");
93
+ }
94
+ return useStore(store, selector);
95
+ }
96
+ var LockupStoreContext = createContext(null);
97
+ function LockupStoreProvider({ children }) {
98
+ const storeRef = useRef(void 0);
99
+ if (!storeRef.current) {
100
+ storeRef.current = createLockupStore();
101
+ }
102
+ return /* @__PURE__ */ jsx(LockupStoreContext.Provider, { value: storeRef.current, children });
103
+ }
104
+ function useLockupStore(selector) {
105
+ const store = useContext(LockupStoreContext);
106
+ if (!store) {
107
+ throw new Error("useLockupStore must be used within LockupStoreProvider");
108
+ }
109
+ return useStore(store, selector);
110
+ }
77
111
  function PyeSDKProvider({ children }) {
78
- return /* @__PURE__ */ jsx(WalletStoreProvider, { children: /* @__PURE__ */ jsx(BalanceStoreProvider, { children: /* @__PURE__ */ jsx(MarketStoreProvider, { children: /* @__PURE__ */ jsx(ApyStoreProvider, { children }) }) }) });
112
+ return /* @__PURE__ */ jsx(WalletStoreProvider, { children: /* @__PURE__ */ jsx(BalanceStoreProvider, { children: /* @__PURE__ */ jsx(ValidatorStoreProvider, { children: /* @__PURE__ */ jsx(LockupStoreProvider, { children: /* @__PURE__ */ jsx(MarketStoreProvider, { children: /* @__PURE__ */ jsx(ApyStoreProvider, { children }) }) }) }) }) });
79
113
  }
80
114
 
81
115
  // src/react/BalanceSyncer.tsx
@@ -153,9 +187,13 @@ function BalanceSyncer() {
153
187
  console.log("[BalanceSyncer] wallet changed:", prevPublicKeyRef.current, "\u2192", publicKey);
154
188
  prevPublicKeyRef.current = publicKey;
155
189
  resetBalances();
156
- const cached = readCachedStakeAccounts(publicKey);
157
- if (cached && cached.length > 0) {
158
- setUserStakeAccounts(cached);
190
+ const cachedStakes = readCachedStakeAccounts(publicKey);
191
+ if (cachedStakes && cachedStakes.length > 0) {
192
+ setUserStakeAccounts(cachedStakes);
193
+ }
194
+ const cachedBalances = readCachedWalletBalances(publicKey);
195
+ if (cachedBalances) {
196
+ setWalletBalances(cachedBalances);
159
197
  }
160
198
  }
161
199
  const owner = new PublicKey(publicKey);
@@ -174,6 +212,7 @@ function BalanceSyncer() {
174
212
  fetchBalances(connection, owner).then((walletBals) => {
175
213
  if (prevPublicKeyRef.current !== pkAtStart) return;
176
214
  setWalletBalances(walletBals);
215
+ writeCachedWalletBalances(pkAtStart, walletBals);
177
216
  }).catch((err) => {
178
217
  console.error("[BalanceSyncer] wallet-balances fetch failed:", err);
179
218
  });
@@ -200,6 +239,7 @@ function BalanceSyncer() {
200
239
  fetchBalances(connection, owner).then((walletBals) => {
201
240
  if (prevPublicKeyRef.current !== pkAtStart) return;
202
241
  setWalletBalances(walletBals);
242
+ writeCachedWalletBalances(pkAtStart, walletBals);
203
243
  }).catch((err) => {
204
244
  console.error("[BalanceSyncer] wallet-balances poll failed:", err);
205
245
  });
@@ -397,19 +437,45 @@ function ApySyncer() {
397
437
  }, [voteAccounts, fetchApyForVoteAccounts]);
398
438
  return null;
399
439
  }
440
+
441
+ // src/react/ValidatorSyncer.tsx
442
+ import { useEffect as useEffect5 } from "react";
443
+ function ValidatorSyncer() {
444
+ const fetchAll = useValidatorStore((s) => s.fetchAll);
445
+ useEffect5(() => {
446
+ fetchAll();
447
+ }, [fetchAll]);
448
+ return null;
449
+ }
450
+
451
+ // src/react/LockupSyncer.tsx
452
+ import { useEffect as useEffect6 } from "react";
453
+ function LockupSyncer() {
454
+ const fetchAll = useLockupStore((s) => s.fetchAll);
455
+ useEffect6(() => {
456
+ fetchAll();
457
+ }, [fetchAll]);
458
+ return null;
459
+ }
400
460
  export {
401
461
  ApyStoreProvider,
402
462
  ApySyncer,
403
463
  BalanceStoreProvider,
404
464
  BalanceSyncer,
465
+ LockupStoreProvider,
466
+ LockupSyncer,
405
467
  MarketStoreProvider,
406
468
  MarketSyncer,
407
469
  PyeSDKProvider,
470
+ ValidatorStoreProvider,
471
+ ValidatorSyncer,
408
472
  WalletStoreProvider,
409
473
  WalletSyncer,
410
474
  useApyStore,
411
475
  useBalanceStore,
476
+ useLockupStore,
412
477
  useMarketStore,
478
+ useValidatorStore,
413
479
  useWalletStore
414
480
  };
415
481
  //# sourceMappingURL=react.js.map
package/dist/react.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/react/providers.tsx","../src/react/BalanceSyncer.tsx","../src/lib/stake-accounts-cache.ts","../src/react/WalletSyncer.tsx","../src/react/MarketSyncer.tsx","../src/react/ApySyncer.tsx"],"sourcesContent":["import { createContext, useContext, useRef, type ReactNode } from \"react\";\nimport { useStore } from \"zustand\";\nimport { createWalletStore, type WalletStore } from \"../stores/wallet-store\";\nimport { createBalanceStore, type BalanceStore } from \"../stores/balance-store\";\nimport { createMarketStore, type MarketStore } from \"../stores/market-store\";\nimport { createApyStore, type ApyStore } from \"../stores/apy-store\";\n\n// ── Wallet Store ──\n\ntype WalletStoreApi = ReturnType<typeof createWalletStore>;\nconst WalletStoreContext = createContext<WalletStoreApi | null>(null);\n\nexport function WalletStoreProvider({ children }: { children: ReactNode }) {\n const storeRef = useRef<WalletStoreApi>(undefined);\n if (!storeRef.current) {\n storeRef.current = createWalletStore();\n }\n return (\n <WalletStoreContext.Provider value={storeRef.current}>\n {children}\n </WalletStoreContext.Provider>\n );\n}\n\nexport function useWalletStore<T>(selector: (state: WalletStore) => T): T {\n const store = useContext(WalletStoreContext);\n if (!store) {\n throw new Error(\"useWalletStore must be used within WalletStoreProvider\");\n }\n return useStore(store, selector);\n}\n\n// ── Balance Store ──\n\ntype BalanceStoreApi = ReturnType<typeof createBalanceStore>;\nconst BalanceStoreContext = createContext<BalanceStoreApi | null>(null);\n\nexport function BalanceStoreProvider({ children }: { children: ReactNode }) {\n const storeRef = useRef<BalanceStoreApi>(undefined);\n if (!storeRef.current) {\n storeRef.current = createBalanceStore();\n }\n return (\n <BalanceStoreContext.Provider value={storeRef.current}>\n {children}\n </BalanceStoreContext.Provider>\n );\n}\n\nexport function useBalanceStore<T>(selector: (state: BalanceStore) => T): T {\n const store = useContext(BalanceStoreContext);\n if (!store) {\n throw new Error(\"useBalanceStore must be used within BalanceStoreProvider\");\n }\n return useStore(store, selector);\n}\n\n// ── Market Store ──\n\ntype MarketStoreApi = ReturnType<typeof createMarketStore>;\nconst MarketStoreContext = createContext<MarketStoreApi | null>(null);\n\nexport function MarketStoreProvider({ children }: { children: ReactNode }) {\n const storeRef = useRef<MarketStoreApi>(undefined);\n if (!storeRef.current) {\n storeRef.current = createMarketStore();\n }\n return (\n <MarketStoreContext.Provider value={storeRef.current}>\n {children}\n </MarketStoreContext.Provider>\n );\n}\n\nexport function useMarketStore<T>(selector: (state: MarketStore) => T): T {\n const store = useContext(MarketStoreContext);\n if (!store) {\n throw new Error(\"useMarketStore must be used within MarketStoreProvider\");\n }\n return useStore(store, selector);\n}\n\n// ── APY Store ──\n\ntype ApyStoreApi = ReturnType<typeof createApyStore>;\nconst ApyStoreContext = createContext<ApyStoreApi | null>(null);\n\nexport function ApyStoreProvider({ children }: { children: ReactNode }) {\n const storeRef = useRef<ApyStoreApi>(undefined);\n if (!storeRef.current) {\n storeRef.current = createApyStore();\n }\n return (\n <ApyStoreContext.Provider value={storeRef.current}>\n {children}\n </ApyStoreContext.Provider>\n );\n}\n\nexport function useApyStore<T>(selector: (state: ApyStore) => T): T {\n const store = useContext(ApyStoreContext);\n if (!store) {\n throw new Error(\"useApyStore must be used within ApyStoreProvider\");\n }\n return useStore(store, selector);\n}\n\n// ── Composed Provider ──\n\nexport function PyeSDKProvider({ children }: { children: ReactNode }) {\n return (\n <WalletStoreProvider>\n <BalanceStoreProvider>\n <MarketStoreProvider>\n <ApyStoreProvider>\n {children}\n </ApyStoreProvider>\n </MarketStoreProvider>\n </BalanceStoreProvider>\n </WalletStoreProvider>\n );\n}\n","import { useEffect, useRef } from \"react\";\nimport { useConnection } from \"@solana/wallet-adapter-react\";\nimport { PublicKey } from \"@solana/web3.js\";\nimport { useWalletStore, useBalanceStore, useMarketStore } from \"./providers\";\nimport { fetchBalances } from \"../lib/fetch-balances\";\nimport { fetchExchangeBalances } from \"../lib/fetch-exchange-balances\";\nimport { fetchUserStakeAccounts } from \"../lib/fetch-user-stake-accounts\";\nimport {\n readCachedStakeAccounts,\n writeCachedStakeAccounts,\n} from \"../lib/stake-accounts-cache\";\n\nconst POLL_INTERVAL_MS = 5 * 60 * 1000;\n\nexport default function BalanceSyncer() {\n const { connection } = useConnection();\n const status = useWalletStore((s) => s.status);\n const publicKey = useWalletStore((s) => s.publicKey);\n const setWalletBalances = useBalanceStore((s) => s.setWalletBalances);\n const setExchangeBalances = useBalanceStore((s) => s.setExchangeBalances);\n const setOpenOrdersBalances = useBalanceStore((s) => s.setOpenOrdersBalances);\n const setSolBalances = useBalanceStore((s) => s.setSolBalances);\n const setSolOpenOrdersBalances = useBalanceStore((s) => s.setSolOpenOrdersBalances);\n const setOpenOrders = useBalanceStore((s) => s.setOpenOrders);\n const setPerMarketBaseBalances = useBalanceStore((s) => s.setPerMarketBaseBalances);\n const setUserStakeAccounts = useBalanceStore((s) => s.setUserStakeAccounts);\n const setUserStakeAccountsLoading = useBalanceStore((s) => s.setUserStakeAccountsLoading);\n const resetBalances = useBalanceStore((s) => s.resetBalances);\n const marketsRecord = useMarketStore((s) => s.markets);\n const markets = Object.values(marketsRecord);\n const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);\n const prevPublicKeyRef = useRef<string | null>(null);\n\n useEffect(() => {\n if (intervalRef.current) {\n clearInterval(intervalRef.current);\n intervalRef.current = null;\n }\n\n if (status !== \"connected\" || !publicKey) {\n prevPublicKeyRef.current = null;\n resetBalances();\n return;\n }\n\n const walletChanged = prevPublicKeyRef.current !== publicKey;\n if (walletChanged) {\n console.log(\"[BalanceSyncer] wallet changed:\", prevPublicKeyRef.current, \"→\", publicKey);\n prevPublicKeyRef.current = publicKey;\n resetBalances();\n\n // Hydrate from cache synchronously so WelcomeScreen can render enabled rows\n // before the expensive getParsedProgramAccounts scan finishes.\n const cached = readCachedStakeAccounts(publicKey);\n if (cached && cached.length > 0) {\n setUserStakeAccounts(cached);\n }\n }\n\n const owner = new PublicKey(publicKey);\n const pkAtStart = publicKey;\n\n // Fire the three fetches independently so each store slice updates the moment\n // its own request resolves, instead of waiting on the slowest of the batch.\n setUserStakeAccountsLoading(true);\n fetchUserStakeAccounts(connection, owner)\n .then((stakeAccounts) => {\n if (prevPublicKeyRef.current !== pkAtStart) return;\n setUserStakeAccounts(stakeAccounts);\n writeCachedStakeAccounts(pkAtStart, stakeAccounts);\n })\n .catch((err) => {\n console.error(\"[BalanceSyncer] stake-accounts fetch failed:\", err);\n })\n .finally(() => {\n if (prevPublicKeyRef.current !== pkAtStart) return;\n setUserStakeAccountsLoading(false);\n });\n\n fetchBalances(connection, owner)\n .then((walletBals) => {\n if (prevPublicKeyRef.current !== pkAtStart) return;\n setWalletBalances(walletBals);\n })\n .catch((err) => {\n console.error(\"[BalanceSyncer] wallet-balances fetch failed:\", err);\n });\n\n fetchExchangeBalances(connection, owner, markets)\n .then((exchangeResult) => {\n if (prevPublicKeyRef.current !== pkAtStart) return;\n setExchangeBalances(exchangeResult.exchangeBalances);\n setOpenOrdersBalances(exchangeResult.openOrdersBalances);\n setSolBalances(exchangeResult.solBalances);\n setSolOpenOrdersBalances(exchangeResult.solOpenOrdersBalances);\n setOpenOrders(exchangeResult.openOrders);\n setPerMarketBaseBalances(exchangeResult.perMarketBaseBalances);\n })\n .catch((err) => {\n console.error(\"[BalanceSyncer] exchange-balances fetch failed:\", err);\n });\n\n intervalRef.current = setInterval(() => {\n if (prevPublicKeyRef.current !== pkAtStart) return;\n fetchUserStakeAccounts(connection, owner)\n .then((stakeAccounts) => {\n if (prevPublicKeyRef.current !== pkAtStart) return;\n setUserStakeAccounts(stakeAccounts);\n writeCachedStakeAccounts(pkAtStart, stakeAccounts);\n })\n .catch((err) => {\n console.error(\"[BalanceSyncer] stake-accounts poll failed:\", err);\n });\n fetchBalances(connection, owner)\n .then((walletBals) => {\n if (prevPublicKeyRef.current !== pkAtStart) return;\n setWalletBalances(walletBals);\n })\n .catch((err) => {\n console.error(\"[BalanceSyncer] wallet-balances poll failed:\", err);\n });\n fetchExchangeBalances(connection, owner, markets)\n .then((exchangeResult) => {\n if (prevPublicKeyRef.current !== pkAtStart) return;\n setExchangeBalances(exchangeResult.exchangeBalances);\n setOpenOrdersBalances(exchangeResult.openOrdersBalances);\n setSolBalances(exchangeResult.solBalances);\n setSolOpenOrdersBalances(exchangeResult.solOpenOrdersBalances);\n setOpenOrders(exchangeResult.openOrders);\n setPerMarketBaseBalances(exchangeResult.perMarketBaseBalances);\n })\n .catch((err) => {\n console.error(\"[BalanceSyncer] exchange-balances poll failed:\", err);\n });\n }, POLL_INTERVAL_MS);\n\n return () => {\n if (intervalRef.current) {\n clearInterval(intervalRef.current);\n intervalRef.current = null;\n }\n };\n }, [\n status,\n publicKey,\n connection,\n marketsRecord,\n setWalletBalances,\n setExchangeBalances,\n setOpenOrdersBalances,\n setSolBalances,\n setSolOpenOrdersBalances,\n setOpenOrders,\n setPerMarketBaseBalances,\n setUserStakeAccounts,\n setUserStakeAccountsLoading,\n resetBalances,\n ]);\n\n return null;\n}\n","import type { UserStakeAccount } from \"../stores/balance-store\";\n\nconst STORAGE_PREFIX = \"pye.stakeAccounts.v1.\";\nconst MAX_AGE_MS = 24 * 60 * 60 * 1000;\n\ninterface CachedPayload {\n timestamp: number;\n accounts: UserStakeAccount[];\n}\n\nfunction getStorage(): Storage | null {\n try {\n if (typeof window === \"undefined\") return null;\n return window.localStorage;\n } catch {\n return null;\n }\n}\n\nexport function readCachedStakeAccounts(\n publicKey: string,\n): UserStakeAccount[] | null {\n const storage = getStorage();\n if (!storage) return null;\n try {\n const raw = storage.getItem(STORAGE_PREFIX + publicKey);\n if (!raw) return null;\n const parsed = JSON.parse(raw) as CachedPayload;\n if (!parsed?.timestamp || !Array.isArray(parsed.accounts)) return null;\n if (Date.now() - parsed.timestamp > MAX_AGE_MS) return null;\n return parsed.accounts;\n } catch {\n return null;\n }\n}\n\nexport function writeCachedStakeAccounts(\n publicKey: string,\n accounts: UserStakeAccount[],\n): void {\n const storage = getStorage();\n if (!storage) return;\n try {\n const payload: CachedPayload = { timestamp: Date.now(), accounts };\n storage.setItem(STORAGE_PREFIX + publicKey, JSON.stringify(payload));\n } catch {\n // Silently ignore quota / serialization errors — cache is a perf hint, not correctness.\n }\n}\n","import { useEffect, useRef } from \"react\";\nimport { useWallet, useConnection } from \"@solana/wallet-adapter-react\";\nimport { address as toAddress } from \"@solana/kit\";\nimport { useWalletStore } from \"./providers\";\n\nfunction shortenAddress(address: string): string {\n return address.slice(0, 4) + \"...\" + address.slice(-4);\n}\n\n/**\n * Invisible component that syncs the Solana wallet adapter state into the\n * Zustand wallet store.\n */\nexport default function WalletSyncer() {\n const { publicKey, connected, connecting } = useWallet();\n const { connection } = useConnection();\n const fetchedKeyRef = useRef<string | null>(null);\n\n const setWalletStatus = useWalletStore((s) => s.setWalletStatus);\n const setWalletPublicKey = useWalletStore((s) => s.setWalletPublicKey);\n const setDisplayAddress = useWalletStore((s) => s.setDisplayAddress);\n const setBalanceLamports = useWalletStore((s) => s.setBalanceLamports);\n const setWalletInitialized = useWalletStore((s) => s.setWalletInitialized);\n const resetWallet = useWalletStore((s) => s.resetWallet);\n\n const fetchBalance = async (retries = 3) => {\n if (!publicKey || !connection) return;\n for (let i = 0; i < retries; i++) {\n try {\n const balance = await connection.getBalance(publicKey, \"confirmed\");\n console.log(\"[WalletSyncer] balanceLamports:\", balance);\n setBalanceLamports(balance);\n return;\n } catch {\n if (i < retries - 1) {\n await new Promise((r) => setTimeout(r, 1000 * (i + 1)));\n }\n }\n }\n console.warn(\"[WalletSyncer] balance fetch failed after all retries\");\n setBalanceLamports(null);\n };\n\n useEffect(() => {\n setWalletInitialized(true);\n\n if (connecting) {\n setWalletStatus(\"connecting\");\n } else if (connected && publicKey) {\n const base58 = publicKey.toBase58();\n if (fetchedKeyRef.current && fetchedKeyRef.current !== base58) {\n console.log(\"[WalletSyncer] wallet changed:\", fetchedKeyRef.current, \"→\", base58);\n }\n setWalletStatus(\"connected\");\n setWalletPublicKey(toAddress(base58));\n setDisplayAddress(shortenAddress(base58));\n if (fetchedKeyRef.current !== base58) {\n fetchedKeyRef.current = base58;\n fetchBalance();\n }\n } else {\n resetWallet();\n fetchedKeyRef.current = null;\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [connected, connecting, publicKey]);\n\n useEffect(() => {\n if (!connected || !publicKey) return;\n const interval = setInterval(() => fetchBalance(1), 30_000);\n return () => clearInterval(interval);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [connected, publicKey?.toBase58()]);\n\n useEffect(() => {\n if (!connected || !publicKey || !connection) return;\n const id = connection.onAccountChange(\n publicKey,\n (accountInfo) => setBalanceLamports(accountInfo.lamports),\n \"confirmed\",\n );\n return () => {\n connection.removeAccountChangeListener(id);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [connected, publicKey?.toBase58(), connection]);\n\n return null;\n}\n","import { useEffect } from \"react\";\nimport { createClient } from \"@supabase/supabase-js\";\nimport { useMarketStore } from \"./providers\";\nimport { parseOrderBook } from \"../lib/manifest-parser\";\nimport { getPyeConfig } from \"../config\";\n\n/**\n * Invisible component that:\n * 1. Fetches markets and RT backing on mount\n * 2. Polls RT backing every 60s\n * 3. Subscribes to Supabase Realtime for order book updates\n */\nexport default function MarketSyncer() {\n const fetchMarkets = useMarketStore((s) => s.fetchMarkets);\n const fetchRtBacking = useMarketStore((s) => s.fetchRtBacking);\n const updateMarketOrderBook = useMarketStore((s) => s.updateMarketOrderBook);\n const pubkeyIndex = useMarketStore((s) => s.pubkeyIndex);\n\n // Initial fetch\n useEffect(() => {\n fetchMarkets();\n fetchRtBacking();\n }, [fetchMarkets, fetchRtBacking]);\n\n // Re-poll rt_backing every 60s\n useEffect(() => {\n const interval = setInterval(() => {\n fetchRtBacking();\n }, 60_000);\n return () => clearInterval(interval);\n }, [fetchRtBacking]);\n\n // Supabase Realtime subscription for order book updates\n useEffect(() => {\n let config: ReturnType<typeof getPyeConfig>;\n try {\n config = getPyeConfig();\n } catch {\n return;\n }\n\n const supabase = createClient(config.supabaseUrl, config.supabaseAnonKey);\n\n const channel = supabase\n .channel(\"manifest-markets-changes\")\n .on(\n \"postgres_changes\",\n {\n event: \"UPDATE\",\n schema: \"public\",\n table: \"manifest_markets\",\n },\n (payload) => {\n const row = payload.new as { pubkey?: string; account_data?: string };\n if (!row.pubkey || !row.account_data) return;\n if (!pubkeyIndex[row.pubkey]) return;\n try {\n const summary = parseOrderBook(row.pubkey, row.account_data);\n updateMarketOrderBook(row.pubkey, summary);\n } catch (e) {\n console.error(\n `Realtime parse error for ${row.pubkey}:`,\n e instanceof Error ? e.message : e,\n );\n }\n },\n )\n .subscribe();\n\n return () => {\n supabase.removeChannel(channel);\n };\n }, [pubkeyIndex, updateMarketOrderBook]);\n\n return null;\n}\n","import { useEffect, useMemo } from \"react\";\nimport { useApyStore, useBalanceStore } from \"./providers\";\nimport { getPyeConfig } from \"../config\";\n\nconst POLL_INTERVAL_MS = 5 * 60 * 1000; // 5 minutes\n\n/**\n * Fetches staking APY from stakewiz_apy for relevant vote accounts.\n *\n * - Single-validator mode: fetches for the configured vote account on mount.\n * - Universal mode: fetches for vote accounts detected in the user's stake accounts.\n * - Polls every 5 minutes.\n */\nexport default function ApySyncer() {\n const fetchApyForVoteAccounts = useApyStore((s) => s.fetchApyForVoteAccounts);\n const userStakeAccounts = useBalanceStore((s) => s.userStakeAccounts);\n\n // Collect unique vote accounts from config + detected stake accounts\n const voteAccounts = useMemo(() => {\n const set = new Set<string>();\n const config = getPyeConfig();\n if (config.voteAccount) set.add(config.voteAccount);\n for (const sa of userStakeAccounts) {\n if (sa.validatorVoteAccount) set.add(sa.validatorVoteAccount);\n }\n return Array.from(set);\n }, [userStakeAccounts]);\n\n // Fetch whenever vote accounts change (new stake accounts detected)\n useEffect(() => {\n if (voteAccounts.length === 0) return;\n fetchApyForVoteAccounts(voteAccounts);\n }, [voteAccounts, fetchApyForVoteAccounts]);\n\n // Re-poll every 5 minutes (force refresh existing data)\n useEffect(() => {\n if (voteAccounts.length === 0) return;\n const interval = setInterval(() => {\n fetchApyForVoteAccounts(voteAccounts, true);\n }, POLL_INTERVAL_MS);\n return () => clearInterval(interval);\n }, [voteAccounts, fetchApyForVoteAccounts]);\n\n return null;\n}\n"],"mappings":"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","names":["useRef","useRef","useEffect","useRef","useConnection","useConnection","useRef","useEffect","useEffect","useEffect","useEffect","POLL_INTERVAL_MS","useEffect"]}
1
+ {"version":3,"sources":["../src/react/providers.tsx","../src/react/BalanceSyncer.tsx","../src/lib/stake-accounts-cache.ts","../src/react/WalletSyncer.tsx","../src/react/MarketSyncer.tsx","../src/react/ApySyncer.tsx","../src/react/ValidatorSyncer.tsx","../src/react/LockupSyncer.tsx"],"sourcesContent":["import { createContext, useContext, useRef, type ReactNode } from \"react\";\nimport { useStore } from \"zustand\";\nimport { createWalletStore, type WalletStore } from \"../stores/wallet-store\";\nimport { createBalanceStore, type BalanceStore } from \"../stores/balance-store\";\nimport { createMarketStore, type MarketStore } from \"../stores/market-store\";\nimport { createApyStore, type ApyStore } from \"../stores/apy-store\";\nimport { createValidatorStore, type ValidatorStore } from \"../stores/validator-store\";\nimport { createLockupStore, type LockupStore } from \"../stores/lockup-store\";\n\n// ── Wallet Store ──\n\ntype WalletStoreApi = ReturnType<typeof createWalletStore>;\nconst WalletStoreContext = createContext<WalletStoreApi | null>(null);\n\nexport function WalletStoreProvider({ children }: { children: ReactNode }) {\n const storeRef = useRef<WalletStoreApi>(undefined);\n if (!storeRef.current) {\n storeRef.current = createWalletStore();\n }\n return (\n <WalletStoreContext.Provider value={storeRef.current}>\n {children}\n </WalletStoreContext.Provider>\n );\n}\n\nexport function useWalletStore<T>(selector: (state: WalletStore) => T): T {\n const store = useContext(WalletStoreContext);\n if (!store) {\n throw new Error(\"useWalletStore must be used within WalletStoreProvider\");\n }\n return useStore(store, selector);\n}\n\n// ── Balance Store ──\n\ntype BalanceStoreApi = ReturnType<typeof createBalanceStore>;\nconst BalanceStoreContext = createContext<BalanceStoreApi | null>(null);\n\nexport function BalanceStoreProvider({ children }: { children: ReactNode }) {\n const storeRef = useRef<BalanceStoreApi>(undefined);\n if (!storeRef.current) {\n storeRef.current = createBalanceStore();\n }\n return (\n <BalanceStoreContext.Provider value={storeRef.current}>\n {children}\n </BalanceStoreContext.Provider>\n );\n}\n\nexport function useBalanceStore<T>(selector: (state: BalanceStore) => T): T {\n const store = useContext(BalanceStoreContext);\n if (!store) {\n throw new Error(\"useBalanceStore must be used within BalanceStoreProvider\");\n }\n return useStore(store, selector);\n}\n\n// ── Market Store ──\n\ntype MarketStoreApi = ReturnType<typeof createMarketStore>;\nconst MarketStoreContext = createContext<MarketStoreApi | null>(null);\n\nexport function MarketStoreProvider({ children }: { children: ReactNode }) {\n const storeRef = useRef<MarketStoreApi>(undefined);\n if (!storeRef.current) {\n storeRef.current = createMarketStore();\n }\n return (\n <MarketStoreContext.Provider value={storeRef.current}>\n {children}\n </MarketStoreContext.Provider>\n );\n}\n\nexport function useMarketStore<T>(selector: (state: MarketStore) => T): T {\n const store = useContext(MarketStoreContext);\n if (!store) {\n throw new Error(\"useMarketStore must be used within MarketStoreProvider\");\n }\n return useStore(store, selector);\n}\n\n// ── APY Store ──\n\ntype ApyStoreApi = ReturnType<typeof createApyStore>;\nconst ApyStoreContext = createContext<ApyStoreApi | null>(null);\n\nexport function ApyStoreProvider({ children }: { children: ReactNode }) {\n const storeRef = useRef<ApyStoreApi>(undefined);\n if (!storeRef.current) {\n storeRef.current = createApyStore();\n }\n return (\n <ApyStoreContext.Provider value={storeRef.current}>\n {children}\n </ApyStoreContext.Provider>\n );\n}\n\nexport function useApyStore<T>(selector: (state: ApyStore) => T): T {\n const store = useContext(ApyStoreContext);\n if (!store) {\n throw new Error(\"useApyStore must be used within ApyStoreProvider\");\n }\n return useStore(store, selector);\n}\n\n// ── Validator Store ──\n\ntype ValidatorStoreApi = ReturnType<typeof createValidatorStore>;\nconst ValidatorStoreContext = createContext<ValidatorStoreApi | null>(null);\n\nexport function ValidatorStoreProvider({ children }: { children: ReactNode }) {\n const storeRef = useRef<ValidatorStoreApi>(undefined);\n if (!storeRef.current) {\n storeRef.current = createValidatorStore();\n }\n return (\n <ValidatorStoreContext.Provider value={storeRef.current}>\n {children}\n </ValidatorStoreContext.Provider>\n );\n}\n\nexport function useValidatorStore<T>(selector: (state: ValidatorStore) => T): T {\n const store = useContext(ValidatorStoreContext);\n if (!store) {\n throw new Error(\"useValidatorStore must be used within ValidatorStoreProvider\");\n }\n return useStore(store, selector);\n}\n\n// ── Lockup Store ──\n\ntype LockupStoreApi = ReturnType<typeof createLockupStore>;\nconst LockupStoreContext = createContext<LockupStoreApi | null>(null);\n\nexport function LockupStoreProvider({ children }: { children: ReactNode }) {\n const storeRef = useRef<LockupStoreApi>(undefined);\n if (!storeRef.current) {\n storeRef.current = createLockupStore();\n }\n return (\n <LockupStoreContext.Provider value={storeRef.current}>\n {children}\n </LockupStoreContext.Provider>\n );\n}\n\nexport function useLockupStore<T>(selector: (state: LockupStore) => T): T {\n const store = useContext(LockupStoreContext);\n if (!store) {\n throw new Error(\"useLockupStore must be used within LockupStoreProvider\");\n }\n return useStore(store, selector);\n}\n\n// ── Composed Provider ──\n\nexport function PyeSDKProvider({ children }: { children: ReactNode }) {\n return (\n <WalletStoreProvider>\n <BalanceStoreProvider>\n <ValidatorStoreProvider>\n <LockupStoreProvider>\n <MarketStoreProvider>\n <ApyStoreProvider>\n {children}\n </ApyStoreProvider>\n </MarketStoreProvider>\n </LockupStoreProvider>\n </ValidatorStoreProvider>\n </BalanceStoreProvider>\n </WalletStoreProvider>\n );\n}\n","import { useEffect, useRef } from \"react\";\nimport { useConnection } from \"@solana/wallet-adapter-react\";\nimport { PublicKey } from \"@solana/web3.js\";\nimport { useWalletStore, useBalanceStore, useMarketStore } from \"./providers\";\nimport { fetchBalances } from \"../lib/fetch-balances\";\nimport { fetchExchangeBalances } from \"../lib/fetch-exchange-balances\";\nimport { fetchUserStakeAccounts } from \"../lib/fetch-user-stake-accounts\";\nimport {\n readCachedStakeAccounts,\n writeCachedStakeAccounts,\n} from \"../lib/stake-accounts-cache\";\nimport {\n readCachedWalletBalances,\n writeCachedWalletBalances,\n} from \"../lib/wallet-balances-cache\";\n\nconst POLL_INTERVAL_MS = 5 * 60 * 1000;\n\nexport default function BalanceSyncer() {\n const { connection } = useConnection();\n const status = useWalletStore((s) => s.status);\n const publicKey = useWalletStore((s) => s.publicKey);\n const setWalletBalances = useBalanceStore((s) => s.setWalletBalances);\n const setExchangeBalances = useBalanceStore((s) => s.setExchangeBalances);\n const setOpenOrdersBalances = useBalanceStore((s) => s.setOpenOrdersBalances);\n const setSolBalances = useBalanceStore((s) => s.setSolBalances);\n const setSolOpenOrdersBalances = useBalanceStore((s) => s.setSolOpenOrdersBalances);\n const setOpenOrders = useBalanceStore((s) => s.setOpenOrders);\n const setPerMarketBaseBalances = useBalanceStore((s) => s.setPerMarketBaseBalances);\n const setUserStakeAccounts = useBalanceStore((s) => s.setUserStakeAccounts);\n const setUserStakeAccountsLoading = useBalanceStore((s) => s.setUserStakeAccountsLoading);\n const resetBalances = useBalanceStore((s) => s.resetBalances);\n const marketsRecord = useMarketStore((s) => s.markets);\n const markets = Object.values(marketsRecord);\n const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);\n const prevPublicKeyRef = useRef<string | null>(null);\n\n useEffect(() => {\n if (intervalRef.current) {\n clearInterval(intervalRef.current);\n intervalRef.current = null;\n }\n\n if (status !== \"connected\" || !publicKey) {\n prevPublicKeyRef.current = null;\n resetBalances();\n return;\n }\n\n const walletChanged = prevPublicKeyRef.current !== publicKey;\n if (walletChanged) {\n console.log(\"[BalanceSyncer] wallet changed:\", prevPublicKeyRef.current, \"→\", publicKey);\n prevPublicKeyRef.current = publicKey;\n resetBalances();\n\n // Hydrate from cache synchronously so WelcomeScreen can render enabled rows\n // before the expensive getParsedProgramAccounts scan finishes.\n const cachedStakes = readCachedStakeAccounts(publicKey);\n if (cachedStakes && cachedStakes.length > 0) {\n setUserStakeAccounts(cachedStakes);\n }\n const cachedBalances = readCachedWalletBalances(publicKey);\n if (cachedBalances) {\n setWalletBalances(cachedBalances);\n }\n }\n\n const owner = new PublicKey(publicKey);\n const pkAtStart = publicKey;\n\n // Fire the three fetches independently so each store slice updates the moment\n // its own request resolves, instead of waiting on the slowest of the batch.\n setUserStakeAccountsLoading(true);\n fetchUserStakeAccounts(connection, owner)\n .then((stakeAccounts) => {\n if (prevPublicKeyRef.current !== pkAtStart) return;\n setUserStakeAccounts(stakeAccounts);\n writeCachedStakeAccounts(pkAtStart, stakeAccounts);\n })\n .catch((err) => {\n console.error(\"[BalanceSyncer] stake-accounts fetch failed:\", err);\n })\n .finally(() => {\n if (prevPublicKeyRef.current !== pkAtStart) return;\n setUserStakeAccountsLoading(false);\n });\n\n fetchBalances(connection, owner)\n .then((walletBals) => {\n if (prevPublicKeyRef.current !== pkAtStart) return;\n setWalletBalances(walletBals);\n writeCachedWalletBalances(pkAtStart, walletBals);\n })\n .catch((err) => {\n console.error(\"[BalanceSyncer] wallet-balances fetch failed:\", err);\n });\n\n fetchExchangeBalances(connection, owner, markets)\n .then((exchangeResult) => {\n if (prevPublicKeyRef.current !== pkAtStart) return;\n setExchangeBalances(exchangeResult.exchangeBalances);\n setOpenOrdersBalances(exchangeResult.openOrdersBalances);\n setSolBalances(exchangeResult.solBalances);\n setSolOpenOrdersBalances(exchangeResult.solOpenOrdersBalances);\n setOpenOrders(exchangeResult.openOrders);\n setPerMarketBaseBalances(exchangeResult.perMarketBaseBalances);\n })\n .catch((err) => {\n console.error(\"[BalanceSyncer] exchange-balances fetch failed:\", err);\n });\n\n intervalRef.current = setInterval(() => {\n if (prevPublicKeyRef.current !== pkAtStart) return;\n fetchUserStakeAccounts(connection, owner)\n .then((stakeAccounts) => {\n if (prevPublicKeyRef.current !== pkAtStart) return;\n setUserStakeAccounts(stakeAccounts);\n writeCachedStakeAccounts(pkAtStart, stakeAccounts);\n })\n .catch((err) => {\n console.error(\"[BalanceSyncer] stake-accounts poll failed:\", err);\n });\n fetchBalances(connection, owner)\n .then((walletBals) => {\n if (prevPublicKeyRef.current !== pkAtStart) return;\n setWalletBalances(walletBals);\n writeCachedWalletBalances(pkAtStart, walletBals);\n })\n .catch((err) => {\n console.error(\"[BalanceSyncer] wallet-balances poll failed:\", err);\n });\n fetchExchangeBalances(connection, owner, markets)\n .then((exchangeResult) => {\n if (prevPublicKeyRef.current !== pkAtStart) return;\n setExchangeBalances(exchangeResult.exchangeBalances);\n setOpenOrdersBalances(exchangeResult.openOrdersBalances);\n setSolBalances(exchangeResult.solBalances);\n setSolOpenOrdersBalances(exchangeResult.solOpenOrdersBalances);\n setOpenOrders(exchangeResult.openOrders);\n setPerMarketBaseBalances(exchangeResult.perMarketBaseBalances);\n })\n .catch((err) => {\n console.error(\"[BalanceSyncer] exchange-balances poll failed:\", err);\n });\n }, POLL_INTERVAL_MS);\n\n return () => {\n if (intervalRef.current) {\n clearInterval(intervalRef.current);\n intervalRef.current = null;\n }\n };\n }, [\n status,\n publicKey,\n connection,\n marketsRecord,\n setWalletBalances,\n setExchangeBalances,\n setOpenOrdersBalances,\n setSolBalances,\n setSolOpenOrdersBalances,\n setOpenOrders,\n setPerMarketBaseBalances,\n setUserStakeAccounts,\n setUserStakeAccountsLoading,\n resetBalances,\n ]);\n\n return null;\n}\n","import type { UserStakeAccount } from \"../stores/balance-store\";\n\nconst STORAGE_PREFIX = \"pye.stakeAccounts.v1.\";\nconst MAX_AGE_MS = 24 * 60 * 60 * 1000;\n\ninterface CachedPayload {\n timestamp: number;\n accounts: UserStakeAccount[];\n}\n\nfunction getStorage(): Storage | null {\n try {\n if (typeof window === \"undefined\") return null;\n return window.localStorage;\n } catch {\n return null;\n }\n}\n\nexport function readCachedStakeAccounts(\n publicKey: string,\n): UserStakeAccount[] | null {\n const storage = getStorage();\n if (!storage) return null;\n try {\n const raw = storage.getItem(STORAGE_PREFIX + publicKey);\n if (!raw) return null;\n const parsed = JSON.parse(raw) as CachedPayload;\n if (!parsed?.timestamp || !Array.isArray(parsed.accounts)) return null;\n if (Date.now() - parsed.timestamp > MAX_AGE_MS) return null;\n return parsed.accounts;\n } catch {\n return null;\n }\n}\n\nexport function writeCachedStakeAccounts(\n publicKey: string,\n accounts: UserStakeAccount[],\n): void {\n const storage = getStorage();\n if (!storage) return;\n try {\n const payload: CachedPayload = { timestamp: Date.now(), accounts };\n storage.setItem(STORAGE_PREFIX + publicKey, JSON.stringify(payload));\n } catch {\n // Silently ignore quota / serialization errors — cache is a perf hint, not correctness.\n }\n}\n","import { useEffect, useRef } from \"react\";\nimport { useWallet, useConnection } from \"@solana/wallet-adapter-react\";\nimport { address as toAddress } from \"@solana/kit\";\nimport { useWalletStore } from \"./providers\";\n\nfunction shortenAddress(address: string): string {\n return address.slice(0, 4) + \"...\" + address.slice(-4);\n}\n\n/**\n * Invisible component that syncs the Solana wallet adapter state into the\n * Zustand wallet store.\n */\nexport default function WalletSyncer() {\n const { publicKey, connected, connecting } = useWallet();\n const { connection } = useConnection();\n const fetchedKeyRef = useRef<string | null>(null);\n\n const setWalletStatus = useWalletStore((s) => s.setWalletStatus);\n const setWalletPublicKey = useWalletStore((s) => s.setWalletPublicKey);\n const setDisplayAddress = useWalletStore((s) => s.setDisplayAddress);\n const setBalanceLamports = useWalletStore((s) => s.setBalanceLamports);\n const setWalletInitialized = useWalletStore((s) => s.setWalletInitialized);\n const resetWallet = useWalletStore((s) => s.resetWallet);\n\n const fetchBalance = async (retries = 3) => {\n if (!publicKey || !connection) return;\n for (let i = 0; i < retries; i++) {\n try {\n const balance = await connection.getBalance(publicKey, \"confirmed\");\n console.log(\"[WalletSyncer] balanceLamports:\", balance);\n setBalanceLamports(balance);\n return;\n } catch {\n if (i < retries - 1) {\n await new Promise((r) => setTimeout(r, 1000 * (i + 1)));\n }\n }\n }\n console.warn(\"[WalletSyncer] balance fetch failed after all retries\");\n setBalanceLamports(null);\n };\n\n useEffect(() => {\n setWalletInitialized(true);\n\n if (connecting) {\n setWalletStatus(\"connecting\");\n } else if (connected && publicKey) {\n const base58 = publicKey.toBase58();\n if (fetchedKeyRef.current && fetchedKeyRef.current !== base58) {\n console.log(\"[WalletSyncer] wallet changed:\", fetchedKeyRef.current, \"→\", base58);\n }\n setWalletStatus(\"connected\");\n setWalletPublicKey(toAddress(base58));\n setDisplayAddress(shortenAddress(base58));\n if (fetchedKeyRef.current !== base58) {\n fetchedKeyRef.current = base58;\n fetchBalance();\n }\n } else {\n resetWallet();\n fetchedKeyRef.current = null;\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [connected, connecting, publicKey]);\n\n useEffect(() => {\n if (!connected || !publicKey) return;\n const interval = setInterval(() => fetchBalance(1), 30_000);\n return () => clearInterval(interval);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [connected, publicKey?.toBase58()]);\n\n useEffect(() => {\n if (!connected || !publicKey || !connection) return;\n const id = connection.onAccountChange(\n publicKey,\n (accountInfo) => setBalanceLamports(accountInfo.lamports),\n \"confirmed\",\n );\n return () => {\n connection.removeAccountChangeListener(id);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [connected, publicKey?.toBase58(), connection]);\n\n return null;\n}\n","import { useEffect } from \"react\";\nimport { createClient } from \"@supabase/supabase-js\";\nimport { useMarketStore } from \"./providers\";\nimport { parseOrderBook } from \"../lib/manifest-parser\";\nimport { getPyeConfig } from \"../config\";\n\n/**\n * Invisible component that:\n * 1. Fetches markets and RT backing on mount\n * 2. Polls RT backing every 60s\n * 3. Subscribes to Supabase Realtime for order book updates\n */\nexport default function MarketSyncer() {\n const fetchMarkets = useMarketStore((s) => s.fetchMarkets);\n const fetchRtBacking = useMarketStore((s) => s.fetchRtBacking);\n const updateMarketOrderBook = useMarketStore((s) => s.updateMarketOrderBook);\n const pubkeyIndex = useMarketStore((s) => s.pubkeyIndex);\n\n // Initial fetch\n useEffect(() => {\n fetchMarkets();\n fetchRtBacking();\n }, [fetchMarkets, fetchRtBacking]);\n\n // Re-poll rt_backing every 60s\n useEffect(() => {\n const interval = setInterval(() => {\n fetchRtBacking();\n }, 60_000);\n return () => clearInterval(interval);\n }, [fetchRtBacking]);\n\n // Supabase Realtime subscription for order book updates\n useEffect(() => {\n let config: ReturnType<typeof getPyeConfig>;\n try {\n config = getPyeConfig();\n } catch {\n return;\n }\n\n const supabase = createClient(config.supabaseUrl, config.supabaseAnonKey);\n\n const channel = supabase\n .channel(\"manifest-markets-changes\")\n .on(\n \"postgres_changes\",\n {\n event: \"UPDATE\",\n schema: \"public\",\n table: \"manifest_markets\",\n },\n (payload) => {\n const row = payload.new as { pubkey?: string; account_data?: string };\n if (!row.pubkey || !row.account_data) return;\n if (!pubkeyIndex[row.pubkey]) return;\n try {\n const summary = parseOrderBook(row.pubkey, row.account_data);\n updateMarketOrderBook(row.pubkey, summary);\n } catch (e) {\n console.error(\n `Realtime parse error for ${row.pubkey}:`,\n e instanceof Error ? e.message : e,\n );\n }\n },\n )\n .subscribe();\n\n return () => {\n supabase.removeChannel(channel);\n };\n }, [pubkeyIndex, updateMarketOrderBook]);\n\n return null;\n}\n","import { useEffect, useMemo } from \"react\";\nimport { useApyStore, useBalanceStore } from \"./providers\";\nimport { getPyeConfig } from \"../config\";\n\nconst POLL_INTERVAL_MS = 5 * 60 * 1000; // 5 minutes\n\n/**\n * Fetches staking APY from stakewiz_apy for relevant vote accounts.\n *\n * - Single-validator mode: fetches for the configured vote account on mount.\n * - Universal mode: fetches for vote accounts detected in the user's stake accounts.\n * - Polls every 5 minutes.\n */\nexport default function ApySyncer() {\n const fetchApyForVoteAccounts = useApyStore((s) => s.fetchApyForVoteAccounts);\n const userStakeAccounts = useBalanceStore((s) => s.userStakeAccounts);\n\n // Collect unique vote accounts from config + detected stake accounts\n const voteAccounts = useMemo(() => {\n const set = new Set<string>();\n const config = getPyeConfig();\n if (config.voteAccount) set.add(config.voteAccount);\n for (const sa of userStakeAccounts) {\n if (sa.validatorVoteAccount) set.add(sa.validatorVoteAccount);\n }\n return Array.from(set);\n }, [userStakeAccounts]);\n\n // Fetch whenever vote accounts change (new stake accounts detected)\n useEffect(() => {\n if (voteAccounts.length === 0) return;\n fetchApyForVoteAccounts(voteAccounts);\n }, [voteAccounts, fetchApyForVoteAccounts]);\n\n // Re-poll every 5 minutes (force refresh existing data)\n useEffect(() => {\n if (voteAccounts.length === 0) return;\n const interval = setInterval(() => {\n fetchApyForVoteAccounts(voteAccounts, true);\n }, POLL_INTERVAL_MS);\n return () => clearInterval(interval);\n }, [voteAccounts, fetchApyForVoteAccounts]);\n\n return null;\n}\n","import { useEffect } from \"react\";\nimport { useValidatorStore } from \"./providers\";\n\n/** Fetches validator_metadata_configs once on mount. */\nexport default function ValidatorSyncer() {\n const fetchAll = useValidatorStore((s) => s.fetchAll);\n useEffect(() => {\n fetchAll();\n }, [fetchAll]);\n return null;\n}\n","import { useEffect } from \"react\";\nimport { useLockupStore } from \"./providers\";\n\n/** Fetches canonical, visible bonds from solo_validator_bonds once on mount. */\nexport default function LockupSyncer() {\n const fetchAll = useLockupStore((s) => s.fetchAll);\n useEffect(() => {\n fetchAll();\n }, [fetchAll]);\n return null;\n}\n"],"mappings":"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","names":["useRef","useRef","useEffect","useRef","useConnection","useConnection","useRef","useEffect","useEffect","useEffect","useEffect","POLL_INTERVAL_MS","useEffect","useEffect","useEffect","useEffect","useEffect"]}
@@ -2,46 +2,6 @@ import * as immer from 'immer';
2
2
  import * as zustand_vanilla from 'zustand/vanilla';
3
3
  import { Address } from '@solana/kit';
4
4
 
5
- interface Validator {
6
- name: string;
7
- symbol: string;
8
- vote_account: string;
9
- pt_sol: string;
10
- rt_sol: string;
11
- is_allowed: boolean;
12
- type: "validator" | "lst";
13
- }
14
- type ValidatorId = "adrastea" | "alchemy" | "all-nodes" | "alpha-pro" | "anagram" | "anchorage-digital" | "anza" | "astralane" | "asymmetric" | "binance" | "bitwise" | "block-logic" | "blockdaemon" | "blockport" | "blocksize" | "bloxroute" | "blueshift" | "bonk" | "bybit" | "chainflow" | "chorus-one" | "coinbase" | "coyote-staking" | "dawnlabs" | "decentra" | "defi-dev-corp" | "drift" | "dsrv" | "edgevana" | "emory-blockchain" | "everstake" | "exo-tech" | "facilities" | "falconx" | "fd1" | "figment" | "forward-industries" | "galaxy" | "gate-omega" | "gemini" | "genco" | "global-stake" | "greed-academy" | "gripto" | "guardian" | "h2o-nodes" | "hashkey-cloud" | "haus" | "helius" | "hello-moon" | "hinode-tech" | "hubra" | "hylo" | "ice-staking" | "ily-validator" | "infinite-sol" | "jupiter" | "kairos-research" | "kiln" | "kraken" | "kumavalidator" | "laine" | "lakestake" | "lantern" | "ledger" | "luganodes" | "luminal" | "lumos-maxima" | "madlads" | "magic-eden" | "marginfi" | "meria" | "mesh-validator" | "monkedao" | "nansen" | "neodyme" | "nordic-staking" | "nova-consortium" | "okx-earn" | "omakase" | "orang3club" | "orangefin" | "ottersec" | "overclock" | "p-ops" | "p2p" | "parafi" | "phantom" | "phase-labs" | "pier-two" | "portals" | "project-catalyst" | "project-super" | "prostaking" | "pumpkins-pool" | "quicknode" | "radiants" | "rakurai" | "range" | "raposa" | "raydium" | "restake" | "rockaway-x" | "saga-dao" | "sec3" | "sendai" | "sensei-node" | "sentinel" | "shinobi" | "shiro" | "sol-rain-drops" | "sol-strategies" | "solana" | "solana-compass" | "solana-japan" | "solayer" | "solflare" | "solstack" | "solstice" | "solyrae" | "somos" | "squads-validator" | "stachenode" | "stakecraft" | "stakefish" | "stakely" | "stakin-the-tie" | "stakr-space" | "stardust" | "starke-finance" | "step-finance" | "stronghold" | "superfast" | "swyke" | "temporal" | "temporal-opal" | "the-vault" | "theia-capital" | "thw" | "tinydancer" | "triton-one" | "twinstake" | "txtx" | "unruggable" | "upbit-staking" | "valid-blocks" | "validation-cloud" | "valigator" | "vladika" | "vybe-network" | "watchtower" | "xandeum";
15
- declare const validators: {
16
- [key in ValidatorId]: Validator;
17
- };
18
- declare const ALLOWED_VALIDATORS: {
19
- name: string;
20
- symbol: string;
21
- vote_account: string;
22
- pt_sol: string;
23
- rt_sol: string;
24
- is_allowed: boolean;
25
- type: "validator" | "lst";
26
- id: ValidatorId;
27
- }[];
28
-
29
- interface Maturity {
30
- human_readable: string;
31
- month: string;
32
- year: string;
33
- issuance_start_timestamp: string;
34
- issuance_close_timestamp: string;
35
- maturity_timestamp: string;
36
- }
37
- type MaturityId = "q12026" | "q22026" | "q32026" | "q42026";
38
- declare const maturities: {
39
- [key in MaturityId]: Maturity;
40
- };
41
- declare const maturitiesArray: Maturity[];
42
- declare const maturityIdsArray: MaturityId[];
43
- declare const getMaturity: (maturityId: MaturityId) => Maturity;
44
-
45
5
  type WalletStatus = "disconnected" | "connecting" | "connected";
46
6
  interface WalletState {
47
7
  status: WalletStatus;
@@ -97,9 +57,9 @@ interface BalanceState {
97
57
  exchangeBalances: Balances;
98
58
  /** PT/RT open-orders balances keyed by mint address */
99
59
  openOrdersBalances: Balances;
100
- /** Per-market SOL (quote) withdrawable balances, keyed by "validatorId-maturityId-tokenType" */
60
+ /** Per-market SOL (quote) withdrawable balances, keyed by "voteAccount-canonicalLabel-tokenType" */
101
61
  solBalances: Balances;
102
- /** Per-market SOL (quote) open-orders balances, keyed by "validatorId-maturityId-tokenType" */
62
+ /** Per-market SOL (quote) open-orders balances, keyed by "voteAccount-canonicalLabel-tokenType" */
103
63
  solOpenOrdersBalances: Balances;
104
64
  /** Individual open orders for the connected trader */
105
65
  openOrders: OpenOrder[];
@@ -149,6 +109,50 @@ interface OrderBookSummary {
149
109
  */
150
110
  declare function parseOrderBook(marketPubkey: string, hexData: string): OrderBookSummary;
151
111
 
112
+ type CanonicalMaturity = "q12026" | "q22026" | "q32026" | "q42026";
113
+ /**
114
+ * Row from `solo_validator_bonds`. The widget only ever surfaces bonds with
115
+ * a non-null `canonical_label` — the partial unique index guarantees one
116
+ * bond per (validator, canonical_label) pair, so this is safe to key on.
117
+ */
118
+ interface BondRow {
119
+ pubkey: string;
120
+ validator_vote_account: string;
121
+ pt_mint: string;
122
+ rt_mint: string;
123
+ maturity_ts: number;
124
+ canonical_label: CanonicalMaturity;
125
+ is_hidden: boolean;
126
+ /** Only `standard = true` bonds may be swapped. Nullable in DB. */
127
+ standard: boolean | null;
128
+ }
129
+ interface LockupState {
130
+ /**
131
+ * Bonds keyed by `${validator_vote_account}:${canonical_label}`.
132
+ * One row per slot, by construction of the DB unique index.
133
+ */
134
+ bonds: Record<string, BondRow>;
135
+ loading: boolean;
136
+ lastFetched: number | null;
137
+ error: string | null;
138
+ }
139
+ interface LockupActions {
140
+ /**
141
+ * Fetch every visible, canonical bond. Filters applied server-side:
142
+ * `canonical_label IS NOT NULL` and `is_hidden = false`.
143
+ */
144
+ fetchAll: () => Promise<void>;
145
+ }
146
+ type LockupStore = LockupState & LockupActions;
147
+ declare function createLockupStore(): Omit<zustand_vanilla.StoreApi<LockupStore>, "setState"> & {
148
+ setState(nextStateOrUpdater: LockupStore | Partial<LockupStore> | ((state: immer.WritableDraft<LockupStore>) => void), shouldReplace?: false): void;
149
+ setState(nextStateOrUpdater: LockupStore | ((state: immer.WritableDraft<LockupStore>) => void), shouldReplace: true): void;
150
+ };
151
+ /** Selector: every bond for a given validator, sorted by maturity. */
152
+ declare function selectBondsForValidator(state: LockupState, votePubkey: string): BondRow[];
153
+ /** Selector: the bond for (validator, canonical_label), or null. */
154
+ declare function selectBond(state: LockupState, votePubkey: string, label: CanonicalMaturity): BondRow | null;
155
+
152
156
  interface ManifestMarketRecord {
153
157
  marketPubkey: string;
154
158
  bondPubkey: string;
@@ -167,9 +171,11 @@ interface ManifestMarketRecord {
167
171
  interface MatchedMarket {
168
172
  marketPubkey: string;
169
173
  bondPubkey: string;
170
- validatorId: ValidatorId;
171
- maturityId: MaturityId;
174
+ voteAccount: string;
175
+ canonicalLabel: CanonicalMaturity;
172
176
  tokenType: "PT" | "RT";
177
+ /** Mint address for this market's base token (PT or RT). */
178
+ mint: string;
173
179
  totalAskSize: number;
174
180
  bestAskPrice: number | null;
175
181
  totalBidSize: number;
@@ -180,16 +186,18 @@ interface MatchedMarket {
180
186
  bids: IndividualOrder[];
181
187
  }
182
188
  declare function fetchManifestMarkets(): Promise<MatchedMarket[]>;
183
- /** Build a lookup keyed by "validatorId-maturityId-PT/RT".
184
- * One market per key first match wins (no merging across markets). */
189
+ /**
190
+ * Build a lookup keyed by "${voteAccount}-${canonicalLabel}-${PT|RT}".
191
+ * One market per key — first match wins (no merging across markets).
192
+ */
185
193
  declare function buildMarketLookup(markets: MatchedMarket[]): Record<string, MatchedMarket>;
186
194
 
187
195
  interface MarketState {
188
- /** Lookup keyed by "validatorId-maturityId-PT/RT" */
196
+ /** Lookup keyed by "${voteAccount}-${canonicalLabel}-${PT|RT}" */
189
197
  markets: Record<string, MatchedMarket>;
190
198
  /** Reverse map: marketPubkey → store key */
191
199
  pubkeyIndex: Record<string, string>;
192
- /** RT backing per unit, keyed by bond pubkey */
200
+ /** RT backing per unit, keyed by bond pubkey. Populated by fetchRtBacking. */
193
201
  rtBacking: Record<string, number>;
194
202
  loading: boolean;
195
203
  lastFetched: number | null;
@@ -197,7 +205,7 @@ interface MarketState {
197
205
  interface MarketActions {
198
206
  fetchMarkets: () => Promise<void>;
199
207
  fetchRtBacking: () => Promise<void>;
200
- getMarket: (validatorId: string, maturityId: string, tokenType: "PT" | "RT") => MatchedMarket | null;
208
+ getMarket: (voteAccount: string, canonicalLabel: CanonicalMaturity, tokenType: "PT" | "RT") => MatchedMarket | null;
201
209
  updateMarketOrderBook: (marketPubkey: string, summary: OrderBookSummary) => void;
202
210
  }
203
211
  type MarketStore = MarketState & MarketActions;
@@ -222,4 +230,44 @@ declare function createApyStore(): Omit<zustand_vanilla.StoreApi<ApyStore>, "set
222
230
  setState(nextStateOrUpdater: ApyStore | ((state: immer.WritableDraft<ApyStore>) => void), shouldReplace: true): void;
223
231
  };
224
232
 
225
- export { ALLOWED_VALIDATORS as A, type BalanceActions as B, maturityIdsArray as C, parseOrderBook as D, validators as E, type IndividualOrder as I, type MaturityId as M, type OpenOrder as O, type StakeAccountState as S, type UserStakeAccount as U, type ValidatorId as V, type WalletActions as W, type MatchedMarket as a, type Maturity as b, type ApyActions as c, type ApyState as d, type ApyStore as e, type BalanceState as f, type BalanceStore as g, type Balances as h, type ManifestMarketRecord as i, type MarketActions as j, type MarketState as k, type MarketStore as l, type OrderBookSummary as m, type Validator as n, type WalletState as o, type WalletStatus as p, type WalletStore as q, buildMarketLookup as r, createApyStore as s, createBalanceStore as t, createMarketStore as u, createWalletStore as v, fetchManifestMarkets as w, getMaturity as x, maturities as y, maturitiesArray as z };
233
+ /**
234
+ * Row from `validator_metadata_configs`. The `widget` and `app` booleans are
235
+ * the allowlist gates — only validators with `widget = true` should be
236
+ * surfaced in the widget UI.
237
+ */
238
+ interface ValidatorRow {
239
+ vote_pubkey: string;
240
+ name: string;
241
+ symbol: string;
242
+ pt_image_url: string;
243
+ yt_image_url: string;
244
+ base_image_url: string | null;
245
+ alt_pubkey: string | null;
246
+ widget: boolean;
247
+ app: boolean;
248
+ }
249
+ interface ValidatorState {
250
+ /** All validators fetched, keyed by vote_pubkey. */
251
+ validators: Record<string, ValidatorRow>;
252
+ loading: boolean;
253
+ lastFetched: number | null;
254
+ error: string | null;
255
+ }
256
+ interface ValidatorActions {
257
+ /**
258
+ * Fetch every row in `validator_metadata_configs`. Caller filters by
259
+ * `widget = true` (or `app = true`) at the selector level.
260
+ */
261
+ fetchAll: () => Promise<void>;
262
+ }
263
+ type ValidatorStore = ValidatorState & ValidatorActions;
264
+ declare function createValidatorStore(): Omit<zustand_vanilla.StoreApi<ValidatorStore>, "setState"> & {
265
+ setState(nextStateOrUpdater: ValidatorStore | Partial<ValidatorStore> | ((state: immer.WritableDraft<ValidatorStore>) => void), shouldReplace?: false): void;
266
+ setState(nextStateOrUpdater: ValidatorStore | ((state: immer.WritableDraft<ValidatorStore>) => void), shouldReplace: true): void;
267
+ };
268
+ /** Selector helper: only rows where `widget = true`. */
269
+ declare function selectWidgetValidators(state: ValidatorState): ValidatorRow[];
270
+ /** Selector helper: single validator by vote_pubkey, only if `widget = true`. */
271
+ declare function selectWidgetValidator(state: ValidatorState, votePubkey: string): ValidatorRow | null;
272
+
273
+ export { type ApyActions as A, type Balances as B, type CanonicalMaturity as C, fetchManifestMarkets as D, parseOrderBook as E, selectBond as F, selectBondsForValidator as G, selectWidgetValidator as H, type IndividualOrder as I, selectWidgetValidators as J, type LockupActions as L, type MatchedMarket as M, type OpenOrder as O, type StakeAccountState as S, type UserStakeAccount as U, type ValidatorRow as V, type WalletActions as W, type BondRow as a, type ApyState as b, type ApyStore as c, type BalanceActions as d, type BalanceState as e, type BalanceStore as f, type LockupState as g, type LockupStore as h, type ManifestMarketRecord as i, type MarketActions as j, type MarketState as k, type MarketStore as l, type OrderBookSummary as m, type ValidatorActions as n, type ValidatorState as o, type ValidatorStore as p, type WalletState as q, type WalletStatus as r, type WalletStore as s, buildMarketLookup as t, createApyStore as u, createBalanceStore as v, createLockupStore as w, createMarketStore as x, createValidatorStore as y, createWalletStore as z };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pyefi/sdk",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "Core SDK for the Pye Finance Solana yield protocol — stores, data fetching, transaction execution.",
5
5
  "keywords": [
6
6
  "solana",
@@ -43,11 +43,6 @@
43
43
  "README.md",
44
44
  "LICENSE"
45
45
  ],
46
- "scripts": {
47
- "build": "tsup",
48
- "dev": "tsup --watch",
49
- "typecheck": "tsc --noEmit"
50
- },
51
46
  "dependencies": {
52
47
  "buffer": "^6.0.3",
53
48
  "zustand": "^5.0.0",
@@ -63,9 +58,15 @@
63
58
  "react": "^18.0.0 || ^19.0.0"
64
59
  },
65
60
  "peerDependenciesMeta": {
66
- "react": { "optional": true },
67
- "@solana/wallet-adapter-react": { "optional": true },
68
- "@supabase/supabase-js": { "optional": true }
61
+ "react": {
62
+ "optional": true
63
+ },
64
+ "@solana/wallet-adapter-react": {
65
+ "optional": true
66
+ },
67
+ "@supabase/supabase-js": {
68
+ "optional": true
69
+ }
69
70
  },
70
71
  "devDependencies": {
71
72
  "tsup": "^8.0.0",
@@ -78,5 +79,10 @@
78
79
  "@supabase/supabase-js": "^2.0.0",
79
80
  "@types/react": "^19.0.0",
80
81
  "react": "^19.0.0"
82
+ },
83
+ "scripts": {
84
+ "build": "tsup",
85
+ "dev": "tsup --watch",
86
+ "typecheck": "tsc --noEmit"
81
87
  }
82
- }
88
+ }