2022-05-03 21:20:14 -07:00
|
|
|
import create from 'zustand'
|
|
|
|
import { subscribeWithSelector } from 'zustand/middleware'
|
|
|
|
import produce from 'immer'
|
2022-06-30 13:12:36 -07:00
|
|
|
import { AnchorProvider, Wallet, web3 } from '@project-serum/anchor'
|
2022-05-03 21:20:14 -07:00
|
|
|
import { Connection, Keypair, PublicKey } from '@solana/web3.js'
|
|
|
|
import {
|
|
|
|
MangoClient,
|
|
|
|
Group,
|
|
|
|
MangoAccount,
|
|
|
|
Serum3Market,
|
2022-06-21 03:58:57 -07:00
|
|
|
MANGO_V4_ID,
|
2022-05-03 21:20:14 -07:00
|
|
|
} from '@blockworks-foundation/mango-v4'
|
|
|
|
import EmptyWallet from '../utils/wallet'
|
2022-05-04 14:46:04 -07:00
|
|
|
import { Order } from '@project-serum/serum/lib/market'
|
2022-07-05 20:37:49 -07:00
|
|
|
import { Notification } from '../utils/notifications'
|
|
|
|
import {
|
|
|
|
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-05-31 18:41:18 -07:00
|
|
|
const DEVNET_GROUP = new PublicKey(
|
2022-06-29 20:37:25 -07:00
|
|
|
'A9XhGqUUjV992cD36qWDY8wDiZnGuCaUWtSE3NGXjDCb'
|
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-05-31 18:41:18 -07:00
|
|
|
const provider = new AnchorProvider(
|
2022-05-03 21:20:14 -07:00
|
|
|
connection,
|
|
|
|
new EmptyWallet(Keypair.generate()),
|
|
|
|
options
|
|
|
|
)
|
2022-07-05 20:37:49 -07:00
|
|
|
provider.opts.skipPreflight = true
|
2022-05-03 21:20:14 -07:00
|
|
|
|
|
|
|
export type MangoStore = {
|
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-05-03 21:20:14 -07:00
|
|
|
mangoAccount: MangoAccount | undefined
|
|
|
|
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-10 19:01:16 -07:00
|
|
|
inputTokenInfo: any
|
|
|
|
outputTokenInfo: any
|
2022-05-03 21:20:14 -07:00
|
|
|
set: (x: (x: MangoStore) => void) => void
|
2022-07-05 20:37:49 -07:00
|
|
|
wallet: {
|
|
|
|
tokens: TokenAccount[]
|
|
|
|
}
|
2022-05-03 21:20:14 -07:00
|
|
|
actions: {
|
|
|
|
fetchGroup: () => Promise<void>
|
2022-05-31 18:41:18 -07:00
|
|
|
fetchMangoAccount: (wallet: Wallet) => Promise<void>
|
2022-05-03 21:20:14 -07:00
|
|
|
loadSerumMarket: () => 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-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-05 20:37:49 -07:00
|
|
|
client: MangoClient.connect(provider, CLUSTER, MANGO_V4_ID[CLUSTER]),
|
2022-07-10 19:01:16 -07:00
|
|
|
inputTokenInfo: undefined,
|
2022-07-05 20:37:49 -07:00
|
|
|
jupiterTokens: [],
|
2022-05-03 21:20:14 -07:00
|
|
|
mangoAccount: undefined,
|
|
|
|
markets: undefined,
|
2022-07-05 20:37:49 -07:00
|
|
|
notificationIdCounter: 0,
|
|
|
|
notifications: [],
|
2022-07-10 19:01:16 -07:00
|
|
|
outputTokenInfo: undefined,
|
2022-05-03 21:20:14 -07:00
|
|
|
serumOrders: undefined,
|
|
|
|
set: (fn) => set(produce(fn)),
|
2022-07-05 20:37:49 -07:00
|
|
|
wallet: {
|
|
|
|
tokens: [],
|
|
|
|
},
|
2022-05-03 21:20:14 -07:00
|
|
|
actions: {
|
|
|
|
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-05-31 18:41:18 -07:00
|
|
|
const group = await client.getGroup(DEVNET_GROUP)
|
2022-06-22 04:55:03 -07:00
|
|
|
const markets = await client.serum3GetMarkets(
|
|
|
|
group,
|
|
|
|
group.banksMap.get('BTC')?.tokenIndex,
|
|
|
|
group.banksMap.get('USDC')?.tokenIndex
|
|
|
|
)
|
2022-05-03 21:20:14 -07:00
|
|
|
|
|
|
|
set((state) => {
|
|
|
|
state.group = group
|
2022-06-22 04:55:03 -07:00
|
|
|
state.markets = markets
|
2022-05-03 21:20:14 -07:00
|
|
|
})
|
|
|
|
} catch (e) {
|
|
|
|
console.error('Error fetching group', e)
|
|
|
|
}
|
|
|
|
},
|
2022-05-31 18:41:18 -07:00
|
|
|
fetchMangoAccount: async (wallet) => {
|
2022-05-03 21:20:14 -07:00
|
|
|
try {
|
2022-06-21 03:58:57 -07:00
|
|
|
const set = get().set
|
2022-05-03 21:20:14 -07:00
|
|
|
const group = get().group
|
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-05-31 18:41:18 -07:00
|
|
|
const provider = new AnchorProvider(connection, wallet, options)
|
2022-07-05 20:37:49 -07:00
|
|
|
provider.opts.skipPreflight = true
|
2022-06-21 03:58:57 -07:00
|
|
|
const client = await MangoClient.connect(
|
|
|
|
provider,
|
2022-07-05 20:37:49 -07:00
|
|
|
CLUSTER,
|
|
|
|
MANGO_V4_ID[CLUSTER]
|
2022-06-21 03:58:57 -07:00
|
|
|
)
|
2022-05-03 21:20:14 -07:00
|
|
|
|
|
|
|
const mangoAccount = await client.getOrCreateMangoAccount(
|
|
|
|
group,
|
|
|
|
wallet.publicKey,
|
|
|
|
0,
|
|
|
|
'Account'
|
|
|
|
)
|
|
|
|
|
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-05-03 21:20:14 -07:00
|
|
|
|
|
|
|
set((state) => {
|
|
|
|
state.client = client
|
|
|
|
state.mangoAccount = mangoAccount
|
2022-07-05 20:37:49 -07:00
|
|
|
state.connected = true
|
2022-05-31 18:41:18 -07:00
|
|
|
// state.serumOrders = orders
|
2022-05-03 21:20:14 -07:00
|
|
|
})
|
|
|
|
} catch (e) {
|
|
|
|
console.error('Error fetching mango acct', e)
|
|
|
|
}
|
|
|
|
},
|
2022-07-05 20:37:49 -07:00
|
|
|
fetchWalletTokens: async (wallet: Wallet) => {
|
|
|
|
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-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
|
|
|
|
const group = await client.getGroup(DEVNET_GROUP)
|
|
|
|
|
|
|
|
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
|
|
|
|
const mangoAccount = get().mangoAccount
|
|
|
|
|
|
|
|
if (!mangoAccount) return
|
|
|
|
|
|
|
|
try {
|
|
|
|
const newMangoAccount = await client.getMangoAccount(mangoAccount)
|
|
|
|
|
|
|
|
set((state) => {
|
|
|
|
state.mangoAccount = newMangoAccount
|
|
|
|
})
|
|
|
|
} catch {
|
|
|
|
console.error('Error reloading mango account')
|
|
|
|
}
|
|
|
|
},
|
|
|
|
loadSerumMarket: 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
|
|
|
|
const group = get().group
|
|
|
|
if (!group) return
|
|
|
|
|
2022-06-21 03:58:57 -07:00
|
|
|
const markets = await client.serum3GetMarkets(
|
2022-05-03 21:20:14 -07:00
|
|
|
group,
|
|
|
|
group.banksMap.get('BTC')?.tokenIndex,
|
|
|
|
group.banksMap.get('USDC')?.tokenIndex
|
|
|
|
)
|
|
|
|
|
2022-06-21 03:58:57 -07:00
|
|
|
let orders = await client.getSerum3Orders(group, 'BTC/USDC')
|
2022-05-03 21:20:14 -07:00
|
|
|
|
|
|
|
set((state) => {
|
|
|
|
state.markets = markets
|
|
|
|
state.serumOrders = orders
|
|
|
|
})
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
})
|
|
|
|
)
|
|
|
|
|
|
|
|
export default mangoStore
|