Remove duplicate connection to halve websockets, then only make websocket connections for things we mostly expect to care about. Come back later for further whittling.
This commit is contained in:
parent
434e1c5a11
commit
6847ae8975
|
@ -13,10 +13,8 @@ import { TokenAccount } from '../models';
|
||||||
import { chunks } from '../utils/utils';
|
import { chunks } from '../utils/utils';
|
||||||
import { EventEmitter } from '../utils/eventEmitter';
|
import { EventEmitter } from '../utils/eventEmitter';
|
||||||
import { useUserAccounts } from '../hooks/useUserAccounts';
|
import { useUserAccounts } from '../hooks/useUserAccounts';
|
||||||
import {
|
import { WRAPPED_SOL_MINT, programIds } from '../utils/ids';
|
||||||
WRAPPED_SOL_MINT,
|
import { AuctionParser } from '../actions';
|
||||||
programIds,
|
|
||||||
} from '../utils/ids';
|
|
||||||
|
|
||||||
const AccountsContext = React.createContext<any>(null);
|
const AccountsContext = React.createContext<any>(null);
|
||||||
|
|
||||||
|
@ -106,6 +104,8 @@ export const keyToAccountParser = new Map<string, AccountParser>();
|
||||||
|
|
||||||
export const cache = {
|
export const cache = {
|
||||||
emitter: new EventEmitter(),
|
emitter: new EventEmitter(),
|
||||||
|
totalSubs: 0,
|
||||||
|
totalObjects: 0,
|
||||||
query: async (
|
query: async (
|
||||||
connection: Connection,
|
connection: Connection,
|
||||||
pubKey: string | PublicKey,
|
pubKey: string | PublicKey,
|
||||||
|
@ -146,6 +146,7 @@ export const cache = {
|
||||||
id: PublicKey | string,
|
id: PublicKey | string,
|
||||||
obj: AccountInfo<Buffer>,
|
obj: AccountInfo<Buffer>,
|
||||||
parser?: AccountParser,
|
parser?: AccountParser,
|
||||||
|
isEligibleForSub?: boolean | undefined | ((parsed: any) => boolean),
|
||||||
) => {
|
) => {
|
||||||
if (obj.data.length === 0) {
|
if (obj.data.length === 0) {
|
||||||
return;
|
return;
|
||||||
|
@ -166,10 +167,19 @@ export const cache = {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isEligibleForSub == undefined) isEligibleForSub = true;
|
||||||
|
else if (isEligibleForSub instanceof Function)
|
||||||
|
isEligibleForSub = isEligibleForSub(account);
|
||||||
|
|
||||||
const isNew = !genericCache.has(address);
|
const isNew = !genericCache.has(address);
|
||||||
|
|
||||||
genericCache.set(address, account);
|
genericCache.set(address, account);
|
||||||
cache.emitter.raiseCacheUpdated(address, isNew, deserialize);
|
cache.emitter.raiseCacheUpdated(
|
||||||
|
address,
|
||||||
|
isNew,
|
||||||
|
deserialize,
|
||||||
|
isEligibleForSub,
|
||||||
|
);
|
||||||
return account;
|
return account;
|
||||||
},
|
},
|
||||||
get: (pubKey: string | PublicKey) => {
|
get: (pubKey: string | PublicKey) => {
|
||||||
|
@ -320,7 +330,7 @@ const UseNativeAccount = () => {
|
||||||
const id = wallet.publicKey?.toBase58();
|
const id = wallet.publicKey?.toBase58();
|
||||||
cache.registerParser(id, TokenAccountParser);
|
cache.registerParser(id, TokenAccountParser);
|
||||||
genericCache.set(id, wrapped as TokenAccount);
|
genericCache.set(id, wrapped as TokenAccount);
|
||||||
cache.emitter.raiseCacheUpdated(id, false, TokenAccountParser);
|
cache.emitter.raiseCacheUpdated(id, false, TokenAccountParser, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -341,7 +351,7 @@ const UseNativeAccount = () => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const account = await connection.getAccountInfo(wallet.publicKey)
|
const account = await connection.getAccountInfo(wallet.publicKey);
|
||||||
updateAccount(account);
|
updateAccount(account);
|
||||||
|
|
||||||
subId = connection.onAccountChange(wallet.publicKey, updateAccount);
|
subId = connection.onAccountChange(wallet.publicKey, updateAccount);
|
||||||
|
@ -351,7 +361,7 @@ const UseNativeAccount = () => {
|
||||||
if (subId) {
|
if (subId) {
|
||||||
connection.removeAccountChangeListener(subId);
|
connection.removeAccountChangeListener(subId);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}, [setNativeAccount, wallet, wallet?.publicKey, connection, updateCache]);
|
}, [setNativeAccount, wallet, wallet?.publicKey, connection, updateCache]);
|
||||||
|
|
||||||
return { nativeAccount };
|
return { nativeAccount };
|
||||||
|
@ -405,7 +415,10 @@ export function AccountsProvider({ children = null as any }) {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const subs: number[] = [];
|
const subs: number[] = [];
|
||||||
cache.emitter.onCache(args => {
|
cache.emitter.onCache(args => {
|
||||||
if (args.isNew) {
|
cache.totalObjects += 1;
|
||||||
|
|
||||||
|
if (args.isNew && args.isEligibleForSub) {
|
||||||
|
cache.totalSubs += 1;
|
||||||
let id = args.id;
|
let id = args.id;
|
||||||
let deserialize = args.parser;
|
let deserialize = args.parser;
|
||||||
connection.onAccountChange(new PublicKey(id), info => {
|
connection.onAccountChange(new PublicKey(id), info => {
|
||||||
|
@ -435,7 +448,7 @@ export function AccountsProvider({ children = null as any }) {
|
||||||
programIds().token,
|
programIds().token,
|
||||||
info => {
|
info => {
|
||||||
// TODO: fix type in web3.js
|
// TODO: fix type in web3.js
|
||||||
const id = (info.accountId as unknown) as string;
|
const id = info.accountId as unknown as string;
|
||||||
// TODO: do we need a better way to identify layout (maybe a enum identifing type?)
|
// TODO: do we need a better way to identify layout (maybe a enum identifing type?)
|
||||||
if (info.accountInfo.data.length === AccountLayout.span) {
|
if (info.accountInfo.data.length === AccountLayout.span) {
|
||||||
const data = deserializeAccount(info.accountInfo.data);
|
const data = deserializeAccount(info.accountInfo.data);
|
||||||
|
|
|
@ -63,7 +63,6 @@ const DEFAULT = ENDPOINTS[0].endpoint;
|
||||||
|
|
||||||
interface ConnectionConfig {
|
interface ConnectionConfig {
|
||||||
connection: Connection;
|
connection: Connection;
|
||||||
sendConnection: Connection;
|
|
||||||
endpoint: string;
|
endpoint: string;
|
||||||
env: ENV;
|
env: ENV;
|
||||||
setEndpoint: (val: string) => void;
|
setEndpoint: (val: string) => void;
|
||||||
|
@ -75,7 +74,6 @@ const ConnectionContext = React.createContext<ConnectionConfig>({
|
||||||
endpoint: DEFAULT,
|
endpoint: DEFAULT,
|
||||||
setEndpoint: () => {},
|
setEndpoint: () => {},
|
||||||
connection: new Connection(DEFAULT, 'recent'),
|
connection: new Connection(DEFAULT, 'recent'),
|
||||||
sendConnection: new Connection(DEFAULT, 'recent'),
|
|
||||||
env: ENDPOINTS[0].name,
|
env: ENDPOINTS[0].name,
|
||||||
tokens: [],
|
tokens: [],
|
||||||
tokenMap: new Map<string, TokenInfo>(),
|
tokenMap: new Map<string, TokenInfo>(),
|
||||||
|
@ -91,10 +89,6 @@ export function ConnectionProvider({ children = undefined as any }) {
|
||||||
() => new Connection(endpoint, 'recent'),
|
() => new Connection(endpoint, 'recent'),
|
||||||
[endpoint],
|
[endpoint],
|
||||||
);
|
);
|
||||||
const sendConnection = useMemo(
|
|
||||||
() => new Connection(endpoint, 'recent'),
|
|
||||||
[endpoint],
|
|
||||||
);
|
|
||||||
|
|
||||||
const env =
|
const env =
|
||||||
ENDPOINTS.find(end => end.endpoint === endpoint)?.name || ENDPOINTS[0].name;
|
ENDPOINTS.find(end => end.endpoint === endpoint)?.name || ENDPOINTS[0].name;
|
||||||
|
@ -144,30 +138,12 @@ export function ConnectionProvider({ children = undefined as any }) {
|
||||||
};
|
};
|
||||||
}, [connection]);
|
}, [connection]);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const id = sendConnection.onAccountChange(
|
|
||||||
Keypair.generate().publicKey,
|
|
||||||
() => {},
|
|
||||||
);
|
|
||||||
return () => {
|
|
||||||
sendConnection.removeAccountChangeListener(id);
|
|
||||||
};
|
|
||||||
}, [sendConnection]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const id = sendConnection.onSlotChange(() => null);
|
|
||||||
return () => {
|
|
||||||
sendConnection.removeSlotChangeListener(id);
|
|
||||||
};
|
|
||||||
}, [sendConnection]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ConnectionContext.Provider
|
<ConnectionContext.Provider
|
||||||
value={{
|
value={{
|
||||||
endpoint,
|
endpoint,
|
||||||
setEndpoint,
|
setEndpoint,
|
||||||
connection,
|
connection,
|
||||||
sendConnection,
|
|
||||||
tokens,
|
tokens,
|
||||||
tokenMap,
|
tokenMap,
|
||||||
env,
|
env,
|
||||||
|
@ -182,10 +158,6 @@ export function useConnection() {
|
||||||
return useContext(ConnectionContext).connection as Connection;
|
return useContext(ConnectionContext).connection as Connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useSendConnection() {
|
|
||||||
return useContext(ConnectionContext)?.sendConnection;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useConnectionConfig() {
|
export function useConnectionConfig() {
|
||||||
const context = useContext(ConnectionContext);
|
const context = useContext(ConnectionContext);
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -5,10 +5,17 @@ export class CacheUpdateEvent {
|
||||||
id: string;
|
id: string;
|
||||||
parser: any;
|
parser: any;
|
||||||
isNew: boolean;
|
isNew: boolean;
|
||||||
constructor(id: string, isNew: boolean, parser: any) {
|
isEligibleForSub: boolean;
|
||||||
|
constructor(
|
||||||
|
id: string,
|
||||||
|
isNew: boolean,
|
||||||
|
parser: any,
|
||||||
|
isEligibleForSub: boolean,
|
||||||
|
) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.parser = parser;
|
this.parser = parser;
|
||||||
this.isNew = isNew;
|
this.isNew = isNew;
|
||||||
|
this.isEligibleForSub = isEligibleForSub;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,10 +54,15 @@ export class EventEmitter {
|
||||||
this.emitter.emit(MarketUpdateEvent.type, new MarketUpdateEvent(ids));
|
this.emitter.emit(MarketUpdateEvent.type, new MarketUpdateEvent(ids));
|
||||||
}
|
}
|
||||||
|
|
||||||
raiseCacheUpdated(id: string, isNew: boolean, parser: any) {
|
raiseCacheUpdated(
|
||||||
|
id: string,
|
||||||
|
isNew: boolean,
|
||||||
|
parser: any,
|
||||||
|
isEligibleForSub: boolean,
|
||||||
|
) {
|
||||||
this.emitter.emit(
|
this.emitter.emit(
|
||||||
CacheUpdateEvent.type,
|
CacheUpdateEvent.type,
|
||||||
new CacheUpdateEvent(id, isNew, parser),
|
new CacheUpdateEvent(id, isNew, parser, isEligibleForSub),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,9 @@ import {
|
||||||
Vault,
|
Vault,
|
||||||
setProgramIds,
|
setProgramIds,
|
||||||
useConnectionConfig,
|
useConnectionConfig,
|
||||||
|
useWallet,
|
||||||
|
walletAdapters,
|
||||||
|
AuctionState,
|
||||||
} from '@oyster/common';
|
} from '@oyster/common';
|
||||||
import { MintInfo } from '@solana/spl-token';
|
import { MintInfo } from '@solana/spl-token';
|
||||||
import { Connection, PublicKey, PublicKeyAndAccount } from '@solana/web3.js';
|
import { Connection, PublicKey, PublicKeyAndAccount } from '@solana/web3.js';
|
||||||
|
@ -112,6 +115,7 @@ const MetaContext = React.createContext<MetaContextState>({
|
||||||
|
|
||||||
export function MetaProvider({ children = null as any }) {
|
export function MetaProvider({ children = null as any }) {
|
||||||
const connection = useConnection();
|
const connection = useConnection();
|
||||||
|
const { wallet } = useWallet();
|
||||||
const { env } = useConnectionConfig();
|
const { env } = useConnectionConfig();
|
||||||
|
|
||||||
const [metadata, setMetadata] = useState<ParsedAccount<Metadata>[]>([]);
|
const [metadata, setMetadata] = useState<ParsedAccount<Metadata>[]>([]);
|
||||||
|
@ -226,6 +230,7 @@ export function MetaProvider({ children = null as any }) {
|
||||||
|
|
||||||
processAuctions(
|
processAuctions(
|
||||||
accounts[i],
|
accounts[i],
|
||||||
|
wallet,
|
||||||
(cb: any) => (tempCache.auctions = cb(tempCache.auctions)),
|
(cb: any) => (tempCache.auctions = cb(tempCache.auctions)),
|
||||||
(cb: any) =>
|
(cb: any) =>
|
||||||
(tempCache.bidderMetadataByAuctionAndBidder = cb(
|
(tempCache.bidderMetadataByAuctionAndBidder = cb(
|
||||||
|
@ -327,6 +332,7 @@ export function MetaProvider({ children = null as any }) {
|
||||||
setWhitelistedCreatorsByCreator,
|
setWhitelistedCreatorsByCreator,
|
||||||
updateMints,
|
updateMints,
|
||||||
env,
|
env,
|
||||||
|
wallet,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -408,6 +414,7 @@ export function MetaProvider({ children = null as any }) {
|
||||||
pubkey,
|
pubkey,
|
||||||
account: info.accountInfo,
|
account: info.accountInfo,
|
||||||
},
|
},
|
||||||
|
wallet,
|
||||||
setAuctions,
|
setAuctions,
|
||||||
setBidderMetadataByAuctionAndBidder,
|
setBidderMetadataByAuctionAndBidder,
|
||||||
setBidderPotsByAuctionAndBidder,
|
setBidderPotsByAuctionAndBidder,
|
||||||
|
@ -537,6 +544,7 @@ const queryExtendedMetadata = async (
|
||||||
key,
|
key,
|
||||||
mintAccount,
|
mintAccount,
|
||||||
MintParser,
|
MintParser,
|
||||||
|
false,
|
||||||
) as ParsedAccount<MintInfo>;
|
) as ParsedAccount<MintInfo>;
|
||||||
if (mint.info.supply.gt(new BN(1)) || mint.info.decimals !== 0) {
|
if (mint.info.supply.gt(new BN(1)) || mint.info.decimals !== 0) {
|
||||||
// naive not NFT check
|
// naive not NFT check
|
||||||
|
@ -576,6 +584,7 @@ function isValidHttpUrl(text: string) {
|
||||||
|
|
||||||
const processAuctions = (
|
const processAuctions = (
|
||||||
a: PublicKeyAndAccount<Buffer>,
|
a: PublicKeyAndAccount<Buffer>,
|
||||||
|
wallet: any,
|
||||||
setAuctions: any,
|
setAuctions: any,
|
||||||
setBidderMetadataByAuctionAndBidder: any,
|
setBidderMetadataByAuctionAndBidder: any,
|
||||||
setBidderPotsByAuctionAndBidder: any,
|
setBidderPotsByAuctionAndBidder: any,
|
||||||
|
@ -587,6 +596,7 @@ const processAuctions = (
|
||||||
a.pubkey,
|
a.pubkey,
|
||||||
a.account,
|
a.account,
|
||||||
AuctionParser,
|
AuctionParser,
|
||||||
|
(auction: ParsedAccount<AuctionData>) => !auction.info.ended(),
|
||||||
) as ParsedAccount<AuctionData>;
|
) as ParsedAccount<AuctionData>;
|
||||||
|
|
||||||
setAuctions((e: any) => ({
|
setAuctions((e: any) => ({
|
||||||
|
@ -603,6 +613,8 @@ const processAuctions = (
|
||||||
a.pubkey,
|
a.pubkey,
|
||||||
a.account,
|
a.account,
|
||||||
BidderMetadataParser,
|
BidderMetadataParser,
|
||||||
|
(parsed: ParsedAccount<BidderMetadata>) =>
|
||||||
|
parsed.info.bidderPubkey.toBase58() == wallet.publicKey.toBase58(),
|
||||||
) as ParsedAccount<BidderMetadata>;
|
) as ParsedAccount<BidderMetadata>;
|
||||||
setBidderMetadataByAuctionAndBidder((e: any) => ({
|
setBidderMetadataByAuctionAndBidder((e: any) => ({
|
||||||
...e,
|
...e,
|
||||||
|
@ -621,6 +633,8 @@ const processAuctions = (
|
||||||
a.pubkey,
|
a.pubkey,
|
||||||
a.account,
|
a.account,
|
||||||
BidderPotParser,
|
BidderPotParser,
|
||||||
|
(parsed: ParsedAccount<BidderPot>) =>
|
||||||
|
parsed.info.bidderAct.toBase58() == wallet.publicKey.toBase58(),
|
||||||
) as ParsedAccount<BidderPot>;
|
) as ParsedAccount<BidderPot>;
|
||||||
|
|
||||||
setBidderPotsByAuctionAndBidder((e: any) => ({
|
setBidderPotsByAuctionAndBidder((e: any) => ({
|
||||||
|
@ -714,6 +728,7 @@ const processMetaplexAccounts = async (
|
||||||
a.pubkey,
|
a.pubkey,
|
||||||
a.account,
|
a.account,
|
||||||
WhitelistedCreatorParser,
|
WhitelistedCreatorParser,
|
||||||
|
true,
|
||||||
) as ParsedAccount<WhitelistedCreator>;
|
) as ParsedAccount<WhitelistedCreator>;
|
||||||
|
|
||||||
const nameInfo = (names as any)[account.info.address.toBase58()];
|
const nameInfo = (names as any)[account.info.address.toBase58()];
|
||||||
|
|
Loading…
Reference in New Issue