Fix/duplicated account keys (#1221)
* typing for governance select * Fix select duplicated key * change axios.request by axios.post * nit, remove unused import * nit * Fix typing issues
This commit is contained in:
parent
615de7b806
commit
e4f224e6aa
|
@ -1,5 +1,12 @@
|
|||
{
|
||||
"typescript.tsdk": "node_modules/typescript/lib",
|
||||
"cSpell.words": ["Addin", "blockworks", "lamports", "solana", "VERCEL"],
|
||||
"cSpell.words": [
|
||||
"Addin",
|
||||
"blockworks",
|
||||
"lamports",
|
||||
"solana",
|
||||
"VERCEL",
|
||||
"WSOL"
|
||||
],
|
||||
"editor.formatOnSave": true
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ const Clawback = ({
|
|||
governedTokenAccountsWithoutNfts,
|
||||
governancesArray,
|
||||
} = useGovernanceAssets()
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const [voters, setVoters] = useState<Voter[]>([])
|
||||
const [deposits, setDeposits] = useState<DepositWithMintAccount[]>([])
|
||||
const [form, setForm] = useState<ClawbackForm>({
|
||||
|
|
|
@ -51,7 +51,7 @@ const Grant = ({
|
|||
const wallet = useWalletStore((s) => s.current)
|
||||
const { realm, tokenRecords, realmInfo } = useRealm()
|
||||
const { governedTokenAccountsWithoutNfts } = useGovernanceAssets()
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const [startDate, setStartDate] = useState(dayjs().format('DD-MM-YYYY'))
|
||||
const [endDate, setEndDate] = useState('')
|
||||
const [useableGrantMints, setUseableGrantMints] = useState<string[]>([])
|
||||
|
|
|
@ -19,17 +19,17 @@ const GovernedAccountSelect = ({
|
|||
governance,
|
||||
label,
|
||||
noMaxWidth,
|
||||
autoselectFirst = true,
|
||||
autoSelectFirst = true,
|
||||
}: {
|
||||
onChange
|
||||
value
|
||||
error?
|
||||
governedAccounts: AssetAccount[]
|
||||
shouldBeGoverned?
|
||||
shouldBeGoverned?: boolean
|
||||
governance?: ProgramAccount<Governance> | null | undefined
|
||||
label?
|
||||
noMaxWidth?: boolean
|
||||
autoselectFirst?: boolean
|
||||
autoSelectFirst?: boolean
|
||||
}) => {
|
||||
function getLabel(value: AssetAccount) {
|
||||
if (value) {
|
||||
|
@ -114,7 +114,7 @@ const GovernedAccountSelect = ({
|
|||
)
|
||||
}
|
||||
useEffect(() => {
|
||||
if (governedAccounts.length == 1 && autoselectFirst) {
|
||||
if (governedAccounts.length == 1 && autoSelectFirst) {
|
||||
//wait for microtask queue to be empty
|
||||
setTimeout(() => {
|
||||
onChange(governedAccounts[0])
|
||||
|
|
|
@ -11,6 +11,7 @@ export default function useGovernanceAssets() {
|
|||
const governedTokenAccounts: AssetAccount[] = useGovernanceAssetsStore(
|
||||
(s) => s.governedTokenAccounts
|
||||
)
|
||||
|
||||
const assetAccounts = useGovernanceAssetsStore((s) =>
|
||||
s.assetAccounts.filter((x) => x.type !== AccountType.AuxiliaryToken)
|
||||
)
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { MintInfo } from '@blockworks-foundation/mango-v4'
|
||||
import { getCertifiedRealmInfos, RealmInfo } from '@models/registry/api'
|
||||
import { AssetType, TokenOwnerRecordAsset } from '@models/treasury/Asset'
|
||||
import {
|
||||
|
@ -11,7 +10,11 @@ import {
|
|||
} from '@solana/spl-governance'
|
||||
import { AccountInfo, PublicKey } from '@solana/web3.js'
|
||||
import { ConnectionContext } from '@utils/connection'
|
||||
import { parseMintAccountData, TokenProgramAccount } from '@utils/tokens'
|
||||
import {
|
||||
MintAccount,
|
||||
parseMintAccountData,
|
||||
TokenProgramAccount,
|
||||
} from '@utils/tokens'
|
||||
import axios from 'axios'
|
||||
|
||||
const getAccountInfoFromRaw = (raw: any) => {
|
||||
|
@ -112,7 +115,7 @@ const getTokenOwnerRecordsForWallet = async (
|
|||
tokenOwnerRecordAccountInfo
|
||||
) as ProgramAccount<TokenOwnerRecord>
|
||||
|
||||
const mintAccount: TokenProgramAccount<MintInfo> = {
|
||||
const mintAccount: TokenProgramAccount<MintAccount> = {
|
||||
publicKey: cacheMap[id].realmInfo.communityMint!, // already checking above if present
|
||||
account: parseMintAccountData(communityMintAccountInfo.data),
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ const GovernanceAccountSelect = ({
|
|||
governanceAccounts = [],
|
||||
label,
|
||||
noMaxWidth,
|
||||
autoselectFirst = true,
|
||||
autoSelectFirst = true,
|
||||
}: {
|
||||
onChange
|
||||
value
|
||||
|
@ -18,10 +18,10 @@ const GovernanceAccountSelect = ({
|
|||
governanceAccounts: ProgramAccount<Governance>[]
|
||||
label?
|
||||
noMaxWidth?: boolean
|
||||
autoselectFirst?: boolean
|
||||
autoSelectFirst?: boolean
|
||||
}) => {
|
||||
useEffect(() => {
|
||||
if (governanceAccounts.length == 1 && autoselectFirst) {
|
||||
if (governanceAccounts.length == 1 && autoSelectFirst) {
|
||||
//wait for microtask queue to be empty
|
||||
setTimeout(() => {
|
||||
onChange(governanceAccounts[0])
|
||||
|
|
|
@ -19,43 +19,45 @@ const GovernedAccountSelect = ({
|
|||
governance,
|
||||
label,
|
||||
noMaxWidth,
|
||||
autoselectFirst = true,
|
||||
autoSelectFirst = true,
|
||||
}: {
|
||||
onChange
|
||||
value
|
||||
error?
|
||||
onChange: (value: unknown) => void
|
||||
value?: AssetAccount | null
|
||||
error?: string
|
||||
governedAccounts: AssetAccount[]
|
||||
shouldBeGoverned?
|
||||
governance?: ProgramAccount<Governance> | null | undefined
|
||||
label?
|
||||
shouldBeGoverned?: boolean | null
|
||||
governance?: ProgramAccount<Governance> | null
|
||||
label?: string
|
||||
noMaxWidth?: boolean
|
||||
autoselectFirst?: boolean
|
||||
autoSelectFirst?: boolean
|
||||
}) => {
|
||||
function getLabel(value: AssetAccount) {
|
||||
if (value) {
|
||||
const accountType = value.governance.account.accountType
|
||||
if (value.isSol || value.isToken) {
|
||||
return getTokenAccountLabelComponent(
|
||||
value.isSol
|
||||
? getSolAccountLabel(value)
|
||||
: getTokenAccountLabelInfo(value)
|
||||
)
|
||||
} else {
|
||||
switch (accountType) {
|
||||
case GovernanceAccountType.MintGovernanceV1:
|
||||
case GovernanceAccountType.MintGovernanceV2:
|
||||
return getMintAccountLabelComponent(getMintAccountLabelInfo(value))
|
||||
case GovernanceAccountType.ProgramGovernanceV1:
|
||||
case GovernanceAccountType.ProgramGovernanceV2:
|
||||
return getProgramAccountLabel(value.governance)
|
||||
default:
|
||||
return value.governance.account.governedAccount.toBase58()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
function getLabel(value?: AssetAccount | null) {
|
||||
if (!value) {
|
||||
return null
|
||||
}
|
||||
|
||||
const accountType = value.governance.account.accountType
|
||||
|
||||
if (value.isSol || value.isToken) {
|
||||
return getTokenAccountLabelComponent(
|
||||
value.isSol
|
||||
? getSolAccountLabel(value)
|
||||
: getTokenAccountLabelInfo(value)
|
||||
)
|
||||
}
|
||||
|
||||
switch (accountType) {
|
||||
case GovernanceAccountType.MintGovernanceV1:
|
||||
case GovernanceAccountType.MintGovernanceV2:
|
||||
return getMintAccountLabelComponent(getMintAccountLabelInfo(value))
|
||||
case GovernanceAccountType.ProgramGovernanceV1:
|
||||
case GovernanceAccountType.ProgramGovernanceV2:
|
||||
return getProgramAccountLabel(value.governance)
|
||||
default:
|
||||
return value.governance.account.governedAccount.toBase58()
|
||||
}
|
||||
}
|
||||
|
||||
//TODO refactor both methods (getMintAccountLabelComponent, getTokenAccountLabelComponent) make it more common
|
||||
function getMintAccountLabelComponent({
|
||||
account,
|
||||
|
@ -114,7 +116,7 @@ const GovernedAccountSelect = ({
|
|||
)
|
||||
}
|
||||
useEffect(() => {
|
||||
if (governedAccounts.length == 1 && autoselectFirst) {
|
||||
if (governedAccounts.length == 1 && autoSelectFirst) {
|
||||
//wait for microtask queue to be empty
|
||||
setTimeout(() => {
|
||||
onChange(governedAccounts[0])
|
||||
|
|
|
@ -34,7 +34,7 @@ const StakeAccountSelect = ({
|
|||
stakeAccounts = [],
|
||||
label,
|
||||
noMaxWidth,
|
||||
autoselectFirst = true,
|
||||
autoSelectFirst = true,
|
||||
}: {
|
||||
onChange
|
||||
value
|
||||
|
@ -44,7 +44,7 @@ const StakeAccountSelect = ({
|
|||
governance?: ProgramAccount<Governance> | null | undefined
|
||||
label?
|
||||
noMaxWidth?: boolean
|
||||
autoselectFirst?: boolean
|
||||
autoSelectFirst?: boolean
|
||||
}) => {
|
||||
function getLabel(value: StakeAccount) {
|
||||
if (value) {
|
||||
|
@ -81,7 +81,7 @@ const StakeAccountSelect = ({
|
|||
)
|
||||
}
|
||||
useEffect(() => {
|
||||
if (stakeAccounts.length == 1 && autoselectFirst) {
|
||||
if (stakeAccounts.length == 1 && autoSelectFirst) {
|
||||
//wait for microtask queue to be empty
|
||||
setTimeout(() => {
|
||||
onChange(stakeAccounts[0])
|
||||
|
|
|
@ -37,7 +37,7 @@ const CastleDeposit = ({
|
|||
const wallet = useWalletStore((s) => s.current)
|
||||
const { realmInfo } = useRealm()
|
||||
const { governedTokenAccountsWithoutNfts } = useGovernanceAssets()
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const programId: PublicKey | undefined = realmInfo?.programId
|
||||
|
||||
// Store CastleDepositForm state
|
||||
|
|
|
@ -37,7 +37,7 @@ const CastleWithdraw = ({
|
|||
const wallet = useWalletStore((s) => s.current)
|
||||
const { realmInfo } = useRealm()
|
||||
const { governedTokenAccountsWithoutNfts } = useGovernanceAssets()
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const programId: PublicKey | undefined = realmInfo?.programId
|
||||
|
||||
// Store CastleWithdrawForm state
|
||||
|
|
|
@ -38,7 +38,7 @@ const ChangeDonation = ({
|
|||
const wallet = useWalletStore((s) => s.current)
|
||||
const { realmInfo } = useRealm()
|
||||
const { governedTokenAccountsWithoutNfts } = useGovernanceAssets()
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const programId: PublicKey | undefined = realmInfo?.programId
|
||||
const [form, setForm] = useState<SplTokenTransferForm>({
|
||||
destinationAccount: '',
|
||||
|
|
|
@ -43,7 +43,7 @@ const CloseTokenAccount = ({
|
|||
const { realm } = useRealm()
|
||||
const wallet = useWalletStore((s) => s.current)
|
||||
const connection = useWalletStore((s) => s.connection)
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const { governedTokenAccountsWithoutNfts } = useGovernanceAssets()
|
||||
const [form, setForm] = useState<CloseTokenAccountForm>()
|
||||
const [formErrors, setFormErrors] = useState({})
|
||||
|
|
|
@ -36,7 +36,7 @@ const CreateAssociatedTokenAccount = ({
|
|||
|
||||
const { assetAccounts } = useGovernanceAssets()
|
||||
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const programId: PublicKey | undefined = realmInfo?.programId
|
||||
const [form, setForm] = useState<CreateAssociatedTokenAccountForm>({})
|
||||
const [formErrors, setFormErrors] = useState({})
|
||||
|
|
|
@ -29,7 +29,7 @@ const CreateTokenMetadata = ({
|
|||
const mintGovernancesWithMintInfo = assetAccounts.filter(
|
||||
(x) => x.type === AccountType.MINT
|
||||
)
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const programId: PublicKey | undefined = realmInfo?.programId
|
||||
const [form, setForm] = useState<CreateTokenMetadataForm>({
|
||||
name: '',
|
||||
|
|
|
@ -30,7 +30,7 @@ const CustomBase64 = ({
|
|||
const { ownVoterWeight } = useRealm()
|
||||
const wallet = useWalletStore((s) => s.current)
|
||||
const { assetAccounts } = useGovernanceAssets()
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const [form, setForm] = useState<Base64InstructionForm>({
|
||||
governedAccount: undefined,
|
||||
base64: '',
|
||||
|
|
|
@ -22,7 +22,7 @@ const Empty = ({
|
|||
})
|
||||
const { ownVoterWeight } = useRealm()
|
||||
const { assetAccounts } = useGovernanceAssets()
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const [formErrors, setFormErrors] = useState({})
|
||||
const { handleSetInstructions } = useContext(NewProposalContext)
|
||||
const handleSetForm = ({ propertyName, value }) => {
|
||||
|
|
|
@ -59,7 +59,7 @@ const DepositForm = ({
|
|||
// eslint-disable-next-line react-hooks/exhaustive-deps -- TODO please fix, it can cause difficult bugs. You might wanna check out https://bobbyhadz.com/blog/react-hooks-exhaustive-deps for info. -@asktree
|
||||
}, [])
|
||||
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const programId: PublicKey | undefined = realmInfo?.programId
|
||||
const [
|
||||
form,
|
||||
|
|
|
@ -59,7 +59,7 @@ const WithdrawForm = ({
|
|||
// eslint-disable-next-line react-hooks/exhaustive-deps -- TODO please fix, it can cause difficult bugs. You might wanna check out https://bobbyhadz.com/blog/react-hooks-exhaustive-deps for info. -@asktree
|
||||
}, [])
|
||||
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const programId: PublicKey | undefined = realmInfo?.programId
|
||||
const [
|
||||
form,
|
||||
|
|
|
@ -29,7 +29,7 @@ export interface InstructionInput {
|
|||
max?: number
|
||||
step?: number
|
||||
onBlur?: () => void
|
||||
shouldBeGoverned?: false | ProgramAccount<Governance> | null
|
||||
shouldBeGoverned?: boolean
|
||||
governance?: ProgramAccount<Governance> | null
|
||||
options?: any[]
|
||||
hide?: boolean | (() => boolean)
|
||||
|
@ -111,7 +111,7 @@ const InstructionInput = ({
|
|||
case InstructionInputType.GOVERNED_ACCOUNT:
|
||||
return (
|
||||
<GovernedAccountSelect
|
||||
autoselectFirst={false}
|
||||
autoSelectFirst={false}
|
||||
label={input.label}
|
||||
governedAccounts={input.options!}
|
||||
onChange={(value) => {
|
||||
|
|
|
@ -27,7 +27,7 @@ const FriktionClaimPendingDeposit = ({
|
|||
const wallet = useWalletStore((s) => s.current)
|
||||
const { realmInfo } = useRealm()
|
||||
const { governedTokenAccountsWithoutNfts } = useGovernanceAssets()
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const programId: PublicKey | undefined = realmInfo?.programId
|
||||
const [form, setForm] = useState<FriktionClaimPendingDepositForm>({
|
||||
governedTokenAccount: undefined,
|
||||
|
|
|
@ -27,7 +27,7 @@ const FriktionClaimPendingWithdraw = ({
|
|||
const wallet = useWalletStore((s) => s.current)
|
||||
const { realmInfo } = useRealm()
|
||||
const { governedTokenAccountsWithoutNfts } = useGovernanceAssets()
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const programId: PublicKey | undefined = realmInfo?.programId
|
||||
const [form, setForm] = useState<FriktionClaimPendingWithdrawForm>({
|
||||
governedTokenAccount: undefined,
|
||||
|
|
|
@ -30,7 +30,7 @@ const FriktionDeposit = ({
|
|||
const wallet = useWalletStore((s) => s.current)
|
||||
const { realmInfo } = useRealm()
|
||||
const { governedTokenAccountsWithoutNfts } = useGovernanceAssets()
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const programId: PublicKey | undefined = realmInfo?.programId
|
||||
const [form, setForm] = useState<FriktionDepositForm>({
|
||||
amount: undefined,
|
||||
|
|
|
@ -30,7 +30,7 @@ const FriktionWithdraw = ({
|
|||
const wallet = useWalletStore((s) => s.current)
|
||||
const { realmInfo } = useRealm()
|
||||
const { governedTokenAccountsWithoutNfts } = useGovernanceAssets()
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const programId: PublicKey | undefined = realmInfo?.programId
|
||||
const [form, setForm] = useState<FriktionWithdrawForm>({
|
||||
amount: undefined,
|
||||
|
|
|
@ -41,7 +41,7 @@ const ConfigureGatewayPlugin = ({
|
|||
const gatewayClient = useVotePluginsClientStore((s) => s.state.gatewayClient)
|
||||
const { assetAccounts } = useGovernanceAssets()
|
||||
const wallet = useWalletStore((s) => s.current)
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const [form, setForm] = useState<ConfigureGatewayForm>()
|
||||
const [formErrors, setFormErrors] = useState({})
|
||||
const { handleSetInstructions } = useContext(NewProposalContext)
|
||||
|
|
|
@ -42,7 +42,7 @@ const CreateGatewayPluginRegistrar = ({
|
|||
const gatewayClient = useVotePluginsClientStore((s) => s.state.gatewayClient)
|
||||
const { assetAccounts } = useGovernanceAssets()
|
||||
const wallet = useWalletStore((s) => s.current)
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const [form, setForm] = useState<CreateGatewayRegistrarForm>()
|
||||
const [formErrors, setFormErrors] = useState({})
|
||||
const { handleSetInstructions } = useContext(NewProposalContext)
|
||||
|
|
|
@ -30,7 +30,7 @@ const GoblinGoldDeposit = ({
|
|||
const wallet = useWalletStore((s) => s.current)
|
||||
const { realmInfo } = useRealm()
|
||||
const { governedTokenAccountsWithoutNfts } = useGovernanceAssets()
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const programId: PublicKey | undefined = realmInfo?.programId
|
||||
|
||||
const [form, setForm] = useState<GoblinGoldDepositForm>({
|
||||
|
|
|
@ -34,7 +34,7 @@ const GoblinGoldWithdraw = ({
|
|||
const wallet = useWalletStore((s) => s.current)
|
||||
const { realmInfo } = useRealm()
|
||||
const { governedTokenAccountsWithoutNfts } = useGovernanceAssets()
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const programId: PublicKey | undefined = realmInfo?.programId
|
||||
|
||||
const [form, setForm] = useState<GoblinGoldWithdrawForm>({
|
||||
|
|
|
@ -79,7 +79,7 @@ const MangoClaimTokens = ({
|
|||
const [table, setTable] = useState<TableInfo[]>([])
|
||||
const connection = useWalletStore((s) => s.connection)
|
||||
const groupName = connection.cluster === 'devnet' ? 'devnet.2' : 'mainnet.1'
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const programId: PublicKey | undefined = realmInfo?.programId
|
||||
const [form, setForm] = useState<MangoClaimTokens>({
|
||||
governedAccount: null,
|
||||
|
|
|
@ -32,7 +32,7 @@ const MakeAddOracle = ({
|
|||
const governedProgramAccounts = assetAccounts.filter(
|
||||
(x) => x.type === AccountType.PROGRAM
|
||||
)
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const programId: PublicKey | undefined = realmInfo?.programId
|
||||
const [form, setForm] = useState<MangoMakeAddOracleForm>({
|
||||
governedAccount: undefined,
|
||||
|
|
|
@ -49,7 +49,7 @@ const MakeAddSpotMarket = ({
|
|||
const governedProgramAccounts = assetAccounts.filter(
|
||||
(x) => x.type === AccountType.PROGRAM
|
||||
)
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const programId: PublicKey | undefined = realmInfo?.programId
|
||||
const [form, setForm] = useState<MangoMakeAddSpotMarketForm>({
|
||||
governedAccount: undefined,
|
||||
|
|
|
@ -35,7 +35,7 @@ const MakeChangeMaxAccounts = ({
|
|||
const governedProgramAccounts = assetAccounts.filter(
|
||||
(x) => x.type === AccountType.PROGRAM
|
||||
)
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const programId: PublicKey | undefined = realmInfo?.programId
|
||||
const [form, setForm] = useState<MangoMakeChangeMaxAccountsForm>({
|
||||
governedAccount: undefined,
|
||||
|
|
|
@ -38,7 +38,7 @@ const MakeChangePerpMarket = ({
|
|||
const governedProgramAccounts = assetAccounts.filter(
|
||||
(x) => x.type === AccountType.PROGRAM
|
||||
)
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const programId: PublicKey | undefined = realmInfo?.programId
|
||||
const [form, setForm] = useState<MangoMakeChangePerpMarketForm>({
|
||||
governedAccount: undefined,
|
||||
|
|
|
@ -41,7 +41,7 @@ const MakeChangeQuoteParams = ({
|
|||
const governedProgramAccounts = assetAccounts.filter(
|
||||
(x) => x.type === AccountType.PROGRAM
|
||||
)
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const programId: PublicKey | undefined = realmInfo?.programId
|
||||
const [form, setForm] = useState<MangoMakeChangeSpotMarketForm>({
|
||||
governedAccount: undefined,
|
||||
|
|
|
@ -37,7 +37,7 @@ const MakeChangeReferralFeeParams = ({
|
|||
const governedProgramAccounts = assetAccounts.filter(
|
||||
(x) => x.type === AccountType.PROGRAM
|
||||
)
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const programId: PublicKey | undefined = realmInfo?.programId
|
||||
const [form, setForm] = useState<MangoMakeChangeReferralFeeParams>({
|
||||
governedAccount: undefined,
|
||||
|
|
|
@ -37,7 +37,7 @@ const MakeChangeReferralFeeParams2 = ({
|
|||
const governedProgramAccounts = assetAccounts.filter(
|
||||
(x) => x.type === AccountType.PROGRAM
|
||||
)
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const programId: PublicKey | undefined = realmInfo?.programId
|
||||
const [form, setForm] = useState<MangoMakeChangeReferralFeeParams2>({
|
||||
governedAccount: undefined,
|
||||
|
|
|
@ -43,7 +43,7 @@ const MakeChangeSpotMarket = ({
|
|||
const governedProgramAccounts = assetAccounts.filter(
|
||||
(x) => x.type === AccountType.PROGRAM
|
||||
)
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const programId: PublicKey | undefined = realmInfo?.programId
|
||||
const [form, setForm] = useState<MangoMakeChangeSpotMarketForm>({
|
||||
governedAccount: undefined,
|
||||
|
|
|
@ -45,7 +45,7 @@ const MakeCreatePerpMarket = ({
|
|||
const governedProgramAccounts = assetAccounts.filter(
|
||||
(x) => x.type === AccountType.PROGRAM
|
||||
)
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const programId: PublicKey | undefined = realmInfo?.programId
|
||||
const [form, setForm] = useState<MangoMakeCreatePerpMarketForm>({
|
||||
governedAccount: undefined,
|
||||
|
|
|
@ -38,7 +38,7 @@ const MakeDepositToMangoAccount = ({
|
|||
const { governedTokenAccounts } = useGovernanceAssets()
|
||||
const tokenAccounts = governedTokenAccounts.filter((x) => x.isToken)
|
||||
const connection = useWalletStore((s) => s.connection)
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const programId: PublicKey | undefined = realmInfo?.programId
|
||||
const [form, setForm] = useState<MangoDepositToMangoAccountForm>({
|
||||
governedAccount: null,
|
||||
|
|
|
@ -40,7 +40,7 @@ const MakeDepositToMangoAccountCsv = ({
|
|||
const { governedTokenAccounts } = useGovernanceAssets()
|
||||
const tokenAccounts = governedTokenAccounts.filter((x) => x.isToken)
|
||||
const connection = useWalletStore((s) => s.connection)
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const programId: PublicKey | undefined = realmInfo?.programId
|
||||
// It state will contain the error when
|
||||
// correct file extension is not used
|
||||
|
|
|
@ -39,7 +39,7 @@ const MakeRemoveOracle = ({
|
|||
const governedProgramAccounts = assetAccounts.filter(
|
||||
(x) => x.type === AccountType.PROGRAM
|
||||
)
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const programId: PublicKey | undefined = realmInfo?.programId
|
||||
const [form, setForm] = useState<MangoRemoveOracleForm>({
|
||||
governedAccount: null,
|
||||
|
|
|
@ -42,7 +42,7 @@ const MakeRemovePerpMarket = ({
|
|||
(x) => x.type === AccountType.PROGRAM
|
||||
)
|
||||
const connection = useWalletStore((s) => s.connection)
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const programId: PublicKey | undefined = realmInfo?.programId
|
||||
const [form, setForm] = useState<MangoRemovePerpMarketForm>({
|
||||
governedAccount: null,
|
||||
|
|
|
@ -42,7 +42,7 @@ const MakeRemoveSpotMarket = ({
|
|||
(x) => x.type === AccountType.PROGRAM
|
||||
)
|
||||
const connection = useWalletStore((s) => s.connection)
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const programId: PublicKey | undefined = realmInfo?.programId
|
||||
const [form, setForm] = useState<MangoRemoveSpotMarketForm>({
|
||||
governedAccount: null,
|
||||
|
|
|
@ -41,7 +41,7 @@ const MakeSetMarketMode = ({
|
|||
const governedProgramAccounts = assetAccounts.filter(
|
||||
(x) => x.type === AccountType.PROGRAM
|
||||
)
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const programId: PublicKey | undefined = realmInfo?.programId
|
||||
const [form, setForm] = useState<MangoMakeSetMarketModeForm>({
|
||||
governedAccount: null,
|
||||
|
|
|
@ -41,7 +41,7 @@ const MakeSwapSpotMarket = ({
|
|||
(x) => x.type === AccountType.PROGRAM
|
||||
)
|
||||
const connection = useWalletStore((s) => s.connection.current)
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const programId: PublicKey | undefined = realmInfo?.programId
|
||||
const [form, setForm] = useState<MangoSwapSpotMarketForm>({
|
||||
governedAccount: null,
|
||||
|
|
|
@ -56,7 +56,7 @@ const EditToken = ({
|
|||
(x) => x.type === AccountType.PROGRAM
|
||||
)
|
||||
const { connection } = useWalletStore()
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const programId: PublicKey | undefined = realmInfo?.programId
|
||||
const [form, setForm] = useState<EditTokenForm>({
|
||||
governedAccount: null,
|
||||
|
|
|
@ -54,7 +54,7 @@ const PerpCreate = ({
|
|||
(x) => x.type === AccountType.PROGRAM
|
||||
)
|
||||
const { connection } = useWalletStore()
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const programId: PublicKey | undefined = realmInfo?.programId
|
||||
const [form, setForm] = useState<PerpCreateForm>({
|
||||
governedAccount: null,
|
||||
|
|
|
@ -52,7 +52,7 @@ const PerpEdit = ({
|
|||
(x) => x.type === AccountType.PROGRAM
|
||||
)
|
||||
const { connection } = useWalletStore()
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const programId: PublicKey | undefined = realmInfo?.programId
|
||||
const [form, setForm] = useState<PerpEditForm>({
|
||||
governedAccount: null,
|
||||
|
|
|
@ -43,7 +43,7 @@ const EditToken = ({
|
|||
(x) => x.type === AccountType.PROGRAM
|
||||
)
|
||||
const { connection } = useWalletStore()
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const programId: PublicKey | undefined = realmInfo?.programId
|
||||
const [form, setForm] = useState<Serum3RegisterMarketForm>({
|
||||
governedAccount: null,
|
||||
|
|
|
@ -56,7 +56,7 @@ const TokenRegister = ({
|
|||
(x) => x.type === AccountType.PROGRAM
|
||||
)
|
||||
const { connection } = useWalletStore()
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const programId: PublicKey | undefined = realmInfo?.programId
|
||||
const [form, setForm] = useState<RegisterTokenForm>({
|
||||
governedAccount: null,
|
||||
|
|
|
@ -40,7 +40,7 @@ const TokenRegisterTrustless = ({
|
|||
(x) => x.type === AccountType.SOL
|
||||
)
|
||||
const { connection } = useWalletStore()
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const programId: PublicKey | undefined = realmInfo?.programId
|
||||
const [form, setForm] = useState<TokenRegisterTrustlessForm>({
|
||||
governedAccount: null,
|
||||
|
|
|
@ -83,7 +83,7 @@ const MeanCreateAccountComponent = ({ index, governance }: Props) => {
|
|||
|
||||
// governedTokenAccount
|
||||
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const { governedTokenAccountsWithoutNfts } = useGovernanceAssets()
|
||||
|
||||
// instruction
|
||||
|
|
|
@ -40,7 +40,7 @@ const MeanFundAccountComponent = ({ index, governance }: Props) => {
|
|||
|
||||
// governedTokenAccount
|
||||
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const { governedTokenAccountsWithoutNfts } = useGovernanceAssets()
|
||||
|
||||
// instruction
|
||||
|
|
|
@ -35,7 +35,7 @@ const Mint = ({
|
|||
const mintGovernancesWithMintInfo = assetAccounts.filter(
|
||||
(x) => x.type === AccountType.MINT
|
||||
)
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const programId: PublicKey | undefined = realmInfo?.programId
|
||||
const [form, setForm] = useState<MintForm>({
|
||||
destinationAccount: '',
|
||||
|
|
|
@ -45,7 +45,7 @@ const ConfigureNftPluginCollection = ({
|
|||
const nftClient = useVotePluginsClientStore((s) => s.state.nftClient)
|
||||
const { assetAccounts } = useGovernanceAssets()
|
||||
const wallet = useWalletStore((s) => s.current)
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const [form, setForm] = useState<ConfigureCollectionForm>()
|
||||
const [formErrors, setFormErrors] = useState({})
|
||||
const { handleSetInstructions } = useContext(NewProposalContext)
|
||||
|
|
|
@ -37,7 +37,7 @@ const CreateNftPluginMaxVoterWeightRecord = ({
|
|||
const nftClient = useVotePluginsClientStore((s) => s.state.nftClient)
|
||||
const { assetAccounts } = useGovernanceAssets()
|
||||
const wallet = useWalletStore((s) => s.current)
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const [form, setForm] = useState<CreateNftMaxVoterWeightRecord>()
|
||||
const [formErrors, setFormErrors] = useState({})
|
||||
const { handleSetInstructions } = useContext(NewProposalContext)
|
||||
|
|
|
@ -34,7 +34,7 @@ const CreateNftPluginRegistrar = ({
|
|||
const nftClient = useVotePluginsClientStore((s) => s.state.nftClient)
|
||||
const { assetAccounts } = useGovernanceAssets()
|
||||
const wallet = useWalletStore((s) => s.current)
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const [form, setForm] = useState<CreateNftRegistrarForm>()
|
||||
const [formErrors, setFormErrors] = useState({})
|
||||
const { handleSetInstructions } = useContext(NewProposalContext)
|
||||
|
|
|
@ -42,7 +42,7 @@ const RealmConfig = ({
|
|||
}) => {
|
||||
const { realm, mint, realmInfo } = useRealm()
|
||||
const wallet = useWalletStore((s) => s.current)
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const { assetAccounts } = useGovernanceAssets()
|
||||
const realmAuthority = assetAccounts.find(
|
||||
(x) =>
|
||||
|
|
|
@ -69,7 +69,7 @@ const SagaPreOrder = ({
|
|||
token.extensions.token?.account.owner.toBase58()
|
||||
)
|
||||
)
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const programId: PublicKey | undefined = realmInfo?.programId
|
||||
const [form, setForm] = useState<SagaPhoneForm>({
|
||||
governedAccount: null,
|
||||
|
|
|
@ -38,7 +38,7 @@ const CreateObligationAccount = ({
|
|||
}
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks -- TODO this is potentially quite serious! please fix next time the file is edited, -@asktree
|
||||
const { assetAccounts } = useGovernanceAssets()
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const programId: PublicKey | undefined = realmInfo?.programId
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks -- TODO this is potentially quite serious! please fix next time the file is edited, -@asktree
|
||||
const [form, setForm] = useState<CreateSolendObligationAccountForm>({})
|
||||
|
|
|
@ -42,7 +42,7 @@ const DepositReserveLiquidityAndObligationCollateral = ({
|
|||
return <>This instruction does not support {connection.cluster}</>
|
||||
}
|
||||
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const programId: PublicKey | undefined = realmInfo?.programId
|
||||
const [
|
||||
form,
|
||||
|
|
|
@ -40,7 +40,7 @@ const InitObligationAccount = ({
|
|||
return <>This instruction does not support {connection.cluster}</>
|
||||
}
|
||||
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const programId: PublicKey | undefined = realmInfo?.programId
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks -- TODO this is potentially quite serious! please fix next time the file is edited, -@asktree
|
||||
const [form, setForm] = useState<InitSolendObligationAccountForm>({})
|
||||
|
|
|
@ -41,7 +41,7 @@ const RefreshObligation = ({
|
|||
return <>This instruction does not support {connection.cluster}</>
|
||||
}
|
||||
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const programId: PublicKey | undefined = realmInfo?.programId
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks -- TODO this is potentially quite serious! please fix next time the file is edited, -@asktree
|
||||
const [form, setForm] = useState<RefreshObligationForm>({})
|
||||
|
|
|
@ -35,7 +35,7 @@ const RefreshReserve = ({
|
|||
const { realmInfo } = useRealm()
|
||||
|
||||
const { assetAccounts } = useGovernanceAssets()
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
|
||||
const programId: PublicKey | undefined = realmInfo?.programId
|
||||
const [form, setForm] = useState<RefreshReserveForm>({})
|
||||
|
|
|
@ -43,7 +43,7 @@ const WithdrawObligationCollateralAndRedeemReserveLiquidity = ({
|
|||
return <>This instruction does not support {connection.cluster}</>
|
||||
}
|
||||
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const programId: PublicKey | undefined = realmInfo?.programId
|
||||
const [
|
||||
form,
|
||||
|
|
|
@ -36,7 +36,7 @@ const SplTokenTransfer = ({
|
|||
const wallet = useWalletStore((s) => s.current)
|
||||
const { realmInfo } = useRealm()
|
||||
const { governedTokenAccountsWithoutNfts } = useGovernanceAssets()
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const programId: PublicKey | undefined = realmInfo?.programId
|
||||
const [form, setForm] = useState<SplTokenTransferForm>({
|
||||
destinationAccount: '',
|
||||
|
|
|
@ -51,7 +51,7 @@ const CancelStream = ({
|
|||
const strmProgram = new PublicKey(STREAMFLOW_PROGRAM_ID)
|
||||
|
||||
const { assetAccounts } = useGovernanceAssets()
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const programId: PublicKey | undefined = strmProgram
|
||||
|
||||
const [form, setForm] = useState<CancelStreamForm>({
|
||||
|
|
|
@ -117,7 +117,7 @@ const CreateStream = ({
|
|||
|
||||
const { assetAccounts } = useGovernanceAssets()
|
||||
const treasuryInfo = useTreasuryInfo()
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const programId: PublicKey | undefined = strmProgram
|
||||
const [releaseUnitIdx, setReleaseUnitIdx] = useState<number>(0)
|
||||
const [startOnApproval, setStartOnApproval] = useState<boolean>(true)
|
||||
|
|
|
@ -31,7 +31,7 @@ const TransferDomainName = ({
|
|||
governance: ProgramAccount<Governance> | null
|
||||
}) => {
|
||||
const connection = useWalletStore((s) => s.connection.current)
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const { handleSetInstructions } = useContext(NewProposalContext)
|
||||
|
||||
const { assetAccounts } = useGovernanceAssets()
|
||||
|
|
|
@ -27,7 +27,7 @@ const UpdateTokenMetadata = ({
|
|||
const mintGovernancesWithMintInfo = assetAccounts.filter(
|
||||
(x) => x.type === AccountType.MINT
|
||||
)
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const programId: PublicKey | undefined = realmInfo?.programId
|
||||
const [form, setForm] = useState<UpdateTokenMetadataForm>({
|
||||
name: '',
|
||||
|
|
|
@ -32,7 +32,7 @@ const DeactivateValidatorStake = ({
|
|||
const connection = useWalletStore((s) => s.connection)
|
||||
const programId: PublicKey = StakeProgram.programId
|
||||
const { governedTokenAccountsWithoutNfts } = useGovernanceAssets()
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
|
||||
const [form, setForm] = useState<ValidatorDeactivateStakeForm>({
|
||||
stakingAccount: undefined,
|
||||
|
|
|
@ -35,7 +35,7 @@ const StakeValidator = ({
|
|||
const connection = useWalletStore((s) => s.connection)
|
||||
const programId: PublicKey = StakeProgram.programId
|
||||
const { governedTokenAccountsWithoutNfts } = useGovernanceAssets()
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const wallet = useWalletStore((s) => s.current)
|
||||
|
||||
const [form, setForm] = useState<ValidatorStakingForm>({
|
||||
|
|
|
@ -36,7 +36,7 @@ const WithdrawValidatorStake = ({
|
|||
const connection = useWalletStore((s) => s.connection)
|
||||
const programId: PublicKey = StakeProgram.programId
|
||||
const { governedTokenAccountsWithoutNfts } = useGovernanceAssets()
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
|
||||
const [form, setForm] = useState<ValidatorWithdrawStakeForm>({
|
||||
stakingAccount: undefined,
|
||||
|
|
|
@ -34,7 +34,7 @@ const CreateVsrRegistrar = ({
|
|||
}) => {
|
||||
const { realm, realmInfo } = useRealm()
|
||||
const { assetAccounts } = useGovernanceAssets()
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const [form, setForm] = useState<CreateVsrRegistrarForm>()
|
||||
const [formErrors, setFormErrors] = useState({})
|
||||
const { handleSetInstructions } = useContext(NewProposalContext)
|
||||
|
|
|
@ -51,7 +51,7 @@ const VotingMintConfig = ({
|
|||
}) => {
|
||||
const { realm } = useRealm()
|
||||
const { assetAccounts } = useGovernanceAssets()
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const [form, setForm] = useState<ConfigureCollectionForm>()
|
||||
const [formErrors, setFormErrors] = useState({})
|
||||
const { handleSetInstructions } = useContext(NewProposalContext)
|
||||
|
|
|
@ -37,7 +37,7 @@ const ProgramUpgrade = ({
|
|||
const governedProgramAccounts = assetAccounts.filter(
|
||||
(x) => x.type === AccountType.PROGRAM
|
||||
)
|
||||
const shouldBeGoverned = index !== 0 && governance
|
||||
const shouldBeGoverned = !!(index !== 0 && governance)
|
||||
const programId: PublicKey | undefined = realmInfo?.programId
|
||||
const [form, setForm] = useState<ProgramUpgradeForm>({
|
||||
governedAccount: undefined,
|
||||
|
|
|
@ -1,12 +1,20 @@
|
|||
import create, { State } from 'zustand'
|
||||
import axios from 'axios'
|
||||
import {
|
||||
getNativeTreasuryAddress,
|
||||
Governance,
|
||||
GovernanceAccountType,
|
||||
Realm,
|
||||
TOKEN_PROGRAM_ID,
|
||||
ProgramAccount,
|
||||
} from '@solana/spl-governance'
|
||||
import { ProgramAccount } from '@solana/spl-governance'
|
||||
import {
|
||||
ParsedAccountData,
|
||||
PublicKey,
|
||||
AccountInfo as AccountInfoGeneric,
|
||||
} from '@solana/web3.js'
|
||||
import { AccountInfo, MintInfo } from '@solana/spl-token'
|
||||
import { TokenAccountLayout } from '@blockworks-foundation/mango-client'
|
||||
import {
|
||||
AUXILIARY_TOKEN_ACCOUNTS,
|
||||
DEFAULT_NATIVE_SOL_MINT,
|
||||
|
@ -18,17 +26,14 @@ import {
|
|||
import {
|
||||
AccountInfoGen,
|
||||
getMultipleAccountInfoChunked,
|
||||
MintAccount,
|
||||
parseMintAccountData,
|
||||
parseTokenAccountData,
|
||||
TokenAccount,
|
||||
TokenProgramAccount,
|
||||
} from '@utils/tokens'
|
||||
import { ParsedAccountData, PublicKey } from '@solana/web3.js'
|
||||
import { AccountInfo, MintInfo } from '@solana/spl-token'
|
||||
import { AccountInfo as AccountInfoGeneric } from '@solana/web3.js'
|
||||
import { TokenAccountLayout } from '@blockworks-foundation/mango-client'
|
||||
import tokenService from '@utils/services/token'
|
||||
import { ConnectionContext } from '@utils/connection'
|
||||
import axios from 'axios'
|
||||
import {
|
||||
AccountType,
|
||||
AccountTypeGeneric,
|
||||
|
@ -40,7 +45,7 @@ import {
|
|||
AccountTypeToken,
|
||||
AssetAccount,
|
||||
} from '@utils/uiTypes/assets'
|
||||
import group from '@utils/group'
|
||||
import { chunks } from '@utils/helpers'
|
||||
|
||||
const tokenAccountOwnerOffset = 32
|
||||
|
||||
|
@ -49,11 +54,13 @@ interface SolAccInfo {
|
|||
acc: any
|
||||
nativeSolAddress: PublicKey
|
||||
}
|
||||
|
||||
interface GovernanceAssetsStore extends State {
|
||||
governancesArray: ProgramAccount<Governance>[]
|
||||
governedTokenAccounts: AssetAccount[]
|
||||
assetAccounts: AssetAccount[]
|
||||
loadGovernedAccounts: boolean
|
||||
|
||||
setGovernancesArray: (
|
||||
connection: ConnectionContext,
|
||||
realm: ProgramAccount<Realm>,
|
||||
|
@ -81,21 +88,32 @@ const defaultState = {
|
|||
|
||||
const useGovernanceAssetsStore = create<GovernanceAssetsStore>((set, _get) => ({
|
||||
...defaultState,
|
||||
setGovernancesArray: (connection, realm, governances) => {
|
||||
const array = Object.keys(governances)
|
||||
|
||||
setGovernancesArray: (
|
||||
connection: ConnectionContext,
|
||||
realm: ProgramAccount<Realm>,
|
||||
governances: {
|
||||
[governance: string]: ProgramAccount<Governance>
|
||||
}
|
||||
) => {
|
||||
const array: ProgramAccount<Governance>[] = Object.keys(governances)
|
||||
.filter((gpk) => !HIDDEN_GOVERNANCES.has(gpk))
|
||||
.map((key) => governances[key])
|
||||
|
||||
set((s) => {
|
||||
s.governancesArray = array
|
||||
})
|
||||
|
||||
_get().getGovernedAccounts(connection, realm)
|
||||
},
|
||||
|
||||
getGovernedAccounts: async (connection, realm) => {
|
||||
set((s) => {
|
||||
s.loadGovernedAccounts = true
|
||||
s.governedTokenAccounts = []
|
||||
s.assetAccounts = []
|
||||
})
|
||||
|
||||
const governancesArray = _get().governancesArray
|
||||
const accounts = governancesArray.length
|
||||
? await getAccountsForGovernances(connection, realm, governancesArray)
|
||||
|
@ -111,27 +129,33 @@ const useGovernanceAssetsStore = create<GovernanceAssetsStore>((set, _get) => ({
|
|||
x.type === AccountType.NFT ||
|
||||
x.type === AccountType.SOL
|
||||
)
|
||||
.filter(filterOutHiddenAccs)
|
||||
s.assetAccounts = accounts.filter(filterOutHiddenAccs)
|
||||
.filter(filterOutHiddenAccounts)
|
||||
s.assetAccounts = accounts.filter(filterOutHiddenAccounts)
|
||||
})
|
||||
},
|
||||
refetchGovernanceAccounts: async (connection, realm, governancePk) => {
|
||||
refetchGovernanceAccounts: async (
|
||||
connection: ConnectionContext,
|
||||
realm: ProgramAccount<Realm>,
|
||||
governancePk: PublicKey
|
||||
) => {
|
||||
set((s) => {
|
||||
s.loadGovernedAccounts = false
|
||||
})
|
||||
|
||||
const governancesArray = _get().governancesArray.filter(
|
||||
(x) => x.pubkey?.toBase58() === governancePk.toBase58()
|
||||
const governancesArray = _get().governancesArray.filter((x) =>
|
||||
x.pubkey.equals(governancePk)
|
||||
)
|
||||
|
||||
const previousAccounts = _get().assetAccounts.filter(
|
||||
(x) => x.governance?.pubkey?.toBase58() !== governancePk.toBase58()
|
||||
(x) => !x.governance.pubkey.equals(governancePk)
|
||||
)
|
||||
|
||||
const accounts = await getAccountsForGovernances(
|
||||
connection,
|
||||
realm,
|
||||
governancesArray
|
||||
)
|
||||
|
||||
set((s) => {
|
||||
s.loadGovernedAccounts = false
|
||||
s.governedTokenAccounts = [...previousAccounts, ...accounts]
|
||||
|
@ -141,9 +165,9 @@ const useGovernanceAssetsStore = create<GovernanceAssetsStore>((set, _get) => ({
|
|||
x.type === AccountType.NFT ||
|
||||
x.type === AccountType.SOL
|
||||
)
|
||||
.filter(filterOutHiddenAccs)
|
||||
.filter(filterOutHiddenAccounts)
|
||||
s.assetAccounts = [...previousAccounts, ...accounts].filter(
|
||||
filterOutHiddenAccs
|
||||
filterOutHiddenAccounts
|
||||
)
|
||||
})
|
||||
},
|
||||
|
@ -154,50 +178,73 @@ const getTokenAccountObj = async (
|
|||
governance: ProgramAccount<Governance>,
|
||||
tokenAccount: TokenProgramAccount<AccountInfo>,
|
||||
mintAccounts: TokenProgramAccount<MintInfo>[]
|
||||
) => {
|
||||
): Promise<AccountTypeNFT | AccountTypeToken | null> => {
|
||||
const isNftAccount =
|
||||
tokenAccount.account.mint.toBase58() === DEFAULT_NFT_TREASURY_MINT
|
||||
const mint = mintAccounts.find(
|
||||
(x) => x.publicKey.toBase58() === tokenAccount.account.mint.toBase58()
|
||||
)
|
||||
|
||||
const mint = mintAccounts.find((x) =>
|
||||
x.publicKey.equals(tokenAccount.account.mint)
|
||||
)!
|
||||
|
||||
if (isNftAccount) {
|
||||
return new AccountTypeNFT(tokenAccount, mint!, governance)
|
||||
return new AccountTypeNFT(tokenAccount, mint, governance)
|
||||
}
|
||||
|
||||
if (
|
||||
mint?.account.supply &&
|
||||
mint?.account.supply.cmpn(1) !== 0 &&
|
||||
mint.account.supply &&
|
||||
mint.account.supply.cmpn(1) !== 0 &&
|
||||
mint.publicKey.toBase58() !== DEFAULT_NATIVE_SOL_MINT
|
||||
) {
|
||||
return new AccountTypeToken(tokenAccount, mint!, governance)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
const getSolAccountsObj = async (
|
||||
connection: ConnectionContext,
|
||||
accounts: AssetAccount[],
|
||||
solAccountsInfo: SolAccInfo[],
|
||||
mintAccounts: TokenProgramAccount<MintInfo>[],
|
||||
mintAccounts: TokenProgramAccount<MintAccount>[],
|
||||
governances: ProgramAccount<Governance>[]
|
||||
) => {
|
||||
const solAccs: AccountTypeSol[] = []
|
||||
for (const i of solAccountsInfo) {
|
||||
const mint = mintAccounts.find((x) => x.publicKey.toBase58() === WSOL_MINT)
|
||||
const governance = governances.find(
|
||||
(x) => x.pubkey.toBase58() === i.governancePk.toBase58()
|
||||
)
|
||||
): Promise<AssetAccount[]> => {
|
||||
const solAccounts: AccountTypeSol[] = []
|
||||
|
||||
const wsolMintAccount = mintAccounts.find(
|
||||
(x) => x.publicKey.toBase58() === WSOL_MINT
|
||||
)! // WSOL should be here
|
||||
|
||||
for (const solAccountInfo of solAccountsInfo) {
|
||||
const governance = governances.find((x) =>
|
||||
x.pubkey.equals(solAccountInfo.governancePk)
|
||||
)! // Governance should be here
|
||||
|
||||
const account = await getSolAccountObj(
|
||||
governance!,
|
||||
governance,
|
||||
connection,
|
||||
mint!,
|
||||
wsolMintAccount,
|
||||
accounts,
|
||||
i
|
||||
solAccountInfo
|
||||
)
|
||||
|
||||
if (account) {
|
||||
solAccs.push(account)
|
||||
solAccounts.push(account)
|
||||
}
|
||||
}
|
||||
return solAccs as AssetAccount[]
|
||||
|
||||
return solAccounts
|
||||
}
|
||||
|
||||
// Return array without duplicates
|
||||
const uniquePublicKey = (array: PublicKey[]): PublicKey[] => {
|
||||
return Array.from(
|
||||
array.reduce((mintsPks, publicKey) => {
|
||||
// Transform to string for Set to be able to identify duplicates
|
||||
mintsPks.add(publicKey.toBase58())
|
||||
|
||||
return mintsPks
|
||||
}, new Set<string>())
|
||||
).map((address) => new PublicKey(address))
|
||||
}
|
||||
|
||||
const getTokenAssetAccounts = async (
|
||||
|
@ -210,25 +257,32 @@ const getTokenAssetAccounts = async (
|
|||
connection: ConnectionContext
|
||||
) => {
|
||||
const accounts: AssetAccount[] = []
|
||||
const mintsPks = [...tokenAccounts.map((x) => x.account.mint)]
|
||||
//WSOL is used as mint for sol accounts to calculate amounts
|
||||
if (!mintsPks.find((x) => x.toBase58() === WSOL_MINT)) {
|
||||
|
||||
const mintsPks = uniquePublicKey(
|
||||
tokenAccounts.map((tokenAccount) => tokenAccount.account.mint)
|
||||
)
|
||||
|
||||
// WSOL must be in the mintsPks array
|
||||
// WSOL is used as mint for sol accounts to calculate amounts
|
||||
if (!mintsPks.some((x) => x.toBase58() === WSOL_MINT)) {
|
||||
mintsPks.push(new PublicKey(WSOL_MINT))
|
||||
}
|
||||
const mintAccounts = mintsPks.length
|
||||
? await getMintAccountsInfo(connection, [...mintsPks])
|
||||
: []
|
||||
const nativeSolAddresses = await Promise.all(
|
||||
governances.map((x) => getNativeTreasuryAddress(realm.owner, x!.pubkey))
|
||||
|
||||
const [mintAccounts, ...nativeSolAddresses] = await Promise.all([
|
||||
getMintAccountsInfo(connection, mintsPks),
|
||||
...governances.map((x) => getNativeTreasuryAddress(realm.owner, x.pubkey)),
|
||||
])
|
||||
|
||||
const govNativeSolAddress = nativeSolAddresses.map((x, index) => ({
|
||||
governanceAcc: governances[index],
|
||||
governancePk: governances[index].pubkey,
|
||||
nativeSolAddress: x,
|
||||
}))
|
||||
|
||||
const solAccountsInfo = await getSolAccountsInfo(
|
||||
connection,
|
||||
govNativeSolAddress
|
||||
)
|
||||
const govNativeSolAddress = nativeSolAddresses.map((x, index) => {
|
||||
return {
|
||||
governanceAcc: governances[index],
|
||||
governancePk: governances[index].pubkey,
|
||||
nativeSolAddress: x,
|
||||
}
|
||||
})
|
||||
const solAccs = await getSolAccountsInfo(connection, govNativeSolAddress)
|
||||
|
||||
for (const tokenAccount of tokenAccounts) {
|
||||
let governance = governances.find(
|
||||
|
@ -261,24 +315,26 @@ const getTokenAssetAccounts = async (
|
|||
const mint = mintAccounts.find(
|
||||
(x) => x.publicKey.toBase58() === tokenAccount.account.mint.toBase58()
|
||||
)
|
||||
const account = new AccountTypeAuxiliaryToken(tokenAccount, mint)
|
||||
if (account) {
|
||||
accounts.push(account)
|
||||
|
||||
if (mint) {
|
||||
const account = new AccountTypeAuxiliaryToken(tokenAccount, mint)
|
||||
|
||||
if (account) {
|
||||
accounts.push(account)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const solAccounts = await getSolAccountsObj(
|
||||
connection,
|
||||
accounts,
|
||||
solAccs,
|
||||
solAccountsInfo,
|
||||
mintAccounts,
|
||||
governances
|
||||
)
|
||||
if (solAccounts.length) {
|
||||
accounts.push(...solAccounts)
|
||||
}
|
||||
|
||||
return accounts
|
||||
return [...accounts, ...solAccounts]
|
||||
}
|
||||
|
||||
const getMintAccounts = (
|
||||
|
@ -305,38 +361,27 @@ const getMintAccounts = (
|
|||
|
||||
const getProgramAssetAccounts = (
|
||||
programGovernances: ProgramAccount<Governance>[]
|
||||
) => {
|
||||
const accounts: AccountTypeProgram[] = []
|
||||
programGovernances.forEach((programGov) => {
|
||||
const account = new AccountTypeProgram(programGov!)
|
||||
if (account) {
|
||||
accounts.push(account)
|
||||
}
|
||||
})
|
||||
return accounts
|
||||
): AccountTypeProgram[] => {
|
||||
return programGovernances.map(
|
||||
(programGov) => new AccountTypeProgram(programGov)
|
||||
)
|
||||
}
|
||||
|
||||
const getGenericAssetAccounts = (
|
||||
genericGovernances: ProgramAccount<Governance>[]
|
||||
) => {
|
||||
const accounts: AccountTypeGeneric[] = []
|
||||
genericGovernances.forEach((programGov) => {
|
||||
const account = new AccountTypeGeneric(programGov)
|
||||
if (account) {
|
||||
accounts.push(account)
|
||||
}
|
||||
})
|
||||
return accounts
|
||||
): AccountTypeGeneric[] => {
|
||||
return genericGovernances.map(
|
||||
(programGov) => new AccountTypeGeneric(programGov)
|
||||
)
|
||||
}
|
||||
|
||||
const getGovernancesByAccountTypes = (
|
||||
governancesArray: ProgramAccount<Governance>[],
|
||||
types: GovernanceAccountType[]
|
||||
) => {
|
||||
const governancesFiltered = governancesArray.filter((gov) =>
|
||||
types.some((t) => gov.account?.accountType === t)
|
||||
): ProgramAccount<Governance>[] => {
|
||||
return governancesArray.filter((gov) =>
|
||||
types.some((t) => gov.account.accountType === t)
|
||||
)
|
||||
return governancesFiltered
|
||||
}
|
||||
|
||||
const getSolAccountObj = async (
|
||||
|
@ -344,87 +389,282 @@ const getSolAccountObj = async (
|
|||
connection: ConnectionContext,
|
||||
mint: TokenProgramAccount<MintInfo>,
|
||||
accounts: AssetAccount[],
|
||||
solAcc: SolAccInfo
|
||||
) => {
|
||||
if (solAcc.acc) {
|
||||
const tokenAccountsOwnedBySolAccountInfo = await connection.current.getTokenAccountsByOwner(
|
||||
solAcc.nativeSolAddress,
|
||||
{
|
||||
programId: TOKEN_PROGRAM_ID,
|
||||
}
|
||||
)
|
||||
const tokenAccountsOwnedBySolAccounts = tokenAccountsOwnedBySolAccountInfo.value.map(
|
||||
(x) => {
|
||||
const publicKey = x.pubkey
|
||||
const data = Buffer.from(x.account.data)
|
||||
const account = parseTokenAccountData(publicKey, data)
|
||||
return { publicKey, account }
|
||||
}
|
||||
)
|
||||
const groups = group(tokenAccountsOwnedBySolAccounts)
|
||||
const results = await Promise.all(
|
||||
{ acc, nativeSolAddress }: SolAccInfo
|
||||
): Promise<AccountTypeSol | null> => {
|
||||
if (!acc) {
|
||||
return null
|
||||
}
|
||||
|
||||
const tokenAccountsOwnedBySolAccountInfo = await connection.current.getTokenAccountsByOwner(
|
||||
nativeSolAddress,
|
||||
{
|
||||
programId: TOKEN_PROGRAM_ID,
|
||||
}
|
||||
)
|
||||
|
||||
const tokenAccountsOwnedBySolAccounts = tokenAccountsOwnedBySolAccountInfo.value.map(
|
||||
({ pubkey: publicKey, account: { data: encodedData } }) => {
|
||||
const data = Buffer.from(encodedData)
|
||||
const account = parseTokenAccountData(publicKey, data)
|
||||
return { publicKey, account }
|
||||
}
|
||||
)
|
||||
|
||||
const groups = chunks(tokenAccountsOwnedBySolAccounts, 100)
|
||||
|
||||
const mintAccounts = (
|
||||
await Promise.all(
|
||||
groups.map((group) => {
|
||||
if (group.length) {
|
||||
return getMintAccountsInfo(
|
||||
connection,
|
||||
group.map((x) => x.account.mint)
|
||||
)
|
||||
} else {
|
||||
if (!group.length) {
|
||||
return []
|
||||
}
|
||||
|
||||
return getMintAccountsInfo(
|
||||
connection,
|
||||
group.map((x) => x.account.mint)
|
||||
)
|
||||
})
|
||||
)
|
||||
).flat()
|
||||
|
||||
const mintAccounts = results.flat()
|
||||
for (const acc of tokenAccountsOwnedBySolAccounts) {
|
||||
const account = await getTokenAccountObj(governance, acc, mintAccounts)
|
||||
|
||||
for (const acc of tokenAccountsOwnedBySolAccounts) {
|
||||
const account = await getTokenAccountObj(governance, acc, mintAccounts)
|
||||
if (account) {
|
||||
accounts.push(account)
|
||||
}
|
||||
if (account) {
|
||||
accounts.push(account)
|
||||
}
|
||||
const minRentAmount = await connection.current.getMinimumBalanceForRentExemption(
|
||||
0
|
||||
)
|
||||
const solAccount = solAcc.acc as AccountInfoGen<Buffer | ParsedAccountData>
|
||||
solAccount.lamports =
|
||||
solAccount.lamports !== 0
|
||||
? solAccount.lamports - minRentAmount
|
||||
: solAccount.lamports
|
||||
|
||||
return new AccountTypeSol(
|
||||
mint!,
|
||||
solAcc.nativeSolAddress,
|
||||
solAccount,
|
||||
governance
|
||||
)
|
||||
}
|
||||
|
||||
const minRentAmount = await connection.current.getMinimumBalanceForRentExemption(
|
||||
0
|
||||
)
|
||||
|
||||
const solAccount = acc as AccountInfoGen<Buffer | ParsedAccountData>
|
||||
|
||||
solAccount.lamports =
|
||||
solAccount.lamports !== 0
|
||||
? solAccount.lamports - minRentAmount
|
||||
: solAccount.lamports
|
||||
|
||||
return new AccountTypeSol(mint, nativeSolAddress, solAccount, governance)
|
||||
}
|
||||
|
||||
const getAccountsForGovernances = async (
|
||||
const filterOutHiddenAccounts = (x: AssetAccount) => {
|
||||
const pubkey = typeof x.pubkey === 'string' ? x.pubkey : x.pubkey.toBase58()
|
||||
return (
|
||||
HIDDEN_TREASURES.findIndex((x) => x === pubkey) === -1 &&
|
||||
(!x.extensions.token ||
|
||||
!x.extensions.token?.account.isFrozen ||
|
||||
x.type !== AccountType.GENERIC)
|
||||
)
|
||||
}
|
||||
|
||||
// Return array without duplicates
|
||||
const uniqueGovernedTokenAccounts = (
|
||||
assetAccounts: AssetAccount[]
|
||||
): AssetAccount[] => {
|
||||
const existing = new Set<string>()
|
||||
const deduped: AssetAccount[] = []
|
||||
|
||||
for (const account of assetAccounts) {
|
||||
if (!existing.has(account.pubkey.toBase58())) {
|
||||
existing.add(account.pubkey.toBase58())
|
||||
deduped.push(account)
|
||||
}
|
||||
}
|
||||
|
||||
return deduped
|
||||
}
|
||||
|
||||
const getMintAccountsInfo = async (
|
||||
{ endpoint, current: { commitment } }: ConnectionContext,
|
||||
publicKeys: PublicKey[]
|
||||
): Promise<TokenProgramAccount<MintAccount>[]> => {
|
||||
const { data: mintAccountsJson } = await axios.post(
|
||||
endpoint,
|
||||
publicKeys.map((pubkey) => {
|
||||
const id = pubkey.toBase58()
|
||||
|
||||
return {
|
||||
jsonrpc: '2.0',
|
||||
id,
|
||||
method: 'getAccountInfo',
|
||||
params: [
|
||||
id,
|
||||
{
|
||||
commitment,
|
||||
encoding: 'base64',
|
||||
},
|
||||
],
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
if (!mintAccountsJson) {
|
||||
throw new Error(
|
||||
`Cannot load information about mint accounts ${publicKeys.map((x) =>
|
||||
x.toBase58()
|
||||
)}`
|
||||
)
|
||||
}
|
||||
|
||||
return mintAccountsJson.map(
|
||||
({
|
||||
result: {
|
||||
value: {
|
||||
data: [encodedData],
|
||||
},
|
||||
},
|
||||
id,
|
||||
}) => {
|
||||
const publicKey = new PublicKey(id)
|
||||
const data = Buffer.from(encodedData, 'base64')
|
||||
const account = parseMintAccountData(data)
|
||||
return { publicKey, account }
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
const getTokenAccountsInfo = async (
|
||||
{ endpoint, current: { commitment } }: ConnectionContext,
|
||||
publicKeys: PublicKey[]
|
||||
): Promise<TokenProgramAccount<TokenAccount>[]> => {
|
||||
const { data: tokenAccountsInfoJson } = await axios.post<
|
||||
unknown,
|
||||
{
|
||||
data: {
|
||||
result: {
|
||||
account: {
|
||||
data: [string, 'base64']
|
||||
}
|
||||
pubkey: string
|
||||
}[]
|
||||
}[]
|
||||
}
|
||||
>(
|
||||
endpoint,
|
||||
publicKeys.map((publicKey) => ({
|
||||
jsonrpc: '2.0',
|
||||
id: 1,
|
||||
method: 'getProgramAccounts',
|
||||
params: [
|
||||
TOKEN_PROGRAM_ID.toBase58(),
|
||||
{
|
||||
commitment,
|
||||
encoding: 'base64',
|
||||
filters: [
|
||||
{
|
||||
// number of bytes
|
||||
dataSize: TokenAccountLayout.span,
|
||||
},
|
||||
{
|
||||
memcmp: {
|
||||
// number of bytes
|
||||
offset: tokenAccountOwnerOffset,
|
||||
bytes: publicKey.toBase58(),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}))
|
||||
)
|
||||
|
||||
if (!tokenAccountsInfoJson) {
|
||||
throw new Error(
|
||||
`Cannot load information about token accounts ${publicKeys.map((x) =>
|
||||
x.toBase58()
|
||||
)}`
|
||||
)
|
||||
}
|
||||
|
||||
return tokenAccountsInfoJson.reduce((tokenAccountsInfo, { result }) => {
|
||||
result.forEach(
|
||||
({
|
||||
account: {
|
||||
data: [encodedData],
|
||||
},
|
||||
pubkey,
|
||||
}) => {
|
||||
const publicKey = new PublicKey(pubkey)
|
||||
const data = Buffer.from(encodedData, 'base64')
|
||||
const account = parseTokenAccountData(publicKey, data)
|
||||
tokenAccountsInfo.push({ publicKey, account })
|
||||
}
|
||||
)
|
||||
|
||||
return tokenAccountsInfo
|
||||
}, [] as TokenProgramAccount<TokenAccount>[])
|
||||
}
|
||||
|
||||
const getSolAccountsInfo = async (
|
||||
connection: ConnectionContext,
|
||||
realm: ProgramAccount<Realm>,
|
||||
governancesArray: ProgramAccount<Governance>[]
|
||||
publicKeys: { governancePk: PublicKey; nativeSolAddress: PublicKey }[]
|
||||
): Promise<SolAccInfo[]> => {
|
||||
const { data: solAccountsJson } = await axios.post<
|
||||
unknown,
|
||||
{
|
||||
data: {
|
||||
result: {
|
||||
value: null | {
|
||||
data: [string, 'base64']
|
||||
}
|
||||
}
|
||||
}[]
|
||||
}
|
||||
>(
|
||||
connection.endpoint,
|
||||
publicKeys.map((x) => ({
|
||||
jsonrpc: '2.0',
|
||||
id: 1,
|
||||
method: 'getAccountInfo',
|
||||
params: [
|
||||
x.nativeSolAddress.toBase58(),
|
||||
{
|
||||
commitment: connection.current.commitment,
|
||||
encoding: 'jsonParsed',
|
||||
},
|
||||
],
|
||||
}))
|
||||
)
|
||||
|
||||
if (!solAccountsJson.length) {
|
||||
return []
|
||||
}
|
||||
|
||||
return (
|
||||
solAccountsJson
|
||||
.flatMap(({ result: { value } }, index: number) => {
|
||||
return {
|
||||
acc: value,
|
||||
...publicKeys[index],
|
||||
}
|
||||
})
|
||||
// Remove null values
|
||||
.filter(({ acc }) => acc)
|
||||
)
|
||||
}
|
||||
|
||||
const loadMintGovernanceAccounts = async (
|
||||
connection: ConnectionContext,
|
||||
mintGovernances: ProgramAccount<Governance>[]
|
||||
) => {
|
||||
const mintGovernances = getGovernancesByAccountTypes(governancesArray, [
|
||||
GovernanceAccountType.MintGovernanceV1,
|
||||
GovernanceAccountType.MintGovernanceV2,
|
||||
])
|
||||
const programGovernances = getGovernancesByAccountTypes(governancesArray, [
|
||||
GovernanceAccountType.ProgramGovernanceV1,
|
||||
GovernanceAccountType.ProgramGovernanceV2,
|
||||
])
|
||||
|
||||
const genericGovernances = getGenericAssetAccounts(governancesArray)
|
||||
|
||||
const mintGovernancesMintInfo = await getMultipleAccountInfoChunked(
|
||||
connection.current,
|
||||
mintGovernances.map((x) => x.account.governedAccount)
|
||||
)
|
||||
const mintAccounts = getMintAccounts(mintGovernances, mintGovernancesMintInfo)
|
||||
const programAccounts = getProgramAssetAccounts(programGovernances)
|
||||
const auxiliaryTokenAccounts = AUXILIARY_TOKEN_ACCOUNTS[realm.account.name]
|
||||
?.length
|
||||
|
||||
return getMintAccounts(mintGovernances, mintGovernancesMintInfo)
|
||||
}
|
||||
|
||||
const loadGovernedTokenAccounts = async (
|
||||
connection: ConnectionContext,
|
||||
realm: ProgramAccount<Realm>,
|
||||
governancesArray: ProgramAccount<Governance>[]
|
||||
): Promise<AssetAccount[]> => {
|
||||
const auxiliaryTokenAccounts: typeof AUXILIARY_TOKEN_ACCOUNTS[keyof typeof AUXILIARY_TOKEN_ACCOUNTS] = AUXILIARY_TOKEN_ACCOUNTS[
|
||||
realm.account.name
|
||||
]?.length
|
||||
? AUXILIARY_TOKEN_ACCOUNTS[realm.account.name]
|
||||
: []
|
||||
|
||||
|
@ -434,188 +674,98 @@ const getAccountsForGovernances = async (
|
|||
)
|
||||
)
|
||||
|
||||
const fetchTokenAccounts = (addresses: string[]) =>
|
||||
axios.request({
|
||||
url: connection.endpoint,
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
data: JSON.stringify(
|
||||
addresses.map((address) => ({
|
||||
jsonrpc: '2.0',
|
||||
id: 1,
|
||||
method: 'getProgramAccounts',
|
||||
params: [
|
||||
TOKEN_PROGRAM_ID.toBase58(),
|
||||
{
|
||||
commitment: connection.current.commitment,
|
||||
encoding: 'base64',
|
||||
filters: [
|
||||
{
|
||||
dataSize: TokenAccountLayout.span, // number of bytes
|
||||
},
|
||||
{
|
||||
memcmp: {
|
||||
offset: tokenAccountOwnerOffset, // number of bytes
|
||||
bytes: address, // base58 encoded string
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}))
|
||||
),
|
||||
})
|
||||
const tokenAccountsOwnedByGovernances = uniquePublicKey([
|
||||
...nativeAccountAddresses,
|
||||
...governancesArray.map((g) => g.pubkey),
|
||||
...auxiliaryTokenAccounts.map((x) => new PublicKey(x.owner)),
|
||||
])
|
||||
|
||||
const ownedByGovernancesTokenAccounts = await Promise.all([
|
||||
fetchTokenAccounts(nativeAccountAddresses.map((a) => a.toBase58())),
|
||||
fetchTokenAccounts(governancesArray.map((g) => g.pubkey.toBase58())),
|
||||
auxiliaryTokenAccounts?.length
|
||||
? fetchTokenAccounts(auxiliaryTokenAccounts.map((x) => x.owner))
|
||||
: Promise.resolve({ data: [] }),
|
||||
]).then(([x, y, z]) => x.data.concat(y.data).concat(z.data))
|
||||
|
||||
const tokenAccountsJson = ownedByGovernancesTokenAccounts.map((x) => {
|
||||
const auxiliaryMatch = auxiliaryTokenAccounts.find(
|
||||
(auxAcc) => auxAcc.owner === x.id
|
||||
)
|
||||
if (auxiliaryMatch) {
|
||||
x.result = x.result?.filter((x) =>
|
||||
auxiliaryMatch.accounts.includes(x.pubkey)
|
||||
const tokenAccountsInfo = (
|
||||
await Promise.all(
|
||||
// Load infos in batch, cannot load 9999 accounts within one request
|
||||
chunks(tokenAccountsOwnedByGovernances, 100).map((group) =>
|
||||
getTokenAccountsInfo(connection, group)
|
||||
)
|
||||
}
|
||||
return x
|
||||
})
|
||||
const tokenAccountsParsed = tokenAccountsJson.length
|
||||
? [...tokenAccountsJson.flatMap((x) => x.result)].map((x) => {
|
||||
const publicKey = new PublicKey(x.pubkey)
|
||||
const data = Buffer.from(x.account.data[0], 'base64')
|
||||
const account = parseTokenAccountData(publicKey, data)
|
||||
return { publicKey, account }
|
||||
})
|
||||
: []
|
||||
)
|
||||
).flat()
|
||||
|
||||
const groups = group(tokenAccountsParsed)
|
||||
const results = await Promise.all(
|
||||
groups.map((group) => {
|
||||
return getTokenAssetAccounts(group, governancesArray, realm, connection)
|
||||
})
|
||||
const governedTokenAccounts = (
|
||||
await Promise.all(
|
||||
// Load infos in batch, cannot load 9999 accounts within one request
|
||||
chunks(tokenAccountsInfo, 100).map((group) =>
|
||||
getTokenAssetAccounts(group, governancesArray, realm, connection)
|
||||
)
|
||||
)
|
||||
).flat()
|
||||
|
||||
// Remove potential accounts duplicate
|
||||
return uniqueGovernedTokenAccounts(governedTokenAccounts)
|
||||
}
|
||||
|
||||
const getAccountsForGovernances = async (
|
||||
connection: ConnectionContext,
|
||||
realm: ProgramAccount<Realm>,
|
||||
governancesArray: ProgramAccount<Governance>[]
|
||||
): Promise<
|
||||
(AccountTypeMint | AccountTypeProgram | AssetAccount | AccountTypeGeneric)[]
|
||||
> => {
|
||||
// 1 - Sort different types of governances
|
||||
const mintGovernances = getGovernancesByAccountTypes(governancesArray, [
|
||||
GovernanceAccountType.MintGovernanceV1,
|
||||
GovernanceAccountType.MintGovernanceV2,
|
||||
])
|
||||
|
||||
const programGovernances = getGovernancesByAccountTypes(governancesArray, [
|
||||
GovernanceAccountType.ProgramGovernanceV1,
|
||||
GovernanceAccountType.ProgramGovernanceV2,
|
||||
])
|
||||
|
||||
// 2 - Load accounts related to mint governances
|
||||
const mintAccounts = await loadMintGovernanceAccounts(
|
||||
connection,
|
||||
mintGovernances
|
||||
)
|
||||
const allResults = results.flat()
|
||||
|
||||
// remove potential duplicates
|
||||
const existing = new Set<string>()
|
||||
const deduped: AssetAccount[] = []
|
||||
// 3 - Load accounts related to program governances
|
||||
const programAccounts = getProgramAssetAccounts(programGovernances)
|
||||
|
||||
for (const account of allResults) {
|
||||
if (!existing.has(account.pubkey.toBase58())) {
|
||||
existing.add(account.pubkey.toBase58())
|
||||
deduped.push(account)
|
||||
}
|
||||
}
|
||||
// 4 - Load token accounts behind any type of governance
|
||||
const governedTokenAccounts = await loadGovernedTokenAccounts(
|
||||
connection,
|
||||
realm,
|
||||
governancesArray
|
||||
)
|
||||
|
||||
const tokenAssetAccounts = deduped
|
||||
|
||||
const governedTokenAccounts = tokenAssetAccounts
|
||||
// 5 - Call to fetch token prices for every token account's mints
|
||||
await tokenService.fetchTokenPrices(
|
||||
governedTokenAccounts
|
||||
.filter((x) => x.extensions.mint?.publicKey)
|
||||
.map((x) => x.extensions.mint!.publicKey.toBase58())
|
||||
governedTokenAccounts.reduce((mints, governedTokenAccount) => {
|
||||
if (!governedTokenAccount.extensions.mint?.publicKey) {
|
||||
return mints
|
||||
}
|
||||
|
||||
return [
|
||||
...mints,
|
||||
governedTokenAccount.extensions.mint.publicKey.toBase58(),
|
||||
]
|
||||
}, [] as string[])
|
||||
)
|
||||
return [
|
||||
|
||||
const accounts = [
|
||||
...mintAccounts,
|
||||
...programAccounts,
|
||||
...governedTokenAccounts,
|
||||
...genericGovernances,
|
||||
]
|
||||
}
|
||||
|
||||
const getMintAccountsInfo = async (
|
||||
connection: ConnectionContext,
|
||||
pubkeys: PublicKey[]
|
||||
) => {
|
||||
const mintAccountsInfo = await axios.request({
|
||||
url: connection.endpoint,
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
data: JSON.stringify([
|
||||
...pubkeys.map((x) => {
|
||||
return {
|
||||
jsonrpc: '2.0',
|
||||
id: x.toBase58(),
|
||||
method: 'getAccountInfo',
|
||||
params: [
|
||||
x.toBase58(),
|
||||
{
|
||||
commitment: connection.current.commitment,
|
||||
encoding: 'base64',
|
||||
},
|
||||
],
|
||||
}
|
||||
}),
|
||||
]),
|
||||
})
|
||||
const mintAccountsJson = mintAccountsInfo.data
|
||||
const mintAccountsParsed = mintAccountsJson?.map((x) => {
|
||||
const result = x.result
|
||||
const publicKey = new PublicKey(x.id)
|
||||
const data = Buffer.from(result.value.data[0], 'base64')
|
||||
const account = parseMintAccountData(data)
|
||||
return { publicKey, account }
|
||||
})
|
||||
return mintAccountsParsed
|
||||
}
|
||||
|
||||
const getSolAccountsInfo = async (
|
||||
connection: ConnectionContext,
|
||||
pubkeys: { governancePk: PublicKey; nativeSolAddress: PublicKey }[]
|
||||
) => {
|
||||
const solAccountsInfo = await axios.request({
|
||||
url: connection.endpoint,
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
data: JSON.stringify([
|
||||
...pubkeys.map((x) => {
|
||||
return {
|
||||
jsonrpc: '2.0',
|
||||
id: 1,
|
||||
method: 'getAccountInfo',
|
||||
params: [
|
||||
x.nativeSolAddress.toBase58(),
|
||||
{
|
||||
commitment: connection.current.commitment,
|
||||
encoding: 'jsonParsed',
|
||||
},
|
||||
],
|
||||
}
|
||||
}),
|
||||
]),
|
||||
})
|
||||
const solAccountsJson = solAccountsInfo.data
|
||||
const solAccountsParsed = solAccountsJson?.length
|
||||
? solAccountsJson
|
||||
.flatMap((x, index) => {
|
||||
return {
|
||||
acc: x.result.value,
|
||||
...pubkeys[index],
|
||||
}
|
||||
})
|
||||
.filter((x) => x.acc)
|
||||
: []
|
||||
return solAccountsParsed as SolAccInfo[]
|
||||
}
|
||||
|
||||
const filterOutHiddenAccs = (x: AssetAccount) => {
|
||||
const pubkey = typeof x.pubkey === 'string' ? x.pubkey : x.pubkey.toBase58()
|
||||
return (
|
||||
HIDDEN_TREASURES.findIndex((x) => x === pubkey) === -1 &&
|
||||
(!x.extensions.token ||
|
||||
!x.extensions.token?.account.isFrozen ||
|
||||
x.type !== AccountType.GENERIC)
|
||||
// 6 - Create generic asset accounts for governance's governedAccounts that have not been handled yet
|
||||
// We do this so theses accounts may be selected
|
||||
const genericGovernances = getGenericAssetAccounts(
|
||||
governancesArray.filter(
|
||||
(governance) =>
|
||||
!accounts.some((account) =>
|
||||
account.pubkey.equals(governance.account.governedAccount)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
return [...accounts, ...genericGovernances]
|
||||
}
|
||||
|
|
|
@ -282,7 +282,7 @@ function ForesightGovernedAccountSelect(props: {
|
|||
index: number
|
||||
governance: ProgramAccount<Governance> | null
|
||||
}) {
|
||||
const shouldBeGoverned = props.index !== 0 && props.governance
|
||||
const shouldBeGoverned = !!(props.index !== 0 && props.governance)
|
||||
return (
|
||||
<GovernedAccountSelect
|
||||
label="Program"
|
||||
|
|
|
@ -184,7 +184,7 @@ export function parseTokenAccountData(
|
|||
return accountInfo
|
||||
}
|
||||
|
||||
export function parseMintAccountData(data: Buffer) {
|
||||
export function parseMintAccountData(data: Buffer): MintAccount {
|
||||
const mintInfo = MintLayout.decode(data)
|
||||
if (mintInfo.mintAuthorityOption === 0) {
|
||||
mintInfo.mintAuthority = null
|
||||
|
|
Loading…
Reference in New Issue