update wallet balance from websocket
This commit is contained in:
parent
944a44403b
commit
b40aed3885
|
@ -12,13 +12,13 @@ const Balances = () => {
|
||||||
return quotient.toNumber() + remainder.toNumber() / divisor.toNumber()
|
return quotient.toNumber() + remainder.toNumber() / divisor.toNumber()
|
||||||
}
|
}
|
||||||
|
|
||||||
function calculateBalance(a) {
|
function calculateBalance(acc) {
|
||||||
const mint = mints[a.account.mint.toBase58()]
|
const mint = mints[acc.mint.toBase58()]
|
||||||
return mint ? fixedPointToNumber(a.account.amount, mint.decimals) : 0
|
return mint ? fixedPointToNumber(acc.amount, mint.decimals) : 0
|
||||||
}
|
}
|
||||||
|
|
||||||
const displayedBalances = tokenAccounts
|
const displayedBalances = Object.entries(tokenAccounts)
|
||||||
.map((a) => ({ id: a.publicKey.toBase58(), balance: calculateBalance(a) }))
|
.map(([id, acc]) => ({ id, balance: calculateBalance(acc) }))
|
||||||
.sort((a, b) => (a.id > b.id ? 1 : -1))
|
.sort((a, b) => (a.id > b.id ? 1 : -1))
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -127,9 +127,8 @@ export default function useWallet() {
|
||||||
}, [wallet, setWalletStore])
|
}, [wallet, setWalletStore])
|
||||||
|
|
||||||
useInterval(async () => {
|
useInterval(async () => {
|
||||||
await actions.fetchWalletTokenAccounts()
|
|
||||||
await actions.fetchWalletMints()
|
await actions.fetchWalletMints()
|
||||||
}, 20 * SECONDS)
|
}, 120 * SECONDS)
|
||||||
|
|
||||||
return { connected, wallet }
|
return { connected, wallet }
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { EndpointInfo, WalletAdapter } from '../@types/types'
|
||||||
import {
|
import {
|
||||||
getOwnedTokenAccounts,
|
getOwnedTokenAccounts,
|
||||||
getMint,
|
getMint,
|
||||||
ProgramAccount,
|
subscribeToTokenAccount,
|
||||||
TokenAccount,
|
TokenAccount,
|
||||||
MintAccount,
|
MintAccount,
|
||||||
} from '../utils/tokens'
|
} from '../utils/tokens'
|
||||||
|
@ -39,8 +39,9 @@ interface WalletStore extends State {
|
||||||
}
|
}
|
||||||
current: WalletAdapter | undefined
|
current: WalletAdapter | undefined
|
||||||
providerUrl: string
|
providerUrl: string
|
||||||
tokenAccounts: ProgramAccount<TokenAccount>[]
|
tokenAccounts: { [pubkey: string]: TokenAccount }
|
||||||
mints: { [pubkey: string]: MintAccount }
|
mints: { [pubkey: string]: MintAccount }
|
||||||
|
subscriptions: { [pubkey: string]: () => void }
|
||||||
set: (x: any) => void
|
set: (x: any) => void
|
||||||
actions: any
|
actions: any
|
||||||
}
|
}
|
||||||
|
@ -55,28 +56,43 @@ const useWalletStore = create<WalletStore>((set, get) => ({
|
||||||
},
|
},
|
||||||
current: null,
|
current: null,
|
||||||
providerUrl: null,
|
providerUrl: null,
|
||||||
tokenAccounts: [],
|
tokenAccounts: {},
|
||||||
mints: {},
|
mints: {},
|
||||||
|
subscriptions: {},
|
||||||
actions: {
|
actions: {
|
||||||
async fetchWalletTokenAccounts() {
|
async fetchWalletTokenAccounts() {
|
||||||
const connection = get().connection.current
|
const connection = get().connection.current
|
||||||
const connected = get().connected
|
const connected = get().connected
|
||||||
|
const subscriptions = get().subscriptions
|
||||||
const wallet = get().current
|
const wallet = get().current
|
||||||
const walletOwner = wallet?.publicKey
|
const walletOwner = wallet?.publicKey
|
||||||
const set = get().set
|
const set = get().set
|
||||||
|
|
||||||
if (connected && walletOwner) {
|
if (connected && walletOwner) {
|
||||||
const ownedTokenAccounts = await getOwnedTokenAccounts(
|
const ownedAccountsResult = await getOwnedTokenAccounts(
|
||||||
connection,
|
connection,
|
||||||
walletOwner
|
walletOwner
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const newTokenAccounts: { [pubkey: string]: TokenAccount } = {}
|
||||||
|
ownedAccountsResult.forEach((r) => {
|
||||||
|
newTokenAccounts[r.publicKey.toBase58()] = r.account
|
||||||
|
})
|
||||||
|
|
||||||
|
// cancel all subscriptions
|
||||||
|
Object.values(subscriptions).forEach((s) => s())
|
||||||
|
|
||||||
set((state) => {
|
set((state) => {
|
||||||
state.tokenAccounts = ownedTokenAccounts
|
state.subscriptions = {}
|
||||||
|
state.tokenAccounts = newTokenAccounts
|
||||||
|
})
|
||||||
|
|
||||||
|
ownedAccountsResult.forEach((r) => {
|
||||||
|
this.subscribeToTokenAccount(r.publicKey)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
set((state) => {
|
set((state) => {
|
||||||
state.tokenAccounts = []
|
state.tokenAccounts = {}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -87,14 +103,14 @@ const useWalletStore = create<WalletStore>((set, get) => ({
|
||||||
const set = get().set
|
const set = get().set
|
||||||
|
|
||||||
if (connected) {
|
if (connected) {
|
||||||
const fetchMints = tokenAccounts.map((a) =>
|
const fetchMints = Object.values(tokenAccounts).map((a) =>
|
||||||
getMint(connection, a.account.mint)
|
getMint(connection, a.mint)
|
||||||
)
|
)
|
||||||
const mintResults = await Promise.all(fetchMints)
|
const mintResults = await Promise.all(fetchMints)
|
||||||
|
|
||||||
const newMints: { [pubkey: string]: MintAccount } = {}
|
const newMints: { [pubkey: string]: MintAccount } = {}
|
||||||
mintResults.forEach(
|
mintResults.forEach(
|
||||||
(m) => (newMints[m.publicKey.toBase58()] = m.account)
|
(r) => (newMints[r.publicKey.toBase58()] = r.account)
|
||||||
)
|
)
|
||||||
|
|
||||||
set((state) => {
|
set((state) => {
|
||||||
|
@ -106,6 +122,23 @@ const useWalletStore = create<WalletStore>((set, get) => ({
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
async subscribeToTokenAccount(pubkey) {
|
||||||
|
const connection = get().connection.websocket
|
||||||
|
const connected = get().connected
|
||||||
|
const set = get().set
|
||||||
|
|
||||||
|
if (connected) {
|
||||||
|
const sub = subscribeToTokenAccount(connection, pubkey, (r) => {
|
||||||
|
set((s) => {
|
||||||
|
s.tokenAccounts[pubkey.toBase58()] = r.account
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
set((s) => {
|
||||||
|
s.subscriptions[pubkey.toBase58()] = sub
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
set: (fn) => set(produce(fn)),
|
set: (fn) => set(produce(fn)),
|
||||||
}))
|
}))
|
||||||
|
|
|
@ -9,7 +9,7 @@ import {
|
||||||
|
|
||||||
export type TokenAccount = AccountInfo
|
export type TokenAccount = AccountInfo
|
||||||
export type MintAccount = MintInfo
|
export type MintAccount = MintInfo
|
||||||
export type ProgramAccount<T> = {
|
export type AccountResponse<T> = {
|
||||||
publicKey: PublicKey
|
publicKey: PublicKey
|
||||||
account: T
|
account: T
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ export type ProgramAccount<T> = {
|
||||||
export async function getOwnedTokenAccounts(
|
export async function getOwnedTokenAccounts(
|
||||||
connection: Connection,
|
connection: Connection,
|
||||||
publicKey: PublicKey
|
publicKey: PublicKey
|
||||||
): Promise<ProgramAccount<TokenAccount>[]> {
|
): Promise<AccountResponse<TokenAccount>[]> {
|
||||||
const results = await connection.getTokenAccountsByOwner(publicKey, {
|
const results = await connection.getTokenAccountsByOwner(publicKey, {
|
||||||
programId: TOKEN_PROGRAM_ID,
|
programId: TOKEN_PROGRAM_ID,
|
||||||
})
|
})
|
||||||
|
@ -32,7 +32,7 @@ export async function getOwnedTokenAccounts(
|
||||||
export async function getMint(
|
export async function getMint(
|
||||||
connection: Connection,
|
connection: Connection,
|
||||||
publicKey: PublicKey
|
publicKey: PublicKey
|
||||||
): Promise<ProgramAccount<MintAccount>> {
|
): Promise<AccountResponse<MintAccount>> {
|
||||||
const result = await connection.getAccountInfo(publicKey)
|
const result = await connection.getAccountInfo(publicKey)
|
||||||
const data = Buffer.from(result.data)
|
const data = Buffer.from(result.data)
|
||||||
const account = parseMintAccountData(data)
|
const account = parseMintAccountData(data)
|
||||||
|
@ -42,6 +42,21 @@ export async function getMint(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function subscribeToTokenAccount(
|
||||||
|
connection: Connection,
|
||||||
|
publicKey: PublicKey,
|
||||||
|
cb: (r: AccountResponse<TokenAccount>) => void
|
||||||
|
): () => void {
|
||||||
|
const id = connection.onAccountChange(publicKey, (info) => {
|
||||||
|
const data = Buffer.from(info.data)
|
||||||
|
const account = parseTokenAccountData(publicKey, data)
|
||||||
|
cb({ publicKey, account })
|
||||||
|
})
|
||||||
|
return () => {
|
||||||
|
connection.removeAccountChangeListener(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// copied from @solana/spl-token
|
// copied from @solana/spl-token
|
||||||
|
|
||||||
const TOKEN_PROGRAM_ID = new PublicKey(
|
const TOKEN_PROGRAM_ID = new PublicKey(
|
||||||
|
|
Loading…
Reference in New Issue