mirror of https://github.com/certusone/oyster.git
fix: account subscription
This commit is contained in:
parent
c9b20ed09b
commit
6b2373aebe
|
@ -111,7 +111,7 @@ export const borrow = async (
|
|||
}
|
||||
|
||||
notify({
|
||||
message: "Adding Liquidity...",
|
||||
message: "Borrowing funds...",
|
||||
description: "Please review transactions to approve.",
|
||||
type: "warn",
|
||||
});
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useCallback, useContext, useEffect, useState } from "react";
|
||||
import React, { useCallback, useContext, useEffect, useMemo, useState } from "react";
|
||||
import { useConnection } from "./connection";
|
||||
import { useWallet } from "./wallet";
|
||||
import { AccountInfo, Connection, PublicKey } from "@solana/web3.js";
|
||||
|
@ -7,11 +7,10 @@ import { AccountLayout, u64, MintInfo, MintLayout } from "@solana/spl-token";
|
|||
import { TokenAccount } from "./../models";
|
||||
import { chunks } from "./../utils/utils";
|
||||
import { EventEmitter } from "./../utils/eventEmitter";
|
||||
import { TokenClass } from "typescript";
|
||||
|
||||
const AccountsContext = React.createContext<any>(null);
|
||||
|
||||
const accountEmitter = new EventEmitter();
|
||||
|
||||
const pendingCalls = new Map<string, Promise<ParsedAccountBase>>();
|
||||
const genericCache = new Map<string, ParsedAccountBase>();
|
||||
|
||||
|
@ -141,8 +140,10 @@ export const cache = {
|
|||
return;
|
||||
}
|
||||
|
||||
const isNew = !genericCache.has(address);
|
||||
|
||||
genericCache.set(address, account);
|
||||
cache.emitter.raiseCacheUpdated(address, deserialize);
|
||||
cache.emitter.raiseCacheUpdated(address, isNew, deserialize);
|
||||
return account;
|
||||
},
|
||||
get: (pubKey: string | PublicKey) => {
|
||||
|
@ -217,8 +218,10 @@ const UseNativeAccount = () => {
|
|||
(account) => {
|
||||
const wrapped = wrapNativeAccount(wallet.publicKey, account);
|
||||
if (wrapped !== undefined && wallet) {
|
||||
cache.registerParser(wallet.publicKey?.toBase58(), TokenAccountParser);
|
||||
genericCache.set(wallet.publicKey?.toBase58(), wrapped as TokenAccount);
|
||||
const id = wallet.publicKey?.toBase58();
|
||||
cache.registerParser(id, TokenAccountParser);
|
||||
genericCache.set(id, wrapped as TokenAccount);
|
||||
cache.emitter.raiseCacheUpdated(id, false, TokenAccountParser);
|
||||
}
|
||||
},
|
||||
[wallet]
|
||||
|
@ -291,6 +294,23 @@ export function AccountsProvider({ children = null as any }) {
|
|||
setUserAccounts(accounts);
|
||||
}, [nativeAccount, wallet, tokenAccounts, selectUserAccounts]);
|
||||
|
||||
useEffect(() => {
|
||||
const subs: number[] = [];
|
||||
cache.emitter.onCache((args) => {
|
||||
if(args.isNew) {
|
||||
let id = args.id;
|
||||
let deserialize = args.parser;
|
||||
connection.onAccountChange(new PublicKey(id), (info) => {
|
||||
cache.add(id, info, deserialize);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return () => {
|
||||
subs.forEach(id => connection.removeAccountChangeListener(id));
|
||||
}
|
||||
}, [connection]);
|
||||
|
||||
const publicKey = wallet?.publicKey;
|
||||
useEffect(() => {
|
||||
if (!connection || !publicKey) {
|
||||
|
@ -301,7 +321,8 @@ export function AccountsProvider({ children = null as any }) {
|
|||
});
|
||||
|
||||
// This can return different types of accounts: token-account, mint, multisig
|
||||
// TODO: web3.js expose ability to filter. discuss filter syntax
|
||||
// TODO: web3.js expose ability to filter.
|
||||
// this should use only filter syntax to only get accounts that are owned by user
|
||||
const tokenSubID = connection.onProgramAccountChange(
|
||||
programIds().token,
|
||||
(info) => {
|
||||
|
@ -311,22 +332,10 @@ export function AccountsProvider({ children = null as any }) {
|
|||
if (info.accountInfo.data.length === AccountLayout.span) {
|
||||
const data = deserializeAccount(info.accountInfo.data);
|
||||
|
||||
if (PRECACHED_OWNERS.has(data.owner.toBase58()) || cache.get(id)) {
|
||||
if (PRECACHED_OWNERS.has(data.owner.toBase58())) {
|
||||
cache.add(id, info.accountInfo, TokenAccountParser);
|
||||
setTokenAccounts(selectUserAccounts());
|
||||
accountEmitter.raiseAccountUpdated(id);
|
||||
}
|
||||
} else if (info.accountInfo.data.length === MintLayout.span) {
|
||||
if (cache.get(id)) {
|
||||
cache.add(id, info.accountInfo, MintParser);
|
||||
accountEmitter.raiseAccountUpdated(id);
|
||||
}
|
||||
|
||||
accountEmitter.raiseAccountUpdated(id);
|
||||
}
|
||||
|
||||
if (genericCache.has(id)) {
|
||||
cache.add(new PublicKey(id), info.accountInfo);
|
||||
}
|
||||
},
|
||||
"singleGossip"
|
||||
|
|
|
@ -1,20 +1,14 @@
|
|||
import { EventEmitter as Emitter } from "eventemitter3";
|
||||
|
||||
export class AccountUpdateEvent {
|
||||
static type = "AccountUpdate";
|
||||
id: string;
|
||||
constructor(id: string) {
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
export class CacheUpdateEvent {
|
||||
static type = "CacheUpdate";
|
||||
id: string;
|
||||
parser: any;
|
||||
constructor(id: string, parser: any) {
|
||||
isNew: boolean;
|
||||
constructor(id: string, isNew: boolean, parser: any) {
|
||||
this.id = id;
|
||||
this.parser = parser;
|
||||
this.isNew = isNew;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,27 +29,17 @@ export class EventEmitter {
|
|||
return () => this.emitter.removeListener(MarketUpdateEvent.type, callback);
|
||||
}
|
||||
|
||||
onAccount(callback: (args: AccountUpdateEvent) => void) {
|
||||
this.emitter.on(AccountUpdateEvent.type, callback);
|
||||
|
||||
return () => this.emitter.removeListener(AccountUpdateEvent.type, callback);
|
||||
}
|
||||
|
||||
onCache(callback: (args: CacheUpdateEvent) => void) {
|
||||
this.emitter.on(CacheUpdateEvent.type, callback);
|
||||
|
||||
return () => this.emitter.removeListener(CacheUpdateEvent.type, callback);
|
||||
}
|
||||
|
||||
raiseAccountUpdated(id: string) {
|
||||
this.emitter.emit(AccountUpdateEvent.type, new AccountUpdateEvent(id));
|
||||
}
|
||||
|
||||
raiseMarketUpdated(ids: Set<string>) {
|
||||
this.emitter.emit(MarketUpdateEvent.type, new MarketUpdateEvent(ids));
|
||||
}
|
||||
|
||||
raiseCacheUpdated(id: string, parser: any) {
|
||||
this.emitter.emit(CacheUpdateEvent.type, new CacheUpdateEvent(id, parser));
|
||||
raiseCacheUpdated(id: string, isNew: boolean, parser: any) {
|
||||
this.emitter.emit(CacheUpdateEvent.type, new CacheUpdateEvent(id, isNew, parser));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue