@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/{chunk-62OCHHT7.js → chunk-GXXXUTDQ.js} +204 -81
- package/dist/chunk-GXXXUTDQ.js.map +1 -0
- package/dist/index.d.ts +88 -3
- package/dist/index.js +114 -3
- package/dist/index.js.map +1 -1
- package/dist/react.d.ts +16 -2
- package/dist/react.js +72 -6
- package/dist/react.js.map +1 -1
- package/dist/{apy-store-CNq9A4Xc.d.ts → validator-store-CirN3_Ac.d.ts} +98 -50
- package/package.json +16 -10
- package/dist/chunk-62OCHHT7.js.map +0 -1
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
|
-
|
|
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
|
|
157
|
-
if (
|
|
158
|
-
setUserStakeAccounts(
|
|
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 "
|
|
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 "
|
|
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
|
-
|
|
171
|
-
|
|
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
|
-
/**
|
|
184
|
-
*
|
|
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 "
|
|
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: (
|
|
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
|
-
|
|
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.
|
|
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": {
|
|
67
|
-
|
|
68
|
-
|
|
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
|
+
}
|