2022-08-18 13:50:34 -07:00
|
|
|
import dayjs from 'dayjs'
|
|
|
|
import produce from 'immer'
|
2022-05-03 21:20:14 -07:00
|
|
|
import create from 'zustand'
|
|
|
|
import { subscribeWithSelector } from 'zustand/middleware'
|
2022-08-18 13:50:34 -07:00
|
|
|
import {
|
|
|
|
AnchorProvider,
|
|
|
|
Wallet as AnchorWallet,
|
|
|
|
web3,
|
|
|
|
} from '@project-serum/anchor'
|
2022-05-03 21:20:14 -07:00
|
|
|
import { Connection, Keypair, PublicKey } from '@solana/web3.js'
|
2022-08-18 13:50:34 -07:00
|
|
|
import { getProfilePicture, ProfilePicture } from '@solflare-wallet/pfp'
|
|
|
|
import { TOKEN_LIST_URL } from '@jup-ag/core'
|
|
|
|
import { Order } from '@project-serum/serum/lib/market'
|
|
|
|
import { Wallet } from '@solana/wallet-adapter-react'
|
2022-05-03 21:20:14 -07:00
|
|
|
import {
|
|
|
|
MangoClient,
|
|
|
|
Group,
|
|
|
|
MangoAccount,
|
|
|
|
Serum3Market,
|
2022-06-21 03:58:57 -07:00
|
|
|
MANGO_V4_ID,
|
2022-08-18 13:50:34 -07:00
|
|
|
Bank,
|
2022-05-03 21:20:14 -07:00
|
|
|
} from '@blockworks-foundation/mango-v4'
|
2022-08-18 13:50:34 -07:00
|
|
|
|
2022-05-03 21:20:14 -07:00
|
|
|
import EmptyWallet from '../utils/wallet'
|
2022-08-01 22:32:21 -07:00
|
|
|
import { Notification, notify } from '../utils/notifications'
|
2022-07-05 20:37:49 -07:00
|
|
|
import {
|
2022-08-02 17:17:42 -07:00
|
|
|
COINGECKO_IDS,
|
2022-08-01 22:32:21 -07:00
|
|
|
fetchNftsFromHolaplexIndexer,
|
2022-07-05 20:37:49 -07:00
|
|
|
getTokenAccountsByOwnerWithWrappedSol,
|
|
|
|
TokenAccount,
|
|
|
|
} from '../utils/tokens'
|
2022-07-11 20:00:22 -07:00
|
|
|
import { Token } from '../types/jupiter'
|
2022-05-03 21:20:14 -07:00
|
|
|
|
2022-08-13 11:46:36 -07:00
|
|
|
const GROUP = new PublicKey('DLdcpC6AsAJ9xeKMR3WhHrN5sM5o7GVVXQhQ5vwisTtz')
|
2022-05-31 18:41:18 -07:00
|
|
|
|
2022-06-30 13:12:36 -07:00
|
|
|
export const connection = new web3.Connection(
|
2022-06-29 20:37:25 -07:00
|
|
|
'https://mango.rpcpool.com/946ef7337da3f5b8d3e4a34e7f88',
|
2022-05-31 18:41:18 -07:00
|
|
|
'processed'
|
|
|
|
)
|
2022-06-30 13:12:36 -07:00
|
|
|
const options = AnchorProvider.defaultOptions()
|
2022-07-05 20:37:49 -07:00
|
|
|
export const CLUSTER = 'mainnet-beta'
|
|
|
|
export const CLIENT_TX_TIMEOUT = 90000
|
2022-07-12 19:02:36 -07:00
|
|
|
const DEFAULT_PROVIDER = new AnchorProvider(
|
2022-05-03 21:20:14 -07:00
|
|
|
connection,
|
|
|
|
new EmptyWallet(Keypair.generate()),
|
|
|
|
options
|
|
|
|
)
|
2022-07-12 19:02:36 -07:00
|
|
|
DEFAULT_PROVIDER.opts.skipPreflight = true
|
|
|
|
const DEFAULT_CLIENT = MangoClient.connect(
|
|
|
|
DEFAULT_PROVIDER,
|
|
|
|
CLUSTER,
|
|
|
|
MANGO_V4_ID[CLUSTER]
|
|
|
|
)
|
2022-08-18 13:50:34 -07:00
|
|
|
export const INPUT_TOKEN_DEFAULT = 'USDC'
|
|
|
|
export const OUTPUT_TOKEN_DEFAULT = 'SOL'
|
2022-05-03 21:20:14 -07:00
|
|
|
|
2022-08-12 05:13:11 -07:00
|
|
|
interface TotalInterestDataItem {
|
|
|
|
borrow_interest: number
|
|
|
|
deposit_interest: number
|
|
|
|
borrow_interest_usd: number
|
|
|
|
deposit_interest_usd: number
|
|
|
|
symbol: string
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface PerformanceDataItem {
|
|
|
|
account_equity: number
|
|
|
|
borrow_interest_cumulative_usd: number
|
|
|
|
deposit_interest_cumulative_usd: number
|
|
|
|
pnl: number
|
|
|
|
spot_value: number
|
|
|
|
time: string
|
|
|
|
transfer_balance: number
|
|
|
|
}
|
|
|
|
|
2022-08-12 23:06:09 -07:00
|
|
|
export interface TradeHistoryItem {
|
|
|
|
block_datetime: string
|
|
|
|
mango_account: string
|
|
|
|
signature: string
|
|
|
|
swap_in_amount: number
|
|
|
|
swap_in_loan: number
|
|
|
|
swap_in_loan_origination_fee: number
|
|
|
|
swap_in_price_usd: number
|
|
|
|
swap_in_symbol: string
|
|
|
|
swap_out_amount: number
|
|
|
|
loan: number
|
|
|
|
loan_origination_fee: number
|
|
|
|
swap_out_price_usd: number
|
|
|
|
swap_out_symbol: string
|
|
|
|
}
|
|
|
|
|
2022-08-01 22:32:21 -07:00
|
|
|
interface NFT {
|
|
|
|
address: string
|
|
|
|
image: string
|
|
|
|
}
|
|
|
|
|
2022-05-03 21:20:14 -07:00
|
|
|
export type MangoStore = {
|
2022-08-02 17:17:42 -07:00
|
|
|
coingeckoPrices: {
|
|
|
|
data: any[]
|
|
|
|
loading: boolean
|
|
|
|
}
|
2022-07-05 20:37:49 -07:00
|
|
|
connected: boolean
|
2022-06-22 04:55:03 -07:00
|
|
|
connection: Connection
|
2022-05-03 21:20:14 -07:00
|
|
|
group: Group | undefined
|
|
|
|
client: MangoClient
|
2022-07-11 20:00:22 -07:00
|
|
|
jupiterTokens: Token[]
|
2022-07-27 23:35:18 -07:00
|
|
|
mangoAccount: {
|
|
|
|
current: MangoAccount | undefined
|
|
|
|
loading: boolean
|
2022-08-12 05:13:11 -07:00
|
|
|
stats: {
|
|
|
|
interestTotals: { data: TotalInterestDataItem[]; loading: boolean }
|
|
|
|
performance: { data: PerformanceDataItem[]; loading: boolean }
|
2022-08-12 23:06:09 -07:00
|
|
|
tradeHistory: { data: TradeHistoryItem[]; loading: boolean }
|
2022-08-12 05:13:11 -07:00
|
|
|
}
|
2022-07-27 23:35:18 -07:00
|
|
|
}
|
2022-08-16 05:48:27 -07:00
|
|
|
mangoAccounts: { accounts: MangoAccount[]; loading: boolean }
|
2022-05-03 21:20:14 -07:00
|
|
|
markets: Serum3Market[] | undefined
|
2022-07-05 20:37:49 -07:00
|
|
|
notificationIdCounter: number
|
|
|
|
notifications: Array<Notification>
|
2022-05-03 21:20:14 -07:00
|
|
|
serumOrders: Order[] | undefined
|
2022-07-25 22:27:53 -07:00
|
|
|
swap: {
|
2022-08-18 13:50:34 -07:00
|
|
|
inputBank: Bank | undefined
|
|
|
|
outputBank: Bank | undefined
|
2022-08-02 11:04:00 -07:00
|
|
|
inputTokenInfo: Token | undefined
|
|
|
|
outputTokenInfo: Token | undefined
|
2022-08-08 10:42:18 -07:00
|
|
|
margin: boolean
|
|
|
|
slippage: number
|
2022-07-25 22:27:53 -07:00
|
|
|
}
|
2022-05-03 21:20:14 -07:00
|
|
|
set: (x: (x: MangoStore) => void) => void
|
2022-07-05 20:37:49 -07:00
|
|
|
wallet: {
|
2022-07-26 21:40:17 -07:00
|
|
|
loadProfilePic: boolean
|
|
|
|
profilePic: ProfilePicture | undefined
|
2022-07-05 20:37:49 -07:00
|
|
|
tokens: TokenAccount[]
|
2022-08-01 22:32:21 -07:00
|
|
|
nfts: {
|
|
|
|
data: NFT[] | []
|
|
|
|
loading: boolean
|
|
|
|
}
|
2022-07-05 20:37:49 -07:00
|
|
|
}
|
2022-05-03 21:20:14 -07:00
|
|
|
actions: {
|
2022-08-12 15:29:31 -07:00
|
|
|
fetchAccountInterestTotals: (mangoAccountPk: string) => Promise<void>
|
2022-08-12 05:13:11 -07:00
|
|
|
fetchAccountPerformance: (
|
|
|
|
mangoAccountPk: string,
|
|
|
|
range: number
|
|
|
|
) => Promise<void>
|
2022-08-02 17:17:42 -07:00
|
|
|
fetchCoingeckoPrices: () => Promise<void>
|
2022-05-03 21:20:14 -07:00
|
|
|
fetchGroup: () => Promise<void>
|
2022-08-18 13:50:34 -07:00
|
|
|
fetchMangoAccount: (
|
|
|
|
wallet: AnchorWallet,
|
|
|
|
accountNumber?: number
|
|
|
|
) => Promise<void>
|
|
|
|
fetchMangoAccounts: (wallet: AnchorWallet) => Promise<void>
|
2022-08-01 22:32:21 -07:00
|
|
|
fetchNfts: (connection: Connection, walletPk: PublicKey) => void
|
2022-08-18 13:50:34 -07:00
|
|
|
fetchProfilePicture: (wallet: AnchorWallet) => void
|
2022-08-01 12:22:59 -07:00
|
|
|
fetchJupiterTokens: () => Promise<void>
|
2022-08-12 23:06:09 -07:00
|
|
|
fetchTradeHistory: (mangoAccountPk: string) => Promise<void>
|
2022-08-18 13:50:34 -07:00
|
|
|
fetchWalletTokens: (wallet: AnchorWallet) => Promise<void>
|
2022-08-18 14:38:48 -07:00
|
|
|
connectMangoClientWithWallet: (wallet: Wallet) => Promise<void>
|
2022-05-31 18:41:18 -07:00
|
|
|
reloadAccount: () => Promise<void>
|
|
|
|
reloadGroup: () => Promise<void>
|
2022-05-03 21:20:14 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const mangoStore = create<MangoStore>(
|
|
|
|
subscribeWithSelector((set, get) => {
|
|
|
|
return {
|
2022-08-02 17:17:42 -07:00
|
|
|
coingeckoPrices: {
|
|
|
|
data: [],
|
|
|
|
loading: false,
|
|
|
|
},
|
2022-07-05 20:37:49 -07:00
|
|
|
connected: false,
|
2022-06-22 04:55:03 -07:00
|
|
|
connection,
|
2022-05-03 21:20:14 -07:00
|
|
|
group: undefined,
|
2022-07-12 19:02:36 -07:00
|
|
|
client: DEFAULT_CLIENT,
|
2022-07-05 20:37:49 -07:00
|
|
|
jupiterTokens: [],
|
2022-07-27 23:35:18 -07:00
|
|
|
mangoAccount: {
|
|
|
|
current: undefined,
|
2022-08-11 21:20:17 -07:00
|
|
|
loading: true,
|
2022-08-12 05:13:11 -07:00
|
|
|
stats: {
|
|
|
|
interestTotals: { data: [], loading: false },
|
|
|
|
performance: { data: [], loading: false },
|
2022-08-12 23:06:09 -07:00
|
|
|
tradeHistory: { data: [], loading: false },
|
2022-08-12 05:13:11 -07:00
|
|
|
},
|
2022-07-27 23:35:18 -07:00
|
|
|
},
|
2022-08-16 05:48:27 -07:00
|
|
|
mangoAccounts: { accounts: [], loading: true },
|
2022-05-03 21:20:14 -07:00
|
|
|
markets: undefined,
|
2022-07-05 20:37:49 -07:00
|
|
|
notificationIdCounter: 0,
|
|
|
|
notifications: [],
|
2022-05-03 21:20:14 -07:00
|
|
|
serumOrders: undefined,
|
|
|
|
set: (fn) => set(produce(fn)),
|
2022-07-25 22:27:53 -07:00
|
|
|
swap: {
|
2022-08-18 13:50:34 -07:00
|
|
|
inputBank: undefined,
|
|
|
|
outputBank: undefined,
|
2022-07-25 22:27:53 -07:00
|
|
|
inputTokenInfo: undefined,
|
|
|
|
outputTokenInfo: undefined,
|
2022-08-08 10:42:18 -07:00
|
|
|
margin: true,
|
2022-08-08 11:44:25 -07:00
|
|
|
slippage: 0.5,
|
2022-07-25 22:27:53 -07:00
|
|
|
},
|
2022-07-05 20:37:49 -07:00
|
|
|
wallet: {
|
2022-07-26 21:40:17 -07:00
|
|
|
loadProfilePic: true,
|
|
|
|
profilePic: undefined,
|
2022-07-05 20:37:49 -07:00
|
|
|
tokens: [],
|
2022-08-01 22:32:21 -07:00
|
|
|
nfts: {
|
|
|
|
data: [],
|
|
|
|
loading: false,
|
|
|
|
},
|
2022-07-05 20:37:49 -07:00
|
|
|
},
|
2022-05-03 21:20:14 -07:00
|
|
|
actions: {
|
2022-08-12 15:29:31 -07:00
|
|
|
fetchAccountInterestTotals: async (mangoAccountPk: string) => {
|
2022-08-12 05:13:11 -07:00
|
|
|
const set = get().set
|
|
|
|
set((state) => {
|
|
|
|
state.mangoAccount.stats.interestTotals.loading = true
|
|
|
|
})
|
|
|
|
try {
|
|
|
|
const response = await fetch(
|
2022-08-12 15:29:31 -07:00
|
|
|
`https://mango-transaction-log.herokuapp.com/v4/stats/interest-account-total?mango-account=${mangoAccountPk}`
|
2022-08-12 05:13:11 -07:00
|
|
|
)
|
|
|
|
const parsedResponse = await response.json()
|
|
|
|
const entries: any = Object.entries(parsedResponse).sort((a, b) =>
|
|
|
|
b[0].localeCompare(a[0])
|
|
|
|
)
|
|
|
|
|
|
|
|
const stats = entries
|
|
|
|
.map(([key, value]: Array<{ key: string; value: number }>) => {
|
|
|
|
return { ...value, symbol: key }
|
|
|
|
})
|
|
|
|
.filter((x: string) => x)
|
|
|
|
|
|
|
|
set((state) => {
|
|
|
|
state.mangoAccount.stats.interestTotals.data = stats
|
|
|
|
state.mangoAccount.stats.interestTotals.loading = false
|
|
|
|
})
|
|
|
|
} catch {
|
|
|
|
set((state) => {
|
|
|
|
state.mangoAccount.stats.interestTotals.loading = false
|
|
|
|
})
|
|
|
|
notify({
|
|
|
|
title: 'Failed to load account interest totals',
|
|
|
|
type: 'error',
|
|
|
|
})
|
|
|
|
}
|
|
|
|
},
|
|
|
|
fetchAccountPerformance: async (
|
|
|
|
mangoAccountPk: string,
|
|
|
|
range: number
|
|
|
|
) => {
|
|
|
|
const set = get().set
|
|
|
|
set((state) => {
|
|
|
|
state.mangoAccount.stats.performance.loading = true
|
|
|
|
})
|
|
|
|
try {
|
|
|
|
const response = await fetch(
|
|
|
|
`https://mango-transaction-log.herokuapp.com/v4/stats/performance_account?mango-account=${mangoAccountPk}&start-date=${dayjs()
|
|
|
|
.subtract(range, 'day')
|
|
|
|
.format('YYYY-MM-DD')}`
|
|
|
|
)
|
|
|
|
const parsedResponse = await response.json()
|
|
|
|
const entries: any = Object.entries(parsedResponse).sort((a, b) =>
|
|
|
|
b[0].localeCompare(a[0])
|
|
|
|
)
|
|
|
|
|
|
|
|
const stats = entries
|
|
|
|
.map(([key, value]: Array<{ key: string; value: number }>) => {
|
|
|
|
return { ...value, time: key }
|
|
|
|
})
|
|
|
|
.filter((x: string) => x)
|
|
|
|
|
|
|
|
set((state) => {
|
2022-08-15 17:16:21 -07:00
|
|
|
state.mangoAccount.stats.performance.data = stats.reverse()
|
2022-08-12 05:13:11 -07:00
|
|
|
state.mangoAccount.stats.performance.loading = false
|
|
|
|
})
|
|
|
|
} catch {
|
|
|
|
set((state) => {
|
|
|
|
state.mangoAccount.stats.performance.loading = false
|
|
|
|
})
|
|
|
|
notify({
|
|
|
|
title: 'Failed to load account performance data',
|
|
|
|
type: 'error',
|
|
|
|
})
|
|
|
|
}
|
|
|
|
},
|
2022-08-02 17:17:42 -07:00
|
|
|
fetchCoingeckoPrices: async () => {
|
|
|
|
const set = get().set
|
|
|
|
set((state) => {
|
|
|
|
state.coingeckoPrices.loading = true
|
|
|
|
})
|
|
|
|
try {
|
|
|
|
const promises: any = []
|
|
|
|
for (const asset of COINGECKO_IDS) {
|
|
|
|
promises.push(
|
|
|
|
fetch(
|
|
|
|
`https://api.coingecko.com/api/v3/coins/${asset.id}/market_chart?vs_currency=usd&days=1`
|
|
|
|
).then((res) => res.json())
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
const data = await Promise.all(promises)
|
|
|
|
for (let i = 0; i < data.length; i++) {
|
|
|
|
data[i].symbol = COINGECKO_IDS[i].symbol
|
|
|
|
}
|
|
|
|
set((state) => {
|
|
|
|
state.coingeckoPrices.data = data
|
|
|
|
state.coingeckoPrices.loading = false
|
|
|
|
})
|
|
|
|
} catch (e) {
|
|
|
|
console.log('ERORR: Unable to load Coingecko prices')
|
|
|
|
set((state) => {
|
|
|
|
state.coingeckoPrices.loading = false
|
|
|
|
})
|
|
|
|
}
|
|
|
|
},
|
2022-05-03 21:20:14 -07:00
|
|
|
fetchGroup: async () => {
|
|
|
|
try {
|
2022-06-21 03:58:57 -07:00
|
|
|
const set = get().set
|
2022-05-03 21:20:14 -07:00
|
|
|
const client = get().client
|
2022-08-03 14:46:37 -07:00
|
|
|
const group = await client.getGroup(GROUP)
|
|
|
|
|
2022-05-03 21:20:14 -07:00
|
|
|
set((state) => {
|
|
|
|
state.group = group
|
|
|
|
})
|
|
|
|
} catch (e) {
|
|
|
|
console.error('Error fetching group', e)
|
|
|
|
}
|
|
|
|
},
|
2022-08-11 21:20:17 -07:00
|
|
|
fetchMangoAccount: async (wallet, accountNumber) => {
|
2022-08-03 14:46:37 -07:00
|
|
|
const set = get().set
|
2022-05-03 21:20:14 -07:00
|
|
|
try {
|
|
|
|
const group = get().group
|
2022-08-18 13:50:34 -07:00
|
|
|
const client = get().client
|
2022-05-31 18:41:18 -07:00
|
|
|
if (!group) throw new Error('Group not loaded')
|
2022-05-03 21:20:14 -07:00
|
|
|
|
2022-08-11 21:20:17 -07:00
|
|
|
const mangoAccount = await client.getMangoAccountForOwner(
|
2022-05-03 21:20:14 -07:00
|
|
|
group,
|
|
|
|
wallet.publicKey,
|
2022-08-11 21:20:17 -07:00
|
|
|
accountNumber || 0
|
2022-05-03 21:20:14 -07:00
|
|
|
)
|
|
|
|
|
2022-05-31 18:41:18 -07:00
|
|
|
// let orders = await client.getSerum3Orders(
|
|
|
|
// group,
|
2022-06-21 03:58:57 -07:00
|
|
|
// SERUM3_PROGRAM_ID['devnet'],
|
2022-05-31 18:41:18 -07:00
|
|
|
// 'BTC/USDC'
|
|
|
|
// )
|
2022-08-11 21:20:17 -07:00
|
|
|
if (mangoAccount) {
|
|
|
|
await mangoAccount.reloadAccountData(client, group)
|
|
|
|
}
|
2022-05-03 21:20:14 -07:00
|
|
|
set((state) => {
|
2022-07-27 23:35:18 -07:00
|
|
|
state.mangoAccount.current = mangoAccount
|
|
|
|
state.mangoAccount.loading = false
|
2022-05-03 21:20:14 -07:00
|
|
|
})
|
|
|
|
} catch (e) {
|
2022-07-27 23:35:18 -07:00
|
|
|
set((state) => {
|
|
|
|
state.mangoAccount.loading = false
|
|
|
|
})
|
2022-05-03 21:20:14 -07:00
|
|
|
console.error('Error fetching mango acct', e)
|
|
|
|
}
|
|
|
|
},
|
2022-08-01 18:08:08 -07:00
|
|
|
fetchMangoAccounts: async (wallet) => {
|
|
|
|
try {
|
|
|
|
const set = get().set
|
|
|
|
const group = get().group
|
|
|
|
const client = get().client
|
|
|
|
if (!group) throw new Error('Group not loaded')
|
|
|
|
if (!client) throw new Error('Client not loaded')
|
|
|
|
|
2022-08-04 09:42:03 -07:00
|
|
|
const mangoAccounts = await client.getMangoAccountsForOwner(
|
2022-08-01 18:08:08 -07:00
|
|
|
group,
|
|
|
|
wallet.publicKey
|
|
|
|
)
|
2022-08-16 16:49:39 -07:00
|
|
|
set((state) => {
|
|
|
|
state.mangoAccounts.accounts = mangoAccounts
|
|
|
|
state.mangoAccounts.loading = false
|
|
|
|
})
|
2022-08-01 18:08:08 -07:00
|
|
|
} catch (e) {
|
2022-08-16 16:49:39 -07:00
|
|
|
set((state) => {
|
|
|
|
state.mangoAccounts.loading = false
|
|
|
|
})
|
2022-08-01 18:08:08 -07:00
|
|
|
console.error('Error fetching mango accts', e)
|
|
|
|
}
|
|
|
|
},
|
2022-08-01 22:32:21 -07:00
|
|
|
fetchNfts: async (connection: Connection, ownerPk: PublicKey) => {
|
|
|
|
const set = get().set
|
|
|
|
set((state) => {
|
|
|
|
state.wallet.nfts.loading = true
|
|
|
|
})
|
|
|
|
try {
|
|
|
|
const data = await fetchNftsFromHolaplexIndexer(ownerPk)
|
|
|
|
set((state) => {
|
|
|
|
state.wallet.nfts.data = data.nfts
|
|
|
|
state.wallet.nfts.loading = false
|
|
|
|
})
|
|
|
|
} catch (error) {
|
|
|
|
notify({
|
|
|
|
type: 'error',
|
|
|
|
title: 'Unable to fetch nfts',
|
|
|
|
})
|
|
|
|
}
|
|
|
|
return []
|
|
|
|
},
|
2022-08-12 23:06:09 -07:00
|
|
|
fetchTradeHistory: async (mangoAccountPk: string) => {
|
|
|
|
const set = get().set
|
|
|
|
set((state) => {
|
|
|
|
state.mangoAccount.stats.tradeHistory.loading = true
|
|
|
|
})
|
|
|
|
try {
|
|
|
|
const history = await fetch(
|
|
|
|
`https://mango-transaction-log.herokuapp.com/v4/stats/swap-history?mango-account=${mangoAccountPk}`
|
|
|
|
)
|
|
|
|
const parsedHistory = await history.json()
|
|
|
|
const sortedHistory =
|
|
|
|
parsedHistory && parsedHistory.length
|
|
|
|
? parsedHistory.sort(
|
|
|
|
(a: TradeHistoryItem, b: TradeHistoryItem) =>
|
|
|
|
dayjs(b.block_datetime).unix() -
|
|
|
|
dayjs(a.block_datetime).unix()
|
|
|
|
)
|
|
|
|
: []
|
|
|
|
|
|
|
|
set((state) => {
|
|
|
|
state.mangoAccount.stats.tradeHistory.data = sortedHistory
|
|
|
|
state.mangoAccount.stats.tradeHistory.loading = false
|
|
|
|
})
|
|
|
|
} catch {
|
|
|
|
set((state) => {
|
|
|
|
state.mangoAccount.stats.tradeHistory.loading = false
|
|
|
|
})
|
|
|
|
notify({
|
|
|
|
title: 'Failed to load account performance data',
|
|
|
|
type: 'error',
|
|
|
|
})
|
|
|
|
}
|
|
|
|
},
|
2022-08-18 13:50:34 -07:00
|
|
|
fetchWalletTokens: async (wallet: AnchorWallet) => {
|
2022-07-05 20:37:49 -07:00
|
|
|
const set = get().set
|
|
|
|
const connection = get().connection
|
|
|
|
|
|
|
|
if (wallet.publicKey) {
|
|
|
|
const token = await getTokenAccountsByOwnerWithWrappedSol(
|
|
|
|
connection,
|
|
|
|
wallet.publicKey
|
|
|
|
)
|
|
|
|
|
|
|
|
set((state) => {
|
|
|
|
state.wallet.tokens = token
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
set((state) => {
|
|
|
|
state.wallet.tokens = []
|
|
|
|
})
|
|
|
|
}
|
|
|
|
},
|
2022-08-01 12:22:59 -07:00
|
|
|
fetchJupiterTokens: async () => {
|
|
|
|
const set = mangoStore.getState().set
|
2022-08-02 11:04:00 -07:00
|
|
|
const group = mangoStore.getState().group
|
|
|
|
if (!group) {
|
|
|
|
console.error(
|
|
|
|
'Mango group unavailable; Loading jupiter tokens failed'
|
|
|
|
)
|
|
|
|
return
|
|
|
|
}
|
2022-08-18 13:50:34 -07:00
|
|
|
const bankMints = Array.from(group.banksMapByName.values()).map((b) =>
|
|
|
|
b[0].mint.toString()
|
2022-08-10 12:43:16 -07:00
|
|
|
)
|
2022-08-01 12:22:59 -07:00
|
|
|
|
|
|
|
fetch(TOKEN_LIST_URL[CLUSTER])
|
|
|
|
.then((response) => response.json())
|
|
|
|
.then((result) => {
|
2022-08-02 11:04:00 -07:00
|
|
|
const groupTokens = result.filter((t: any) =>
|
2022-08-10 12:43:16 -07:00
|
|
|
bankMints.includes(t.address)
|
2022-08-02 11:04:00 -07:00
|
|
|
)
|
|
|
|
const inputTokenInfo = groupTokens.find(
|
2022-08-18 13:50:34 -07:00
|
|
|
(t: any) => t.symbol === INPUT_TOKEN_DEFAULT
|
2022-08-02 11:04:00 -07:00
|
|
|
)
|
|
|
|
const outputTokenInfo = groupTokens.find(
|
2022-08-18 13:50:34 -07:00
|
|
|
(t: any) => t.symbol === OUTPUT_TOKEN_DEFAULT
|
2022-08-01 12:22:59 -07:00
|
|
|
)
|
|
|
|
set((s) => {
|
|
|
|
s.swap.inputTokenInfo = inputTokenInfo
|
|
|
|
s.swap.outputTokenInfo = outputTokenInfo
|
2022-08-02 11:04:00 -07:00
|
|
|
s.jupiterTokens = groupTokens
|
2022-08-01 12:22:59 -07:00
|
|
|
})
|
|
|
|
})
|
|
|
|
},
|
2022-08-18 14:38:48 -07:00
|
|
|
connectMangoClientWithWallet: async (wallet: Wallet) => {
|
2022-08-18 13:50:34 -07:00
|
|
|
try {
|
|
|
|
const provider = new AnchorProvider(
|
|
|
|
connection,
|
2022-08-18 14:38:48 -07:00
|
|
|
wallet.adapter as unknown as AnchorWallet,
|
2022-08-18 13:50:34 -07:00
|
|
|
options
|
|
|
|
)
|
|
|
|
provider.opts.skipPreflight = true
|
|
|
|
const client = await MangoClient.connect(
|
|
|
|
provider,
|
|
|
|
CLUSTER,
|
|
|
|
MANGO_V4_ID[CLUSTER],
|
|
|
|
{
|
|
|
|
prioritizationFee: 2,
|
|
|
|
postSendTxCallback: ({ txid }: { txid: string }) => {
|
|
|
|
notify({
|
|
|
|
title: 'Transaction sent',
|
|
|
|
description: 'Waiting for confirmation',
|
|
|
|
type: 'confirm',
|
|
|
|
txid: txid,
|
|
|
|
})
|
|
|
|
},
|
|
|
|
}
|
|
|
|
)
|
|
|
|
set((s) => {
|
|
|
|
s.client = client
|
|
|
|
s.connected = true
|
|
|
|
})
|
|
|
|
} catch (e: any) {
|
|
|
|
if (e.name.includes('WalletLoadError')) {
|
|
|
|
notify({
|
|
|
|
title: `${wallet.adapter.name} Error`,
|
|
|
|
type: 'error',
|
|
|
|
description: `Please install ${wallet.adapter.name} and then reload this page.`,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
2022-05-31 18:41:18 -07:00
|
|
|
reloadGroup: async () => {
|
|
|
|
try {
|
2022-06-21 03:58:57 -07:00
|
|
|
const set = get().set
|
2022-05-31 18:41:18 -07:00
|
|
|
const client = get().client
|
2022-08-03 14:46:37 -07:00
|
|
|
const group = await client.getGroup(GROUP)
|
2022-05-31 18:41:18 -07:00
|
|
|
|
|
|
|
set((state) => {
|
|
|
|
state.group = group
|
|
|
|
})
|
|
|
|
} catch (e) {
|
|
|
|
console.error('Error fetching group', e)
|
|
|
|
}
|
|
|
|
},
|
2022-05-03 21:20:14 -07:00
|
|
|
reloadAccount: async () => {
|
2022-06-21 03:58:57 -07:00
|
|
|
const set = get().set
|
2022-05-03 21:20:14 -07:00
|
|
|
const client = get().client
|
2022-07-27 23:35:18 -07:00
|
|
|
const mangoAccount = get().mangoAccount.current
|
2022-07-14 12:33:11 -07:00
|
|
|
const group = get().group
|
2022-08-02 11:04:00 -07:00
|
|
|
const actions = get().actions
|
2022-05-03 21:20:14 -07:00
|
|
|
|
2022-07-14 12:33:11 -07:00
|
|
|
if (!mangoAccount || !group) return
|
2022-05-03 21:20:14 -07:00
|
|
|
|
|
|
|
try {
|
|
|
|
const newMangoAccount = await client.getMangoAccount(mangoAccount)
|
2022-07-14 12:33:11 -07:00
|
|
|
await newMangoAccount.reloadAccountData(client, group)
|
2022-05-03 21:20:14 -07:00
|
|
|
|
|
|
|
set((state) => {
|
2022-07-27 23:35:18 -07:00
|
|
|
state.mangoAccount.current = newMangoAccount
|
2022-05-03 21:20:14 -07:00
|
|
|
})
|
|
|
|
} catch {
|
|
|
|
console.error('Error reloading mango account')
|
|
|
|
}
|
|
|
|
},
|
2022-08-18 13:50:34 -07:00
|
|
|
async fetchProfilePicture(wallet: AnchorWallet) {
|
2022-07-26 21:40:17 -07:00
|
|
|
const set = get().set
|
|
|
|
const walletPk = wallet?.publicKey
|
|
|
|
const connection = get().connection
|
|
|
|
|
|
|
|
if (!walletPk) return
|
|
|
|
|
|
|
|
try {
|
|
|
|
const result = await getProfilePicture(connection, walletPk)
|
|
|
|
|
|
|
|
set((state) => {
|
|
|
|
state.wallet.profilePic = result
|
|
|
|
state.wallet.loadProfilePic = false
|
|
|
|
})
|
|
|
|
} catch (e) {
|
|
|
|
console.log('Could not get profile picture', e)
|
|
|
|
set((state) => {
|
|
|
|
state.wallet.loadProfilePic = false
|
|
|
|
})
|
|
|
|
}
|
|
|
|
},
|
2022-05-03 21:20:14 -07:00
|
|
|
},
|
|
|
|
}
|
|
|
|
})
|
|
|
|
)
|
|
|
|
|
|
|
|
export default mangoStore
|