diff --git a/GatewayPlugin/config.ts b/GatewayPlugin/config.ts
new file mode 100644
index 0000000000..734f8b660c
--- /dev/null
+++ b/GatewayPlugin/config.ts
@@ -0,0 +1,23 @@
+// A list of "passes" offered by Civic to verify or gate access to a DAO.
+export const availablePasses = [
+ {
+ name: 'Uniqueness',
+ value: 'uniqobk8oGh4XBLMqM68K8M2zNu3CdYX7q5go7whQiv',
+ description: 'A biometric proof of personhood, preventing Sybil attacks while retaining privacy'
+ },
+ {
+ name: 'ID Verification',
+ value: 'bni1ewus6aMxTxBi5SAfzEmmXLf8KcVFRmTfproJuKw',
+ description: 'A KYC process for your DAO, allowing users to prove their identity by presenting a government-issued ID'
+ },
+ {
+ name: 'Bot Resistance',
+ value: 'ignREusXmGrscGNUesoU9mxfds9AiYTezUKex2PsZV6',
+ description: 'A simple CAPTCHA to prevent bots from spamming your DAO'
+ },
+ {
+ name: 'Other',
+ value: '',
+ description: 'Set up your own custom verification (contact Civic.com for options)'
+ },
+] as const;
\ No newline at end of file
diff --git a/HeliumVotePlugin/components/LockTokensAccount.tsx b/HeliumVotePlugin/components/LockTokensAccount.tsx
index c3bb1450f6..882ca86e15 100644
--- a/HeliumVotePlugin/components/LockTokensAccount.tsx
+++ b/HeliumVotePlugin/components/LockTokensAccount.tsx
@@ -401,7 +401,6 @@ export const LockTokensAccount: React.FC<{
diff --git a/HeliumVotePlugin/components/VotingPowerCard.tsx b/HeliumVotePlugin/components/VotingPowerCard.tsx
index 3b20531b05..78fc7167e8 100644
--- a/HeliumVotePlugin/components/VotingPowerCard.tsx
+++ b/HeliumVotePlugin/components/VotingPowerCard.tsx
@@ -63,7 +63,6 @@ export const VotingPowerCard: React.FC<{
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000000..f49a4e16e6
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
\ No newline at end of file
diff --git a/PythVotePlugin/components/PythAccountDetails.tsx b/PythVotePlugin/components/PythAccountDetails.tsx
new file mode 100644
index 0000000000..09c81443b1
--- /dev/null
+++ b/PythVotePlugin/components/PythAccountDetails.tsx
@@ -0,0 +1,142 @@
+import { MintInfo } from '@solana/spl-token'
+import BN from 'bn.js'
+import useRealm from '@hooks/useRealm'
+import { GoverningTokenType } from '@solana/spl-governance'
+import { fmtMintAmount } from '@tools/sdk/units'
+import { useEffect } from 'react'
+import useWalletOnePointOh from '@hooks/useWalletOnePointOh'
+import {
+ useUserCommunityTokenOwnerRecord,
+} from '@hooks/queries/tokenOwnerRecord'
+import { useRealmConfigQuery } from '@hooks/queries/realmConfig'
+import VanillaWithdrawTokensButton from '@components/TokenBalance/VanillaWithdrawTokensButton'
+import { useRealmCommunityMintInfoQuery } from '@hooks/queries/mintInfo'
+import PythVotingPower from './PythVotingPower'
+
+export const PYTH_INSTRUCTIONS = "You can deposit Pyth tokens at https://staking.pyth.network/. If you previously deposited tokens on https://app.realms.today/dao/PYTH, use the button below to withdraw them immediately. Those tokens have no voting power."
+
+const TokenDeposit = ({
+ mint,
+ inAccountDetails,
+ setHasGovPower,
+}: {
+ mint: MintInfo | undefined
+ inAccountDetails?: boolean
+ setHasGovPower?: (hasGovPower: boolean) => void
+}) => {
+ const wallet = useWalletOnePointOh()
+ const connected = !!wallet?.connected
+
+ const ownTokenRecord = useUserCommunityTokenOwnerRecord().data?.result
+ const config = useRealmConfigQuery().data?.result
+
+ const relevantTokenConfig = config?.account.communityTokenConfig
+ const isMembership =
+ relevantTokenConfig?.tokenType === GoverningTokenType.Membership
+
+ const { realmTokenAccount } = useRealm()
+
+ const depositTokenRecord = ownTokenRecord
+ const depositTokenAccount = realmTokenAccount
+
+ const hasTokensInWallet =
+ depositTokenAccount && depositTokenAccount.account.amount.gt(new BN(0))
+
+ const hasTokensDeposited =
+ depositTokenRecord &&
+ depositTokenRecord.account.governingTokenDepositAmount.gt(new BN(0))
+
+ const availableTokens =
+ depositTokenRecord && mint
+ ? fmtMintAmount(
+ mint,
+ depositTokenRecord.account.governingTokenDepositAmount
+ )
+ : '0'
+
+ useEffect(() => {
+ if (availableTokens != '0' || hasTokensDeposited || hasTokensInWallet) {
+ if (setHasGovPower) setHasGovPower(true)
+ }
+ }, [availableTokens, hasTokensDeposited, hasTokensInWallet, setHasGovPower])
+
+ const canShowAvailableTokensMessage = hasTokensInWallet && connected
+ const tokensToShow =
+ hasTokensInWallet && depositTokenAccount
+ ? fmtMintAmount(mint, depositTokenAccount.account.amount)
+ : hasTokensInWallet
+ ? availableTokens
+ : 0
+
+ // Do not show deposits for mints with zero supply because nobody can deposit anyway
+ if (!mint || mint.supply.isZero()) {
+ return null
+ }
+
+ return (
+
+ {(availableTokens != '0' || inAccountDetails) && (
+
+ )}
+
+
+ You have {tokensToShow} {hasTokensDeposited ? `more ` : ``} tokens available to deposit.
+
+
+ {PYTH_INSTRUCTIONS}
+
+
+
+ {!isMembership && // Membership tokens can't be withdrawn (that is their whole point, actually)
+ inAccountDetails && (
+
+ )}
+
+
+ )
+}
+
+const PythAccountDetails = () => {
+ const mint = useRealmCommunityMintInfoQuery().data?.result
+ const wallet = useWalletOnePointOh()
+ const connected = !!wallet?.connected
+ const hasLoaded = mint
+
+ return (
+ <>
+ {hasLoaded ? (
+
+ {!connected && (
+
+ Connect your wallet to see governance power
+
+ )}
+ {(
+
+ )}
+
+ ) : (
+ <>
+
+
+ >
+ )}
+ >
+ )
+}
+
+export default PythAccountDetails
diff --git a/PythVotePlugin/components/PythVotingPower.tsx b/PythVotePlugin/components/PythVotingPower.tsx
new file mode 100644
index 0000000000..39bc29442c
--- /dev/null
+++ b/PythVotePlugin/components/PythVotingPower.tsx
@@ -0,0 +1,109 @@
+import { BigNumber } from 'bignumber.js'
+import { useMemo } from 'react'
+import { useRealmQuery } from '@hooks/queries/realm'
+import { useMintInfoByPubkeyQuery } from '@hooks/queries/mintInfo'
+import { useConnection } from '@solana/wallet-adapter-react'
+import { getPythGovPower } from '@hooks/queries/governancePower'
+import { useAsync } from 'react-async-hook'
+import BN from 'bn.js'
+import { getMintMetadata } from '@components/instructions/programs/splToken'
+import VotingPowerPct from '@components/ProposalVotingPower/VotingPowerPct'
+import clsx from 'clsx'
+import { useRealmConfigQuery } from '@hooks/queries/realmConfig'
+import { GoverningTokenType } from '@solana/spl-governance'
+import usePythScalingFactor from '@hooks/PythNetwork/useScalingFactor'
+import useWalletOnePointOh from '@hooks/useWalletOnePointOh'
+
+export const PYTH_INSTRUCTIONS = "You can deposit Pyth tokens at https://staking.pyth.network/. If you previously deposited tokens on https://app.realms.today/dao/PYTH, use the button below to withdraw them immediately. Those tokens have no voting power."
+
+interface Props {
+ className?: string
+ role: 'community' | 'council'
+ hideIfZero?: boolean
+ children?: React.ReactNode
+}
+
+export default function PythVotingPower({
+ role,
+ hideIfZero,
+ children,
+ ...props
+}: Props) {
+ const realm = useRealmQuery().data?.result
+ const realmConfig = useRealmConfigQuery().data?.result
+
+ const wallet = useWalletOnePointOh();
+
+
+ const { connection } = useConnection()
+
+ const relevantMint =
+ role === 'community'
+ ? realm?.account.communityMint
+ : realm?.account.config.councilMint
+
+ const mintInfo = useMintInfoByPubkeyQuery(relevantMint).data?.result
+
+ const { result: personalAmount } = useAsync(
+ async () => wallet?.publicKey && getPythGovPower(connection, wallet?.publicKey),
+ [connection, wallet]
+ )
+
+ const pythScalingFactor: number | undefined = usePythScalingFactor();
+
+ const totalAmount = personalAmount ?? new BN(0)
+
+ const formattedTotal = useMemo(
+ () =>
+ mintInfo && totalAmount !== undefined
+ ? new BigNumber(totalAmount.toString())
+ .multipliedBy(pythScalingFactor ?? 1)
+ .shiftedBy(-mintInfo.decimals)
+ .integerValue()
+ .toString()
+ : undefined,
+ [totalAmount, mintInfo]
+ )
+
+ const tokenName =
+ getMintMetadata(relevantMint)?.name ?? realm?.account.name ?? ''
+
+ const disabled =
+ role === 'community'
+ ? realmConfig?.account.communityTokenConfig.tokenType ===
+ GoverningTokenType.Dormant
+ : realmConfig?.account.councilTokenConfig.tokenType ===
+ GoverningTokenType.Dormant
+
+ return (
+
+
+
+ {tokenName}
+ {role === 'council' ? ' Council' : ''} Votes
+
+
+
+
+ {formattedTotal ?? 0}
+
+
+
+ {mintInfo && (
+
+ )}
+
+
+ {children}
+
+ )
+}
diff --git a/VoteStakeRegistry/components/Account/LockTokensAccount.tsx b/VoteStakeRegistry/components/Account/LockTokensAccount.tsx
index c486b37120..e8c56a3b29 100644
--- a/VoteStakeRegistry/components/Account/LockTokensAccount.tsx
+++ b/VoteStakeRegistry/components/Account/LockTokensAccount.tsx
@@ -415,7 +415,6 @@ const LockTokensAccount: React.FC<{
diff --git a/VoteStakeRegistry/components/Account/LockTokensAccountWithdraw.tsx b/VoteStakeRegistry/components/Account/LockTokensAccountWithdraw.tsx
index 8a97d2a872..c0a4c58665 100644
--- a/VoteStakeRegistry/components/Account/LockTokensAccountWithdraw.tsx
+++ b/VoteStakeRegistry/components/Account/LockTokensAccountWithdraw.tsx
@@ -438,7 +438,6 @@ const LockTokensAccount = ({ tokenOwnerRecordPk }) => {
diff --git a/VoteStakeRegistry/components/Account/LockTokensModal.tsx b/VoteStakeRegistry/components/Account/LockTokensModal.tsx
index fa67087e0d..f211202819 100644
--- a/VoteStakeRegistry/components/Account/LockTokensModal.tsx
+++ b/VoteStakeRegistry/components/Account/LockTokensModal.tsx
@@ -110,7 +110,14 @@ const LockTokensModal = ({
display: '5y',
},
{
- defaultValue: 1,
+ defaultValue: depositToUnlock
+ ? Math.ceil(
+ secsToDays(
+ depositToUnlock?.lockup.endTs.toNumber() -
+ depositToUnlock.lockup.startTs.toNumber()
+ )
+ )
+ : 1,
display: 'Custom',
},
]
@@ -142,6 +149,7 @@ const LockTokensModal = ({
x.lockup.kind.none
)
const [lockupPeriodDays, setLockupPeriodDays] = useState(0)
+
const allowClawback = false
const [lockupPeriod, setLockupPeriod] = useState(lockupPeriods[0])
const [amount, setAmount] = useState()
@@ -169,6 +177,7 @@ const LockTokensModal = ({
depositToUnlock?.amountInitiallyLockedNative
)
: 0
+
const maxAmountToLock =
depositRecord && mint
? wantToLockMoreThenDeposited
@@ -431,7 +440,7 @@ const LockTokensModal = ({
values={lockupPeriods.map((p) => p.display)}
/>
- {lockupPeriod.defaultValue === 1 && (
+ {lockupPeriod.display === 'Custom' && (
<>
Number of days
diff --git a/VoteStakeRegistry/components/TokenBalance/LockPluginTokenBalanceCard.tsx b/VoteStakeRegistry/components/TokenBalance/LockPluginTokenBalanceCard.tsx
index 77cd8bcfbe..4435986393 100644
--- a/VoteStakeRegistry/components/TokenBalance/LockPluginTokenBalanceCard.tsx
+++ b/VoteStakeRegistry/components/TokenBalance/LockPluginTokenBalanceCard.tsx
@@ -133,7 +133,6 @@ const LockPluginTokenBalanceCard = ({
diff --git a/VoteStakeRegistry/components/TokenBalance/VSRVotingPower.tsx b/VoteStakeRegistry/components/TokenBalance/VSRVotingPower.tsx
index 7dfe0e7caf..8106a94a33 100644
--- a/VoteStakeRegistry/components/TokenBalance/VSRVotingPower.tsx
+++ b/VoteStakeRegistry/components/TokenBalance/VSRVotingPower.tsx
@@ -68,7 +68,7 @@ export default function VSRCommunityVotingPower(props: Props) {
.shiftedBy(-mint.decimals)
: new BigNumber('0')
- const delegatedTors = useTokenOwnerRecordsDelegatedToUser()
+ const { data: delegatedTors } = useTokenOwnerRecordsDelegatedToUser()
const selectedDelegator = useSelectedDelegatorStore(
(s) => s.communityDelegator
)
diff --git a/VoteStakeRegistry/components/instructions/Clawback.tsx b/VoteStakeRegistry/components/instructions/Clawback.tsx
index 49a13b802f..b52fd555b6 100644
--- a/VoteStakeRegistry/components/instructions/Clawback.tsx
+++ b/VoteStakeRegistry/components/instructions/Clawback.tsx
@@ -5,7 +5,7 @@ import React, {
useMemo,
useState,
} from 'react'
-import { TransactionInstruction } from '@solana/web3.js'
+import { PublicKey, TransactionInstruction } from '@solana/web3.js'
import { tryGetMint } from '@utils/tokens'
import {
ClawbackForm,
@@ -231,6 +231,23 @@ const Clawback = ({
}
return (
<>
+
+ Use only with realm authority governance cant be executed with other
+ governances
+
+ governance: {realmAuthorityGov?.pubkey.toBase58()}
+
+ wallet:{' '}
+ {realmAuthorityGov
+ ? PublicKey.findProgramAddressSync(
+ [
+ Buffer.from('native-treasury'),
+ realmAuthorityGov!.pubkey.toBuffer(),
+ ],
+ realm!.owner
+ )[0].toBase58()
+ : null}
+
{
diff --git a/VoteStakeRegistry/tools/deposits.ts b/VoteStakeRegistry/tools/deposits.ts
index d78150a1e0..a78e2bb272 100644
--- a/VoteStakeRegistry/tools/deposits.ts
+++ b/VoteStakeRegistry/tools/deposits.ts
@@ -365,6 +365,7 @@ const getDepositsAdditionalInfoEvents = async (
//because we switch wallet in here we can't use rpc from npm module
//anchor dont allow to switch wallets inside existing client
//parse events response as anchor do
+ const latestBlockhash = await connection.getLatestBlockhash()
const events: any[] = []
const parser = new EventParser(client.program.programId, client.program.coder)
const maxRange = 8
@@ -373,6 +374,8 @@ const getDepositsAdditionalInfoEvents = async (
for (let i = 0; i < numberOfSimulations; i++) {
const take = maxRange
const transaction = new Transaction({ feePayer: simulationWallet })
+ transaction.lastValidBlockHeight = latestBlockhash.lastValidBlockHeight
+ transaction.recentBlockhash = latestBlockhash.blockhash
const logVoterInfoIx = await client.program.methods
.logVoterInfo(maxRange * i, take)
.accounts({ registrar, voter })
diff --git a/actions/cancelProposal.ts b/actions/cancelProposal.ts
index ae6bb718c4..e5a262acab 100644
--- a/actions/cancelProposal.ts
+++ b/actions/cancelProposal.ts
@@ -67,17 +67,20 @@ export const cancelProposal = async (
connection.getBalance(possibleTorDeposit),
])
- const activeDeposit = delegateDeposit ? delegateDeposit : torDeposit
+ let refundAddress;
+ if (delegateDeposit && delegateDeposit > 0 && possibleDelegateDeposit) {
+ refundAddress = proposalOwner.account.governanceDelegate;
+ } else if (torDeposit && torDeposit > 0) {
+ refundAddress = proposalOwner.account.governingTokenOwner;
+ }
- if (activeDeposit) {
+ if (refundAddress) {
await withRefundProposalDeposit(
instructions,
programId!,
programVersion,
proposal!.pubkey,
- possibleDelegateDeposit && delegateDeposit
- ? proposalOwner.account.governanceDelegate!
- : proposalOwner.account.governingTokenOwner!
+ refundAddress
)
}
diff --git a/actions/createProposal.ts b/actions/createProposal.ts
index c073c016ad..82b5eb6ee1 100644
--- a/actions/createProposal.ts
+++ b/actions/createProposal.ts
@@ -96,11 +96,11 @@ export const createProposal = async (
const voteType = isMulti
? VoteType.MULTI_CHOICE(
- MultiChoiceType.FullWeight,
- 1,
- options.length,
- options.length
- )
+ MultiChoiceType.FullWeight,
+ 1,
+ options.length,
+ options.length
+ )
: VoteType.SINGLE_CHOICE
//will run only if plugin is connected with realm
diff --git a/actions/finalizeVotes.ts b/actions/finalizeVotes.ts
index b1b4c2cacf..1b21f2acd7 100644
--- a/actions/finalizeVotes.ts
+++ b/actions/finalizeVotes.ts
@@ -67,21 +67,24 @@ export const finalizeVote = async (
connection.getBalance(possibleTorDeposit),
])
- const activeDeposit = delegateDeposit ? delegateDeposit : torDeposit
+ let refundAddress;
+ if (delegateDeposit && delegateDeposit > 0 && possibleDelegateDeposit) {
+ refundAddress = proposalOwner.account.governanceDelegate;
+ } else if (torDeposit && torDeposit > 0) {
+ refundAddress = proposalOwner.account.governingTokenOwner;
+ }
- if (activeDeposit) {
+ if (refundAddress) {
await withRefundProposalDeposit(
instructions,
programId!,
programVersion,
proposal.pubkey,
- possibleDelegateDeposit && delegateDeposit
- ? proposalOwner.account.governanceDelegate!
- : proposalOwner.account.governingTokenOwner!
+ refundAddress
)
}
- const transaction = new Transaction()
+ const transaction = new Transaction({ feePayer: wallet.publicKey });
transaction.add(...instructions)
diff --git a/components/AssetsList/UpgradeProgram.tsx b/components/AssetsList/UpgradeProgram.tsx
index b330d438ec..8c1bfe59be 100644
--- a/components/AssetsList/UpgradeProgram.tsx
+++ b/components/AssetsList/UpgradeProgram.tsx
@@ -22,7 +22,7 @@ import { validateInstruction } from 'utils/instructionTools'
import * as yup from 'yup'
import { createUpgradeInstruction } from '@tools/sdk/bpfUpgradeableLoader/createUpgradeInstruction'
import { debounce } from '@utils/debounce'
-import { isFormValid } from '@utils/formValidation'
+import { isFormValid, validatePubkey } from '@utils/formValidation'
import ProgramUpgradeInfo from 'pages/dao/[symbol]/proposal/components/instructions/bpfUpgradeableLoader/ProgramUpgradeInfo'
import { getProgramName } from '@components/instructions/programs/names'
import useCreateProposal from '@hooks/useCreateProposal'
@@ -49,6 +49,7 @@ const UpgradeProgram = ({ program }: { program: AssetAccount }) => {
const [form, setForm] = useState({
governedAccount: program,
programId: programId?.toString(),
+ bufferSpillAddress: wallet?.publicKey ? wallet.publicKey.toBase58() : '',
bufferAddress: '',
description: '',
title: '',
@@ -87,6 +88,12 @@ const UpgradeProgram = ({ program }: { program: AssetAccount }) => {
})
}
}),
+ bufferSpillAddress: yup
+ .string()
+ .required("Spill account is required")
+ .test('is-spill-account-valid', 'Invalid Spill Account', function (val: string) {
+ return val ? validatePubkey(val) : true
+ }),
governedAccount: yup
.object()
.nullable()
@@ -105,7 +112,7 @@ const UpgradeProgram = ({ program }: { program: AssetAccount }) => {
form.governedAccount.pubkey,
new PublicKey(form.bufferAddress),
form.governedAccount.extensions.program!.authority,
- wallet!.publicKey
+ new PublicKey(form.bufferSpillAddress!)
)
serializedInstruction = serializeInstructionToBase64(upgradeIx)
}
@@ -188,6 +195,19 @@ const UpgradeProgram = ({ program }: { program: AssetAccount }) => {
noMaxWidth={true}
error={formErrors['bufferAddress']}
/>
+
+ handleSetForm({
+ value: evt.target.value,
+ propertyName: 'bufferSpillAddress',
+ })
+ }
+ noMaxWidth={true}
+ error={formErrors['bufferSpillAddress']}
+ />
diff --git a/components/GovernancePower/GovernancePowerForRole.tsx b/components/GovernancePower/GovernancePowerForRole.tsx
index 6b627cbc9f..0b3cc1a541 100644
--- a/components/GovernancePower/GovernancePowerForRole.tsx
+++ b/components/GovernancePower/GovernancePowerForRole.tsx
@@ -3,15 +3,15 @@ import { useAsync } from 'react-async-hook'
import { determineVotingPowerType } from '@hooks/queries/governancePower'
import { useConnection } from '@solana/wallet-adapter-react'
import useSelectedRealmPubkey from '@hooks/selectedRealm/useSelectedRealmPubkey'
-import LockedCommunityVotingPower from '@components/ProposalVotingPower/LockedCommunityVotingPower'
import NftVotingPower from '@components/ProposalVotingPower/NftVotingPower'
import LockedCommunityNFTRecordVotingPower from '@components/ProposalVotingPower/LockedCommunityNFTRecordVotingPower'
import VanillaVotingPower from './Vanilla/VanillaVotingPower'
import { Deposit } from './Vanilla/Deposit'
import { useUserCommunityTokenOwnerRecord } from '@hooks/queries/tokenOwnerRecord'
import { ExclamationIcon } from '@heroicons/react/solid'
-import { VSR_PLUGIN_PKS } from '@constants/plugins'
-import { useRealmConfigQuery } from '@hooks/queries/realmConfig'
+import VanillaWithdrawTokensButton from '@components/TokenBalance/VanillaWithdrawTokensButton'
+import LockedCommunityVotingPower from '@components/ProposalVotingPower/LockedCommunityVotingPower'
+import PythVotingPower from 'PythVotePlugin/components/PythVotingPower'
export default function GovernancePowerForRole({
role,
@@ -23,16 +23,11 @@ export default function GovernancePowerForRole({
}) {
const { connection } = useConnection()
const realmPk = useSelectedRealmPubkey()
- const config = useRealmConfigQuery().data?.result
const ownTokenRecord = useUserCommunityTokenOwnerRecord().data?.result
- //if dao transited to use plugin and some users have still deposited tokens they should withdraw before
+
+ //VSR if dao transited to use plugin and some users have still deposited tokens they should withdraw before
//depositing to plugin
- const isVsr =
- config?.account?.communityTokenConfig?.voterWeightAddin &&
- VSR_PLUGIN_PKS.includes(
- config?.account?.communityTokenConfig?.voterWeightAddin?.toBase58()
- )
const didWithdrawFromVanillaSetup =
!ownTokenRecord ||
ownTokenRecord.account.governingTokenDepositAmount.isZero()
@@ -42,10 +37,8 @@ export default function GovernancePowerForRole({
const { result: kind } = useAsync(async () => {
if (realmPk === undefined) return undefined
- return didWithdrawFromVanillaSetup
- ? determineVotingPowerType(connection, realmPk, role)
- : 'vanilla'
- }, [connection, realmPk, role, didWithdrawFromVanillaSetup])
+ return determineVotingPowerType(connection, realmPk, role)
+ }, [connection, realmPk, role])
if (connected && kind === undefined && !props.hideIfZero) {
return (
@@ -60,21 +53,35 @@ export default function GovernancePowerForRole({
- {isVsr && !didWithdrawFromVanillaSetup && (
-
-
- Please withdraw your tokens and deposit again to get governance
- power
-
- )}
) : kind === 'VSR' ? (
-
+ didWithdrawFromVanillaSetup ? (
+
+ ) : (
+ //TODO make a better generic little prompt for when a plugin is used but there are still tokens in vanilla
+ <>
+
+
+
+
+
+ Please withdraw your tokens and deposit again to get
+ governance power
+
+
+
+
+
+
+ >
+ )
) : kind === 'NFT' ? (
-
- ) : kind === 'HeliumVSR' ? (
-
- ) : null
+ )
+ : kind === 'pyth' ? (
+
+ ) : kind === 'HeliumVSR' ? (
+
+ ) : null
) : kind === 'vanilla' ? (
diff --git a/components/GovernancePower/Vanilla/VanillaVotingPower.tsx b/components/GovernancePower/Vanilla/VanillaVotingPower.tsx
index 938df7198b..421c983214 100644
--- a/components/GovernancePower/Vanilla/VanillaVotingPower.tsx
+++ b/components/GovernancePower/Vanilla/VanillaVotingPower.tsx
@@ -59,7 +59,7 @@ export default function VanillaVotingPower({
role === 'community' ? s.communityDelegator : s.councilDelegator
)
- const torsDelegatedToUser = useTokenOwnerRecordsDelegatedToUser()
+ const { data: torsDelegatedToUser } = useTokenOwnerRecordsDelegatedToUser()
const { result: delegatorsAmount } = useAsync(
async () =>
diff --git a/components/Mango/ProgramSelector.tsx b/components/Mango/ProgramSelector.tsx
new file mode 100644
index 0000000000..ba8bf37f85
--- /dev/null
+++ b/components/Mango/ProgramSelector.tsx
@@ -0,0 +1,73 @@
+import { useEffect, useState } from 'react'
+import {
+ BOOST_MAINNET_GROUP,
+ MANGO_BOOST_PROGRAM_ID,
+ MANGO_V4_MAINNET_GROUP,
+} from '@hooks/useMangoV4'
+import { MANGO_V4_ID } from '@blockworks-foundation/mango-v4'
+import { PublicKey } from '@metaplex-foundation/js'
+import useProgramSelector from './useProgramSelector'
+import { InstructionInputType } from 'pages/dao/[symbol]/proposal/components/instructions/inputInstructionType'
+import InstructionForm, {
+ InstructionInput,
+} from 'pages/dao/[symbol]/proposal/components/instructions/FormCreator'
+
+type Program = { name: string; val: PublicKey; group: PublicKey }
+
+interface ProgramSelectorForm {
+ program: Program
+}
+
+const ProgramSelector = ({
+ programSelectorHook,
+}: {
+ programSelectorHook: ReturnType
+}) => {
+ const programs: Program[] = [
+ {
+ name: 'Mango v4 program',
+ val: MANGO_V4_ID['mainnet-beta'],
+ group: MANGO_V4_MAINNET_GROUP,
+ },
+ {
+ name: 'JLP boost program',
+ val: MANGO_BOOST_PROGRAM_ID,
+ group: BOOST_MAINNET_GROUP,
+ },
+ ]
+ const [form, setForm] = useState({
+ program: programs[0],
+ })
+
+ useEffect(() => {
+ if (programSelectorHook.setProgram) {
+ programSelectorHook.setProgram(form.program)
+ }
+ }, [form.program, programSelectorHook])
+
+ const inputs: InstructionInput[] = [
+ {
+ label: 'Program',
+ name: 'program',
+ type: InstructionInputType.SELECT,
+ initialValue: form.program,
+ options: programs,
+ },
+ ]
+
+ return (
+ <>
+ {form && (
+ null}
+ formErrors={{}}
+ >
+ )}
+ >
+ )
+}
+
+export default ProgramSelector
diff --git a/components/Mango/useProgramSelector.tsx b/components/Mango/useProgramSelector.tsx
new file mode 100644
index 0000000000..03a61bff6b
--- /dev/null
+++ b/components/Mango/useProgramSelector.tsx
@@ -0,0 +1,14 @@
+import { PublicKey } from '@solana/web3.js'
+import { useState } from 'react'
+
+type Program = { name: string; val: PublicKey; group: PublicKey }
+
+const useProgramSelector = () => {
+ const [program, setProgram] = useState()
+ return {
+ program,
+ setProgram,
+ }
+}
+
+export default useProgramSelector
diff --git a/components/Profile/useProfile.ts b/components/Profile/useProfile.ts
index 7c07b85e96..a2b1acbe92 100644
--- a/components/Profile/useProfile.ts
+++ b/components/Profile/useProfile.ts
@@ -1,31 +1,13 @@
-import { useEffect, useState } from 'react'
-import { Connection, PublicKey } from '@solana/web3.js'
+import { PublicKey } from '@solana/web3.js'
import { CivicProfile, Profile as BaseProfile } from '@civic/profile'
import useWalletOnePointOh from '@hooks/useWalletOnePointOh'
import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext'
+import { useQuery } from '@tanstack/react-query'
type Profile = BaseProfile & {
exists: boolean
}
-const profiles = new Map>()
-
-const getProfile = async (
- publicKey: PublicKey,
- connection?: Connection
-): Promise => {
- const cached = profiles.get(publicKey.toBase58());
- if (cached) return cached;
-
- const options = connection ? { solana: { connection } } : undefined;
-
- const promise = CivicProfile.get(publicKey.toBase58(), options);
-
- profiles.set(publicKey.toBase58(), promise)
-
- return promise;
-}
-
const profileIsSet = (profile: BaseProfile): boolean =>
!!profile.name || !!profile.image || !!profile.headline
@@ -34,25 +16,24 @@ export const useProfile = (
): { profile: Profile | undefined; loading: boolean } => {
const connection = useLegacyConnectionContext()
const connectedWallet = useWalletOnePointOh()
- const [profile, setProfile] = useState()
- const [loading, setLoading] = useState(true)
const profileWalletPublicKey = publicKey || connectedWallet?.publicKey
-
- useEffect(() => {
- if (profileWalletPublicKey) {
- getProfile(profileWalletPublicKey, connection?.current).then(
- (profile) => {
- setProfile({
- ...profile,
- exists: profileIsSet(profile),
- })
- setLoading(false)
- }
- )
+ const options = connection
+ ? { solana: { connection: connection?.current } }
+ : undefined
+
+ const { data: profile, isLoading } = useQuery(
+ ['Civic Profile', profileWalletPublicKey?.toBase58() + 'Civic'],
+ // @ts-ignore we won't run this if there is no profileWalletPublicKey
+ () => CivicProfile.get(profileWalletPublicKey?.toBase58(), options),
+ {
+ enabled: !!profileWalletPublicKey, // Only run query if profileWalletPublicKey is available
+ select: (data) => ({
+ ...data,
+ exists: profileIsSet(data),
+ }),
}
- // 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
- }, [publicKey, connectedWallet?.publicKey, connection.current])
+ )
- return { profile, loading }
+ return { profile, loading: isLoading }
}
diff --git a/components/ProposalActions.tsx b/components/ProposalActions.tsx
index f989309343..b795f22ffb 100644
--- a/components/ProposalActions.tsx
+++ b/components/ProposalActions.tsx
@@ -259,7 +259,7 @@ const ProposalActionsPanel = () => {
const handleRepropose = async () => {
try {
- if (proposal && realmInfo && signatoryRecord) {
+ if (proposal && realmInfo) {
const proposalAddress = await propose({
title: proposal.account.name,
description: proposal.account.descriptionLink,
@@ -282,6 +282,7 @@ const ProposalActionsPanel = () => {
isValid: true,
governance: undefined,
customHoldUpTime: tx.account.holdUpTime,
+ chunkBy: 2,
},
})
)
diff --git a/components/ProposalVotingPower/LockedCommunityVotingPower.tsx b/components/ProposalVotingPower/LockedCommunityVotingPower.tsx
index cafe39a128..cf0973bb15 100644
--- a/components/ProposalVotingPower/LockedCommunityVotingPower.tsx
+++ b/components/ProposalVotingPower/LockedCommunityVotingPower.tsx
@@ -18,7 +18,11 @@ interface Props {
export default function LockedCommunityVotingPower(props: Props) {
const realm = useRealmQuery().data?.result
- const mint = useRealmCommunityMintInfoQuery().data?.result
+ const {
+ data: mintData,
+ isLoading: mintLoading,
+ } = useRealmCommunityMintInfoQuery()
+ const mint = mintData?.result
const { realmTokenAccount } = useRealm()
@@ -41,7 +45,7 @@ export default function LockedCommunityVotingPower(props: Props) {
// memoize useAsync inputs to prevent constant refetch
const relevantDelegators = useDelegators('community')
- if (isLoading || votingPowerLoading || !(votingPower && mint)) {
+ if (isLoading || votingPowerLoading || mintLoading) {
return (
- {votingPower.isZero() && (relevantDelegators?.length ?? 0) < 1 ? (
+ {(votingPower === undefined || votingPower.isZero()) &&
+ (relevantDelegators?.length ?? 0) < 1 ? (
You do not have any voting power in this dao.
diff --git a/components/ProposalVotingPower/NftVotingPower.tsx b/components/ProposalVotingPower/NftVotingPower.tsx
index 541535f749..b6d3ff6954 100644
--- a/components/ProposalVotingPower/NftVotingPower.tsx
+++ b/components/ProposalVotingPower/NftVotingPower.tsx
@@ -89,7 +89,7 @@ const Join = () => {
}
return (
- (actingAsWalletPk?.toString === wallet?.publicKey?.toString() &&
+ (actingAsWalletPk?.toString() === wallet?.publicKey?.toString() &&
connected &&
!ownTokenRecord && (
diff --git a/components/RealmHeader.tsx b/components/RealmHeader.tsx
index f319c8d8cb..10c13ba991 100644
--- a/components/RealmHeader.tsx
+++ b/components/RealmHeader.tsx
@@ -10,7 +10,11 @@ import { getRealmExplorerHost } from 'tools/routing'
import { tryParsePublicKey } from '@tools/core/pubkey'
import { useRealmQuery } from '@hooks/queries/realm'
import { useRealmConfigQuery } from '@hooks/queries/realmConfig'
-import { NFT_PLUGINS_PKS } from '@constants/plugins'
+import { GoverningTokenType } from '@solana/spl-governance'
+import { determineVotingPowerType } from '@hooks/queries/governancePower'
+import { useAsync } from 'react-async-hook'
+import useSelectedRealmPubkey from '@hooks/selectedRealm/useSelectedRealmPubkey'
+import { useConnection } from '@solana/wallet-adapter-react'
const RealmHeader = () => {
const { fmtUrlWithCluster } = useQueryContext()
@@ -25,6 +29,18 @@ const RealmHeader = () => {
const [isBackNavVisible, setIsBackNavVisible] = useState(true)
+ const { connection } = useConnection()
+ const realmPk = useSelectedRealmPubkey()
+
+ const { result: kind } = useAsync(async () => {
+ if (realmPk === undefined) return undefined
+ return determineVotingPowerType(connection, realmPk, 'community')
+ }, [connection, realmPk])
+ const membersTabIsCouncilOnly = !(kind === 'vanilla' || kind === 'NFT')
+ const councilExists =
+ realm?.account.config.councilMint !== undefined &&
+ config?.account.councilTokenConfig?.tokenType !== GoverningTokenType.Dormant
+
useEffect(() => {
setIsBackNavVisible(realmInfo?.symbol !== REALM)
}, [realmInfo?.symbol, REALM])
@@ -68,17 +84,6 @@ const RealmHeader = () => {
)}
- {(!config?.account.communityTokenConfig.voterWeightAddin ||
- NFT_PLUGINS_PKS.includes(
- config?.account.communityTokenConfig.voterWeightAddin.toBase58()
- )) && (
-
-
-
- Members
-
-
- )}
{vsrMode === 'default' && (
@@ -90,6 +95,14 @@ const RealmHeader = () => {
)}
+ {(!membersTabIsCouncilOnly || councilExists) && (
+
+
+
+ {membersTabIsCouncilOnly ? 'Council' : 'Members'}
+
+
+ )}
diff --git a/components/SelectPrimaryDelegators.tsx b/components/SelectPrimaryDelegators.tsx
index 65435af856..6f58515587 100644
--- a/components/SelectPrimaryDelegators.tsx
+++ b/components/SelectPrimaryDelegators.tsx
@@ -22,7 +22,7 @@ const SelectPrimaryDelegators = () => {
const walletId = wallet?.publicKey?.toBase58()
const realm = useRealmQuery().data?.result
- const delegatesArray = useTokenOwnerRecordsDelegatedToUser()
+ const { data: delegatesArray } = useTokenOwnerRecordsDelegatedToUser()
// returns array of community tokenOwnerRecords that connected wallet has been delegated
const communityTorsDelegatedToUser = useMemo(
diff --git a/components/TokenBalance/TokenBalanceCardWrapper.tsx b/components/TokenBalance/TokenBalanceCardWrapper.tsx
index 8d50160098..a49b1ae46f 100644
--- a/components/TokenBalance/TokenBalanceCardWrapper.tsx
+++ b/components/TokenBalance/TokenBalanceCardWrapper.tsx
@@ -14,6 +14,7 @@ import ClaimUnreleasedPositions from 'HeliumVotePlugin/components/ClaimUnrelease
import VanillaAccountDetails from './VanillaAccountDetails'
import GovernancePowerCard from '@components/GovernancePower/GovernancePowerCard'
import SelectPrimaryDelegators from '@components/SelectPrimaryDelegators'
+import PythAccountDetails from 'PythVotePlugin/components/PythAccountDetails'
const LockPluginTokenBalanceCard = dynamic(
() =>
@@ -104,6 +105,14 @@ const TokenBalanceCardInner = ({
)
}
+ if (vsrMode === 'pyth'){
+ return (
+ <>
+ {inAccountDetails ? : }
+ >
+ )
+ }
+
//Default
return (
<>
diff --git a/components/TokenBalance/TokenDeposit.tsx b/components/TokenBalance/TokenDeposit.tsx
index ac8cc76d0e..6b4a9ebc01 100644
--- a/components/TokenBalance/TokenDeposit.tsx
+++ b/components/TokenBalance/TokenDeposit.tsx
@@ -1,34 +1,11 @@
-import {
- ASSOCIATED_TOKEN_PROGRAM_ID,
- MintInfo,
- Token,
- TOKEN_PROGRAM_ID,
-} from '@solana/spl-token'
-import { PublicKey, Transaction, TransactionInstruction } from '@solana/web3.js'
+import { MintInfo } from '@solana/spl-token'
import BN from 'bn.js'
import useRealm from '@hooks/useRealm'
-import {
- getProposal,
- GoverningTokenType,
- ProposalState,
-} from '@solana/spl-governance'
-import { getUnrelinquishedVoteRecords } from '@models/api'
-import { withRelinquishVote } from '@solana/spl-governance'
-import { withWithdrawGoverningTokens } from '@solana/spl-governance'
-import { sendTransaction } from '@utils/send'
-import { SecondaryButton } from '../Button'
+import { GoverningTokenType } from '@solana/spl-governance'
import { GoverningTokenRole } from '@solana/spl-governance'
import { fmtMintAmount } from '@tools/sdk/units'
import { getMintMetadata } from '../instructions/programs/splToken'
-import { withFinalizeVote } from '@solana/spl-governance'
-import { chunks } from '@utils/helpers'
-import { getProgramVersionForRealm } from '@models/registry/api'
-import { notify } from '@utils/notifications'
-import { ExclamationIcon } from '@heroicons/react/outline'
import { useEffect } from 'react'
-import useVotePluginsClientStore from 'stores/useVotePluginsClientStore'
-import { VSR_PLUGIN_PKS } from '@constants/plugins'
-import { useMaxVoteRecord } from '@hooks/useMaxVoteRecord'
import useWalletOnePointOh from '@hooks/useWalletOnePointOh'
import {
useUserCommunityTokenOwnerRecord,
@@ -36,37 +13,25 @@ import {
} from '@hooks/queries/tokenOwnerRecord'
import { useRealmQuery } from '@hooks/queries/realm'
import { useRealmConfigQuery } from '@hooks/queries/realmConfig'
-import { fetchGovernanceByPubkey } from '@hooks/queries/governance'
-import { useConnection } from '@solana/wallet-adapter-react'
-import queryClient from '@hooks/queries/queryClient'
-import { proposalQueryKeys } from '@hooks/queries/proposal'
-import asFindable from '@utils/queries/asFindable'
import VanillaVotingPower from '@components/GovernancePower/Vanilla/VanillaVotingPower'
-import { fetchTokenAccountByPubkey } from '@hooks/queries/tokenAccount'
import { DepositTokensButton } from '@components/DepositTokensButton'
+import VanillaWithdrawTokensButton from './VanillaWithdrawTokensButton'
+/** deposit + withdraw for vanilla govtokens, used only in account view. plugin views still use this for council. */
export const TokenDeposit = ({
mint,
tokenRole,
- councilVote,
inAccountDetails,
setHasGovPower,
}: {
mint: MintInfo | undefined
tokenRole: GoverningTokenRole
- councilVote?: boolean
inAccountDetails?: boolean
setHasGovPower?: (hasGovPower: boolean) => void
}) => {
const wallet = useWalletOnePointOh()
const connected = !!wallet?.connected
- const { connection } = useConnection()
-
- const client = useVotePluginsClientStore(
- (s) => s.state.currentRealmVotingClient
- )
- const maxVoterWeight = useMaxVoteRecord()?.pubkey || undefined
const ownTokenRecord = useUserCommunityTokenOwnerRecord().data?.result
const ownCouncilTokenRecord = useUserCouncilTokenOwnerRecord().data?.result
const realm = useRealmQuery().data?.result
@@ -79,13 +44,7 @@ export const TokenDeposit = ({
const isMembership =
relevantTokenConfig?.tokenType === GoverningTokenType.Membership
- const {
- realmInfo,
- realmTokenAccount,
- councilTokenAccount,
- toManyCommunityOutstandingProposalsForUser,
- toManyCouncilOutstandingProposalsForUse,
- } = useRealm()
+ const { realmTokenAccount, councilTokenAccount } = useRealm()
const depositTokenRecord =
tokenRole === GoverningTokenRole.Community
@@ -108,152 +67,6 @@ export const TokenDeposit = ({
tokenRole === GoverningTokenRole.Community ? '' : 'Council'
}`
- const withdrawAllTokens = async function () {
- const instructions: TransactionInstruction[] = []
- // If there are unrelinquished votes for the voter then let's release them in the same instruction as convenience
- if (depositTokenRecord!.account!.unrelinquishedVotesCount > 0) {
- const voteRecords = await getUnrelinquishedVoteRecords(
- connection,
- realmInfo!.programId,
- depositTokenRecord!.account!.governingTokenOwner
- )
-
- for (const voteRecord of Object.values(voteRecords)) {
- const proposalQuery = await queryClient.fetchQuery({
- queryKey: proposalQueryKeys.byPubkey(
- connection.rpcEndpoint,
- voteRecord.account.proposal
- ),
- staleTime: 0,
- queryFn: () =>
- asFindable(() =>
- getProposal(connection, voteRecord.account.proposal)
- )(),
- })
- const proposal = proposalQuery.result
- if (!proposal) {
- continue
- }
-
- if (proposal.account.state === ProposalState.Voting) {
- if (proposal.account.state === ProposalState.Voting) {
- const governance = (
- await fetchGovernanceByPubkey(
- connection,
- proposal.account.governance
- )
- ).result
- if (!governance) throw new Error('failed to fetch governance')
- if (proposal.account.getTimeToVoteEnd(governance.account) > 0) {
- // Note: It's technically possible to withdraw the vote here but I think it would be confusing and people would end up unconsciously withdrawing their votes
- notify({
- type: 'error',
- message: `Can't withdraw tokens while Proposal ${proposal.account.name} is being voted on. Please withdraw your vote first`,
- })
- throw new Error(
- `Can't withdraw tokens while Proposal ${proposal.account.name} is being voted on. Please withdraw your vote first`
- )
- } else {
- // finalize proposal before withdrawing tokens so we don't stop the vote from succeeding
- await withFinalizeVote(
- instructions,
- realmInfo!.programId,
- getProgramVersionForRealm(realmInfo!),
- realm!.pubkey,
- proposal.account.governance,
- proposal.pubkey,
- proposal.account.tokenOwnerRecord,
- proposal.account.governingTokenMint,
- maxVoterWeight
- )
- }
- }
- }
- // Note: We might hit single transaction limits here (accounts and size) if user has too many unrelinquished votes
- // It's not going to be an issue for now due to the limited number of proposals so I'm leaving it for now
- // As a temp. work around I'm leaving the 'Release Tokens' button on finalized Proposal to make it possible to release the tokens from one Proposal at a time
- await withRelinquishVote(
- instructions,
- realmInfo!.programId,
- realmInfo!.programVersion!,
- realmInfo!.realmId,
- proposal.account.governance,
- proposal.pubkey,
- depositTokenRecord!.pubkey,
- proposal.account.governingTokenMint,
- voteRecord.pubkey,
- depositTokenRecord!.account.governingTokenOwner,
- wallet!.publicKey!
- )
- await client.withRelinquishVote(
- instructions,
- proposal,
- voteRecord.pubkey,
- depositTokenRecord!.pubkey
- )
- }
- }
-
- const ataPk = await Token.getAssociatedTokenAddress(
- ASSOCIATED_TOKEN_PROGRAM_ID,
- TOKEN_PROGRAM_ID,
- depositMint!,
- wallet!.publicKey!,
- true
- )
- const ata = await fetchTokenAccountByPubkey(connection, ataPk)
-
- if (!ata.found) {
- const ataIx = Token.createAssociatedTokenAccountInstruction(
- ASSOCIATED_TOKEN_PROGRAM_ID,
- TOKEN_PROGRAM_ID,
- depositMint!,
- ataPk,
- wallet!.publicKey!,
- wallet!.publicKey! // fee payer
- )
- instructions.push(ataIx)
- }
-
- await withWithdrawGoverningTokens(
- instructions,
- realmInfo!.programId,
- realmInfo!.programVersion!,
- realm!.pubkey,
- depositTokenAccount?.publicKey
- ? depositTokenAccount!.publicKey
- : new PublicKey(ataPk),
- depositTokenRecord!.account.governingTokenMint,
- wallet!.publicKey!
- )
-
- try {
- // use chunks of 8 here since we added finalize,
- // because previously 9 withdraws used to fit into one tx
- const ixChunks = chunks(instructions, 8)
- for (const [index, chunk] of ixChunks.entries()) {
- const transaction = new Transaction().add(...chunk)
- await sendTransaction({
- connection,
- wallet: wallet!,
- transaction,
- sendingMessage:
- index == ixChunks.length - 1
- ? 'Withdrawing tokens'
- : `Releasing tokens (${index}/${ixChunks.length - 2})`,
- successMessage:
- index == ixChunks.length - 1
- ? 'Tokens have been withdrawn'
- : `Released tokens (${index}/${ixChunks.length - 2})`,
- })
- }
- } catch (ex) {
- //TODO change to more friendly notification
- notify({ type: 'error', message: `${ex}` })
- console.error("Can't withdraw tokens", ex)
- }
- }
-
const hasTokensInWallet =
depositTokenAccount && depositTokenAccount.account.amount.gt(new BN(0))
@@ -261,16 +74,6 @@ export const TokenDeposit = ({
depositTokenRecord &&
depositTokenRecord.account.governingTokenDepositAmount.gt(new BN(0))
- const withdrawTooltipContent = !connected
- ? 'Connect your wallet to withdraw'
- : !hasTokensDeposited
- ? "You don't have any tokens deposited to withdraw."
- : !councilVote &&
- (toManyCouncilOutstandingProposalsForUse ||
- toManyCommunityOutstandingProposalsForUser)
- ? 'You have to many outstanding proposals to withdraw.'
- : ''
-
const availableTokens =
depositTokenRecord && mint
? fmtMintAmount(
@@ -292,12 +95,6 @@ export const TokenDeposit = ({
: hasTokensInWallet
? availableTokens
: 0
- const isVsr =
- config?.account?.communityTokenConfig?.voterWeightAddin &&
- VSR_PLUGIN_PKS.includes(
- config?.account?.communityTokenConfig?.voterWeightAddin?.toBase58()
- ) &&
- tokenRole === GoverningTokenRole.Community
// Do not show deposits for mints with zero supply because nobody can deposit anyway
if (!mint || mint.supply.isZero()) {
@@ -316,57 +113,38 @@ export const TokenDeposit = ({
)}
- {
- <>
-
- You have {tokensToShow} {hasTokensDeposited ? `more ` : ``}
- {depositTokenName} tokens available to deposit.
-
-
-
- {hasTokensInWallet || inAccountDetails ? (
-
- ) : null}
- {!isMembership && // Membership tokens can't be withdrawn (that is their whole point, actually)
- (inAccountDetails || isVsr) && (
-
- Withdraw
-
- )}
-
- >
- }
- {isVsr && (
-
-
- Please withdraw your tokens and deposit again to get governance power
-
- )}
+
+ You have {tokensToShow} {hasTokensDeposited ? `more ` : ``}
+ {depositTokenName} tokens available to deposit.
+
+
+
+ {hasTokensInWallet || inAccountDetails ? (
+
+ ) : null}
+ {!isMembership && // Membership tokens can't be withdrawn (that is their whole point, actually)
+ inAccountDetails && (
+
+ )}
+
)
}
diff --git a/components/TokenBalance/VanillaAccountDetails.tsx b/components/TokenBalance/VanillaAccountDetails.tsx
index 7d35da1b41..0004c0bea2 100644
--- a/components/TokenBalance/VanillaAccountDetails.tsx
+++ b/components/TokenBalance/VanillaAccountDetails.tsx
@@ -34,7 +34,6 @@ const VanillaAccountDetails = () => {
)}
@@ -42,7 +41,6 @@ const VanillaAccountDetails = () => {
)}
diff --git a/components/TokenBalance/VanillaWithdrawTokensButton.tsx b/components/TokenBalance/VanillaWithdrawTokensButton.tsx
new file mode 100644
index 0000000000..7a4b71cc00
--- /dev/null
+++ b/components/TokenBalance/VanillaWithdrawTokensButton.tsx
@@ -0,0 +1,265 @@
+import {
+ ASSOCIATED_TOKEN_PROGRAM_ID,
+ Token,
+ TOKEN_PROGRAM_ID,
+} from '@solana/spl-token'
+import { PublicKey, Transaction, TransactionInstruction } from '@solana/web3.js'
+import BN from 'bn.js'
+import useRealm from '@hooks/useRealm'
+import {
+ getProposal,
+ GoverningTokenType,
+ ProposalState,
+} from '@solana/spl-governance'
+import { getUnrelinquishedVoteRecords } from '@models/api'
+import { withRelinquishVote } from '@solana/spl-governance'
+import { withWithdrawGoverningTokens } from '@solana/spl-governance'
+import { sendTransaction } from '@utils/send'
+import { SecondaryButton } from '../Button'
+import { withFinalizeVote } from '@solana/spl-governance'
+import { chunks } from '@utils/helpers'
+import { getProgramVersionForRealm } from '@models/registry/api'
+import { notify } from '@utils/notifications'
+import useVotePluginsClientStore from 'stores/useVotePluginsClientStore'
+import { useMaxVoteRecord } from '@hooks/useMaxVoteRecord'
+import useWalletOnePointOh from '@hooks/useWalletOnePointOh'
+import {
+ useUserCommunityTokenOwnerRecord,
+ useUserCouncilTokenOwnerRecord,
+} from '@hooks/queries/tokenOwnerRecord'
+import { useRealmQuery } from '@hooks/queries/realm'
+import { useRealmConfigQuery } from '@hooks/queries/realmConfig'
+import { fetchGovernanceByPubkey } from '@hooks/queries/governance'
+import { useConnection } from '@solana/wallet-adapter-react'
+import queryClient from '@hooks/queries/queryClient'
+import { proposalQueryKeys } from '@hooks/queries/proposal'
+import asFindable from '@utils/queries/asFindable'
+import { fetchTokenAccountByPubkey } from '@hooks/queries/tokenAccount'
+
+// TODO make this have reasonable props
+// TODO, also just refactor it
+const VanillaWithdrawTokensButton = ({
+ role,
+}: {
+ role: 'community' | 'council'
+}) => {
+ const wallet = useWalletOnePointOh()
+ const connected = !!wallet?.connected
+ const { connection } = useConnection()
+
+ const client = useVotePluginsClientStore(
+ (s) => s.state.currentRealmVotingClient
+ )
+
+ const maxVoterWeight = useMaxVoteRecord()?.pubkey || undefined
+ const ownTokenRecord = useUserCommunityTokenOwnerRecord().data?.result
+ const ownCouncilTokenRecord = useUserCouncilTokenOwnerRecord().data?.result
+ const realm = useRealmQuery().data?.result
+ const config = useRealmConfigQuery().data?.result
+
+ const relevantTokenConfig =
+ role === 'community'
+ ? config?.account.communityTokenConfig
+ : config?.account.councilTokenConfig
+ const isMembership =
+ relevantTokenConfig?.tokenType === GoverningTokenType.Membership
+
+ const {
+ realmInfo,
+ realmTokenAccount,
+ councilTokenAccount,
+ toManyCommunityOutstandingProposalsForUser,
+ toManyCouncilOutstandingProposalsForUse,
+ } = useRealm()
+
+ const depositTokenRecord =
+ role === 'community' ? ownTokenRecord : ownCouncilTokenRecord
+
+ const depositTokenAccount =
+ role === 'community' ? realmTokenAccount : councilTokenAccount
+
+ const depositMint =
+ role === 'community'
+ ? realm?.account.communityMint
+ : realm?.account.config.councilMint
+
+ const withdrawAllTokens = async function () {
+ const instructions: TransactionInstruction[] = []
+ // If there are unrelinquished votes for the voter then let's release them in the same instruction as convenience
+ if (depositTokenRecord!.account!.unrelinquishedVotesCount > 0) {
+ const voteRecords = await getUnrelinquishedVoteRecords(
+ connection,
+ realmInfo!.programId,
+ depositTokenRecord!.account!.governingTokenOwner
+ )
+
+ for (const voteRecord of Object.values(voteRecords)) {
+ const proposalQuery = await queryClient.fetchQuery({
+ queryKey: proposalQueryKeys.byPubkey(
+ connection.rpcEndpoint,
+ voteRecord.account.proposal
+ ),
+ staleTime: 0,
+ queryFn: () =>
+ asFindable(() =>
+ getProposal(connection, voteRecord.account.proposal)
+ )(),
+ })
+ const proposal = proposalQuery.result
+ if (!proposal) {
+ continue
+ }
+
+ if (proposal.account.state === ProposalState.Voting) {
+ if (proposal.account.state === ProposalState.Voting) {
+ const governance = (
+ await fetchGovernanceByPubkey(
+ connection,
+ proposal.account.governance
+ )
+ ).result
+ if (!governance) throw new Error('failed to fetch governance')
+ if (proposal.account.getTimeToVoteEnd(governance.account) > 0) {
+ // Note: It's technically possible to withdraw the vote here but I think it would be confusing and people would end up unconsciously withdrawing their votes
+ notify({
+ type: 'error',
+ message: `Can't withdraw tokens while Proposal ${proposal.account.name} is being voted on. Please withdraw your vote first`,
+ })
+ throw new Error(
+ `Can't withdraw tokens while Proposal ${proposal.account.name} is being voted on. Please withdraw your vote first`
+ )
+ } else {
+ // finalize proposal before withdrawing tokens so we don't stop the vote from succeeding
+ await withFinalizeVote(
+ instructions,
+ realmInfo!.programId,
+ getProgramVersionForRealm(realmInfo!),
+ realm!.pubkey,
+ proposal.account.governance,
+ proposal.pubkey,
+ proposal.account.tokenOwnerRecord,
+ proposal.account.governingTokenMint,
+ maxVoterWeight
+ )
+ }
+ }
+ }
+ // Note: We might hit single transaction limits here (accounts and size) if user has too many unrelinquished votes
+ // It's not going to be an issue for now due to the limited number of proposals so I'm leaving it for now
+ // As a temp. work around I'm leaving the 'Release Tokens' button on finalized Proposal to make it possible to release the tokens from one Proposal at a time
+ await withRelinquishVote(
+ instructions,
+ realmInfo!.programId,
+ realmInfo!.programVersion!,
+ realmInfo!.realmId,
+ proposal.account.governance,
+ proposal.pubkey,
+ depositTokenRecord!.pubkey,
+ proposal.account.governingTokenMint,
+ voteRecord.pubkey,
+ depositTokenRecord!.account.governingTokenOwner,
+ wallet!.publicKey!
+ )
+ await client.withRelinquishVote(
+ instructions,
+ proposal,
+ voteRecord.pubkey,
+ depositTokenRecord!.pubkey
+ )
+ }
+ }
+
+ const ataPk = await Token.getAssociatedTokenAddress(
+ ASSOCIATED_TOKEN_PROGRAM_ID,
+ TOKEN_PROGRAM_ID,
+ depositMint!,
+ wallet!.publicKey!,
+ true
+ )
+ const ata = await fetchTokenAccountByPubkey(connection, ataPk)
+
+ if (!ata.found) {
+ const ataIx = Token.createAssociatedTokenAccountInstruction(
+ ASSOCIATED_TOKEN_PROGRAM_ID,
+ TOKEN_PROGRAM_ID,
+ depositMint!,
+ ataPk,
+ wallet!.publicKey!,
+ wallet!.publicKey! // fee payer
+ )
+ instructions.push(ataIx)
+ }
+
+ await withWithdrawGoverningTokens(
+ instructions,
+ realmInfo!.programId,
+ realmInfo!.programVersion!,
+ realm!.pubkey,
+ depositTokenAccount?.publicKey
+ ? depositTokenAccount!.publicKey
+ : new PublicKey(ataPk),
+ depositTokenRecord!.account.governingTokenMint,
+ wallet!.publicKey!
+ )
+
+ try {
+ // use chunks of 8 here since we added finalize,
+ // because previously 9 withdraws used to fit into one tx
+ const ixChunks = chunks(instructions, 8)
+ for (const [index, chunk] of ixChunks.entries()) {
+ const transaction = new Transaction().add(...chunk)
+ await sendTransaction({
+ connection,
+ wallet: wallet!,
+ transaction,
+ sendingMessage:
+ index == ixChunks.length - 1
+ ? 'Withdrawing tokens'
+ : `Releasing tokens (${index}/${ixChunks.length - 2})`,
+ successMessage:
+ index == ixChunks.length - 1
+ ? 'Tokens have been withdrawn'
+ : `Released tokens (${index}/${ixChunks.length - 2})`,
+ })
+ }
+ } catch (ex) {
+ //TODO change to more friendly notification
+ notify({ type: 'error', message: `${ex}` })
+ console.error("Can't withdraw tokens", ex)
+ }
+ }
+
+ const hasTokensDeposited =
+ depositTokenRecord &&
+ depositTokenRecord.account.governingTokenDepositAmount.gt(new BN(0))
+
+ const withdrawTooltipContent = !connected
+ ? 'Connect your wallet to withdraw'
+ : !hasTokensDeposited
+ ? "You don't have any tokens deposited to withdraw."
+ : role === 'community' &&
+ (toManyCouncilOutstandingProposalsForUse ||
+ toManyCommunityOutstandingProposalsForUser)
+ ? 'You have to many outstanding proposals to withdraw.'
+ : ''
+
+ return (
+
+ Withdraw
+
+ )
+}
+export default VanillaWithdrawTokensButton
diff --git a/components/TreasuryAccount/MangoModal.tsx b/components/TreasuryAccount/MangoModal.tsx
index cc02cd6ba9..e3cd03b651 100644
--- a/components/TreasuryAccount/MangoModal.tsx
+++ b/components/TreasuryAccount/MangoModal.tsx
@@ -1,6 +1,11 @@
-import { Group, MangoAccount } from '@blockworks-foundation/mango-v4'
+import {
+ Group,
+ MangoAccount,
+ USDC_MINT,
+ toUiDecimals,
+} from '@blockworks-foundation/mango-v4'
import AdditionalProposalOptions from '@components/AdditionalProposalOptions'
-import Button from '@components/Button'
+import Button, { LinkButton } from '@components/Button'
import Input from '@components/inputs/Input'
import Select from '@components/inputs/Select'
import { BN } from '@coral-xyz/anchor'
@@ -16,75 +21,207 @@ import { AccountMeta, PublicKey } from '@solana/web3.js'
import { AssetAccount } from '@utils/uiTypes/assets'
import { useRouter } from 'next/router'
import { useEffect, useState } from 'react'
+import useGovernanceAssets from '@hooks/useGovernanceAssets'
+import Tooltip from '@components/Tooltip'
+import {
+ getMintDecimalAmount,
+ getMintMinAmountAsDecimal,
+ getMintNaturalAmountFromDecimalAsBN,
+} from '@tools/sdk/units'
+import BigNumber from 'bignumber.js'
+import { precision } from '@utils/formatting'
+import * as yup from 'yup'
+import tokenPriceService from '@utils/services/tokenPrice'
+import { validateInstruction } from '@utils/instructionTools'
+import Switch from '@components/Switch'
+import { InstructionDataWithHoldUpTime } from 'actions/createProposal'
+import ProgramSelector from '@components/Mango/ProgramSelector'
+import useProgramSelector from '@components/Mango/useProgramSelector'
const MangoModal = ({ account }: { account: AssetAccount }) => {
- const { mangoClient, mangoGroup } = UseMangoV4()
+ const { canUseTransferInstruction } = useGovernanceAssets()
+ const programSelectorHook = useProgramSelector()
+ const { mangoClient, mangoGroup } = UseMangoV4(
+ programSelectorHook.program?.val,
+ programSelectorHook.program?.group
+ )
const { fmtUrlWithCluster } = useQueryContext()
const { handleCreateProposal } = useCreateProposal()
const router = useRouter()
const { symbol } = useRealm()
- const [mangoAccount, setSelectedMangoAccount] = useState(
- null
- )
- const [mangoAccounts, setMangoAccounts] = useState([])
- const [mangoAccName, setMangoAccName] = useState('')
const [isProposing, setIsProposing] = useState(false)
const [voteByCouncil, setVoteByCouncil] = useState(false)
- const [proposalTitle, setProposalTitle] = useState('Create mango account')
- const [proposalDescription, setProposalDescription] = useState('')
+ const [isLoadingMangoAccount, setIsLoadingMangoAccount] = useState(
+ true
+ )
+ const [mangoAccounts, setMangoAccounts] = useState([])
+ const [form, setForm] = useState<{
+ mangoAccount: MangoAccount | null | undefined
+ accountName: string
+ amount: number
+ title: string
+ description: string
+ delegate: boolean
+ delegateWallet: string
+ }>({
+ accountName: '',
+ title: `Deposit ${
+ tokenPriceService.getTokenInfo(
+ account.extensions.mint!.publicKey.toBase58()
+ )?.symbol || 'tokens'
+ } to the Mango`,
+ description: '',
+ amount: 0,
+ mangoAccount: undefined,
+ delegate: false,
+ delegateWallet: '',
+ })
+ const [formErrors, setFormErrors] = useState({})
+
+ const handleSetForm = ({ propertyName, value }) => {
+ setForm({ ...form, [propertyName]: value })
+ setFormErrors({})
+ }
+
+ useEffect(() => {
+ setForm({ ...form, mangoAccount: undefined })
+ }, [programSelectorHook.program?.val.toBase58()])
+ const SOL_BUFFER = 0.02
+
+ const treasuryAmount = new BN(
+ account.isSol
+ ? account.extensions.amount!.toNumber()
+ : account.extensions.token!.account.amount
+ )
+ const mintInfo = account.extensions.mint!.account!
+ const mintMinAmount = mintInfo ? getMintMinAmountAsDecimal(mintInfo) : 1
+ let maxAmount = mintInfo
+ ? getMintDecimalAmount(mintInfo, treasuryAmount)
+ : new BigNumber(0)
+ if (account.isSol) {
+ maxAmount = maxAmount.minus(SOL_BUFFER)
+ }
+ const maxAmountFtm = maxAmount.toNumber().toFixed(4)
+ const currentPrecision = precision(mintMinAmount)
+
+ const schema = yup.object().shape({
+ mangoAccount: yup
+ .object()
+ .nullable(true)
+ .test(
+ 'is-not-undefined',
+ 'Please select an Account',
+ (value) => value !== undefined
+ ),
+ accountName: yup.string().when('mangoAccount', {
+ is: null,
+ then: yup.string().required('Account name is required'),
+ otherwise: yup.string().notRequired(),
+ }),
+ title: yup.string().required('Title is required'),
+ amount: yup
+ .number()
+ .required('Amount is required')
+ .min(mintMinAmount)
+ .max(maxAmount.toNumber()),
+ delegate: yup.boolean().required('Delegate is required'),
+ delegateWallet: yup
+ .string()
+ .nullable()
+ .when('delegate', {
+ is: true,
+ then: yup.string().required('Delegate Wallet is required'),
+ otherwise: yup.string().notRequired(),
+ }),
+ })
+
+ useEffect(() => {
+ setMangoAccounts([])
+ }, [programSelectorHook.program?.val])
useEffect(() => {
const getMangoAccounts = async () => {
const accounts = await mangoClient?.getMangoAccountsForOwner(
mangoGroup!,
account.extensions.token!.account.owner!
)
+
if (accounts) {
setMangoAccounts(accounts)
}
}
- getMangoAccounts()
- }, [mangoClient !== null && mangoGroup !== null])
+ if (mangoClient && mangoGroup) {
+ setMangoAccounts([])
+ setIsLoadingMangoAccount(true)
+ getMangoAccounts().then(() => setIsLoadingMangoAccount(false))
+ }
+ }, [account.extensions.token, mangoClient, mangoGroup])
+
const handleCreateAccount = async () => {
+ const isValid = await validateInstruction({ schema, form, setFormErrors })
+ if (!isValid) return
+
try {
setIsProposing(true)
- const newAccountNum = getNextAccountNumber(mangoAccounts)
+ const instructions: InstructionDataWithHoldUpTime[] = []
+ let mangoAccountPk = form.mangoAccount?.publicKey
const bank = mangoGroup!.getFirstBankByMint(
account.extensions.mint!.publicKey!
)
- const createAccIx = await mangoClient!.program.methods
- .accountCreate(
- newAccountNum,
- 8,
- 4,
- 4,
- 32,
- mangoAccName || `Account ${newAccountNum + 1}`
- )
- .accounts({
- group: mangoGroup!.publicKey,
- owner: account.extensions.token!.account.owner!,
- payer: account.extensions.token!.account.owner!,
- })
- .instruction()
- const acctNumBuffer = Buffer.alloc(4)
- acctNumBuffer.writeUInt32LE(newAccountNum)
+ if (form.mangoAccount === null) {
+ const newAccountNum = getNextAccountNumber(mangoAccounts)
+ const createAccIx = await mangoClient!.program.methods
+ .accountCreate(
+ newAccountNum,
+ 8,
+ 4,
+ 4,
+ 32,
+ form.accountName || `Account ${newAccountNum + 1}`
+ )
+ .accounts({
+ group: mangoGroup!.publicKey,
+ owner: account.extensions.token!.account.owner!,
+ payer: account.extensions.token!.account.owner!,
+ })
+ .instruction()
+
+ const createAccInstData = {
+ data: getInstructionDataFromBase64(
+ serializeInstructionToBase64(createAccIx)
+ ),
+ holdUpTime:
+ account?.governance.account?.config.minInstructionHoldUpTime,
+ prerequisiteInstructions: [],
+ }
+
+ instructions.push(createAccInstData)
- const [mangoAccount] = PublicKey.findProgramAddressSync(
- [
- Buffer.from('MangoAccount'),
- mangoGroup!.publicKey.toBuffer(),
- account.extensions.token!.account.owner!.toBuffer(),
- acctNumBuffer,
- ],
- mangoClient!.programId
+ const acctNumBuffer = Buffer.alloc(4)
+ acctNumBuffer.writeUInt32LE(newAccountNum)
+
+ const [mangoAccount] = PublicKey.findProgramAddressSync(
+ [
+ Buffer.from('MangoAccount'),
+ mangoGroup!.publicKey.toBuffer(),
+ account.extensions.token!.account.owner!.toBuffer(),
+ acctNumBuffer,
+ ],
+ mangoClient!.programId
+ )
+ mangoAccountPk = mangoAccount
+ }
+
+ const tokens = getMintNaturalAmountFromDecimalAsBN(
+ form.amount,
+ account.extensions.mint!.account!.decimals
)
const depositIx = await mangoClient!.program.methods
- .tokenDeposit(new BN(100000000000), false)
+ .tokenDeposit(tokens, false)
.accounts({
group: mangoGroup!.publicKey,
- account: mangoAccount,
+ account: mangoAccountPk,
owner: account.extensions.token!.account.owner!,
bank: bank.publicKey,
vault: bank.vault,
@@ -104,28 +241,6 @@ const MangoModal = ({ account }: { account: AssetAccount }) => {
)
.instruction()
- const delegateIx = await mangoClient!.program.methods
- .accountEdit(
- null,
- new PublicKey('EsWMqyaEDoAqMgiWG9McSmpetBiYjL4VkHPkfevxKu4D'),
- null,
- null
- )
- .accounts({
- group: mangoGroup!.publicKey,
- account: mangoAccount,
- owner: account.extensions.token!.account.owner!,
- })
- .instruction()
-
- const createAccInstData = {
- data: getInstructionDataFromBase64(
- serializeInstructionToBase64(createAccIx)
- ),
- holdUpTime:
- account?.governance.account?.config.minInstructionHoldUpTime,
- prerequisiteInstructions: [],
- }
const depositAccInstData = {
data: getInstructionDataFromBase64(
serializeInstructionToBase64(depositIx!)
@@ -134,23 +249,36 @@ const MangoModal = ({ account }: { account: AssetAccount }) => {
account?.governance.account?.config.minInstructionHoldUpTime,
prerequisiteInstructions: [],
}
- const delegateAccInstData = {
- data: getInstructionDataFromBase64(
- serializeInstructionToBase64(delegateIx!)
- ),
- holdUpTime:
- account?.governance.account?.config.minInstructionHoldUpTime,
- prerequisiteInstructions: [],
+
+ instructions.push(depositAccInstData)
+
+ if (form.delegate) {
+ const delegateIx = await mangoClient!.program.methods
+ .accountEdit(null, new PublicKey(form.delegateWallet), null, null)
+ .accounts({
+ group: mangoGroup!.publicKey,
+ account: mangoAccountPk,
+ owner: account.extensions.token!.account.owner!,
+ })
+ .instruction()
+
+ const delegateAccInstData = {
+ data: getInstructionDataFromBase64(
+ serializeInstructionToBase64(delegateIx!)
+ ),
+ holdUpTime:
+ account?.governance.account?.config.minInstructionHoldUpTime,
+ prerequisiteInstructions: [],
+ }
+
+ instructions.push(delegateAccInstData)
}
+
const proposalAddress = await handleCreateProposal({
- title: proposalTitle,
- description: proposalDescription,
+ title: form.title,
+ description: form.description,
voteByCouncil,
- instructionsData: [
- createAccInstData,
- depositAccInstData,
- delegateAccInstData,
- ],
+ instructionsData: instructions,
governance: account.governance!,
})
const url = fmtUrlWithCluster(
@@ -162,64 +290,182 @@ const MangoModal = ({ account }: { account: AssetAccount }) => {
}
setIsProposing(false)
}
+
return (
-
-
Mango
-
- {console.log(mangoAccount)}
- {mangoGroup && (
-
- }
- placeholder="Please select..."
- onChange={(val) => setSelectedMangoAccount(val)}
- >
- {mangoAccounts.map((x) => (
+
+
+
+
+
Mango
+
+
+
+ {account.extensions.mint?.publicKey.toBase58() ===
+ USDC_MINT.toBase58() && (
+
+ )}
+
+
+ }
+ placeholder={
+ form.mangoAccount === undefined
+ ? 'Please select...'
+ : form.mangoAccount?.name || 'Create new account'
+ }
+ onChange={(value) =>
+ handleSetForm({
+ propertyName: 'mangoAccount',
+ value,
+ })
+ }
+ >
+ {isLoadingMangoAccount && !mangoAccounts.length ? (
+ Loading accounts...
+ ) : (
+ mangoAccounts.map((x) => (
- ))}
-
- Create new account
-
-
- )}
- {!mangoAccount && (
+ ))
+ )}
+
+
+ Create new account
+
+
+ {form.mangoAccount === null && (
setMangoAccName(e.target.value)}
+ value={form.accountName}
+ onChange={(e) =>
+ handleSetForm({
+ propertyName: 'accountName',
+ value: e.target.value,
+ })
+ }
+ />
+ )}
+
+ Amount
+
+ {maxAmountFtm}
+ {
+ handleSetForm({
+ propertyName: 'amount',
+ value: maxAmount.toNumber(),
+ })
+ }}
+ >
+ Max
+
+
+
+
+ handleSetForm({
+ propertyName: 'amount',
+ value: e.target.value,
+ })
+ }
+ onBlur={() => {
+ handleSetForm({
+ propertyName: 'amount',
+ value: parseFloat(
+ Math.max(
+ Number(mintMinAmount),
+ Math.min(Number(Number.MAX_SAFE_INTEGER), Number(form.amount))
+ ).toFixed(currentPrecision)
+ ),
+ })
+ }}
+ />
+
+
Delegate
+
+ handleSetForm({
+ propertyName: 'delegate',
+ value: !form.delegate,
+ })
+ }
+ />
+
+ {form.delegate && (
+
+ handleSetForm({
+ propertyName: 'delegateWallet',
+ value: e.target.value,
+ })
+ }
/>
)}
{
- setProposalTitle(evt.target.value)
+ handleSetForm({
+ propertyName: 'title',
+ value: evt.target.value,
+ })
+ }}
+ setDescription={(evt) => {
+ handleSetForm({
+ propertyName: 'description',
+ value: evt.target.value,
+ })
}}
- setDescription={(evt) => setProposalDescription(evt.target.value)}
voteByCouncil={voteByCouncil}
setVoteByCouncil={setVoteByCouncil}
/>
@@ -232,13 +478,15 @@ const MangoAccountItem = ({
group,
}: {
account: MangoAccount | null
- group: Group
+ group: Group | null
}) => {
- return account ? (
+ return account && group ? (
Name: {account.name}
{account.publicKey.toBase58()}
-
Pnl: ${account.getPnl(group).toString()}
+
+ Account Value: ${toUiDecimals(account.getAssetsValue(group), 6)}
+
) : (
Create new account
diff --git a/components/VotePanel/YouVoted.tsx b/components/VotePanel/YouVoted.tsx
index 0b1e5b3886..2ad303b9b8 100644
--- a/components/VotePanel/YouVoted.tsx
+++ b/components/VotePanel/YouVoted.tsx
@@ -146,7 +146,9 @@ export const YouVoted = ({ quorum }: { quorum: 'electoral' | 'veto' }) => {
const isMulti = proposal?.account.voteType !== VoteType.SINGLE_CHOICE
&& proposal?.account.accountType === GovernanceAccountType.ProposalV2
-
+
+ const nota = '$$_NOTA_$$'
+
return vote !== undefined ? (
@@ -164,7 +166,11 @@ export const YouVoted = ({ quorum }: { quorum: 'electoral' | 'veto' }) => {
>
-
{proposal?.account.options[index].label}
+
{
+ proposal?.account.options[index].label === nota ?
+ "None of the Above" :
+ proposal?.account.options[index].label
+ }
diff --git a/components/VotePanel/useDelegators.ts b/components/VotePanel/useDelegators.ts
index e44a8716c1..d8fb8e3761 100644
--- a/components/VotePanel/useDelegators.ts
+++ b/components/VotePanel/useDelegators.ts
@@ -14,7 +14,7 @@ const useDelegators = (role: 'community' | 'council' | undefined) => {
? realm?.account.communityMint
: realm?.account.config.councilMint
- const torsDelegatedToUser = useTokenOwnerRecordsDelegatedToUser()
+ const { data: torsDelegatedToUser } = useTokenOwnerRecordsDelegatedToUser()
const relevantDelegators =
relevantMint &&
torsDelegatedToUser?.filter((x) =>
diff --git a/components/chat/DiscussionPanel.tsx b/components/chat/DiscussionPanel.tsx
index f5723cc846..aaf49322a0 100644
--- a/components/chat/DiscussionPanel.tsx
+++ b/components/chat/DiscussionPanel.tsx
@@ -1,6 +1,5 @@
import { useMemo } from 'react'
import DiscussionForm from './DiscussionForm'
-import Comment from './Comment'
import { useQuery } from '@tanstack/react-query'
import {
GOVERNANCE_CHAT_PROGRAM_ID,
@@ -8,6 +7,7 @@ import {
} from '@solana/spl-governance'
import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext'
import { useSelectedProposalPk } from '@hooks/queries/proposal'
+import LazyLoadComment from './LazyLoadComment'
export const useChatMessagesQuery = () => {
const connection = useLegacyConnectionContext()
@@ -57,7 +57,7 @@ const DiscussionPanel = () => {
{sortedMessages?.map((cm) => (
-
+
))}
)
diff --git a/components/chat/LazyLoadComment.tsx b/components/chat/LazyLoadComment.tsx
new file mode 100644
index 0000000000..773c441727
--- /dev/null
+++ b/components/chat/LazyLoadComment.tsx
@@ -0,0 +1,19 @@
+import React from 'react'
+import { useInView } from 'react-intersection-observer'
+import Comment from './Comment'
+import { ChatMessage } from '@solana/spl-governance'
+
+const LazyLoadComment = ({ chatMessage }: { chatMessage: ChatMessage }) => {
+ const { ref, inView } = useInView({
+ /* Optional options */
+ triggerOnce: true,
+ })
+
+ return (
+
+ )
+}
+
+export default LazyLoadComment
diff --git a/components/instructions/TransactionCard.tsx b/components/instructions/TransactionCard.tsx
index 1c6f719602..90ba969729 100644
--- a/components/instructions/TransactionCard.tsx
+++ b/components/instructions/TransactionCard.tsx
@@ -23,6 +23,7 @@ export default function TransactionCard({
? PlayState.Played
: PlayState.Unplayed
)
+
return (
{`Transaction ${index} `}
diff --git a/components/instructions/programs/governance.tsx b/components/instructions/programs/governance.tsx
index 0326295be2..6681a5459a 100644
--- a/components/instructions/programs/governance.tsx
+++ b/components/instructions/programs/governance.tsx
@@ -35,6 +35,7 @@ import {
import { dryRunInstruction } from 'actions/dryRunInstruction'
import { tryGetMint } from '../../../utils/tokens'
import { fetchProgramVersion } from '@hooks/queries/useProgramVersionQuery'
+import { fetchTokenAccountByPubkey } from '@hooks/queries/tokenAccount'
const TOKEN_TYPES = { 0: 'Liquid', 1: 'Membership', 2: 'Disabled' }
const governanceProgramId = 'GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw'
@@ -83,10 +84,17 @@ export const GOVERNANCE_INSTRUCTIONS = {
)
//accounts[2] is token account not mint account
- const mintInfoQuery = await fetchMintInfoByPubkey(
+ const { result: tokenAccount } = await fetchTokenAccountByPubkey(
connection,
accounts[2].pubkey
)
+ if (!tokenAccount) {
+ throw new Error()
+ }
+ const mintInfoQuery = await fetchMintInfoByPubkey(
+ connection,
+ tokenAccount.mint
+ )
const args = deserializeBorsh(
getGovernanceInstructionSchema(programVersion),
diff --git a/components/instructions/programs/mangoV4.tsx b/components/instructions/programs/mangoV4.tsx
index 509fcda4fb..1c3af336eb 100644
--- a/components/instructions/programs/mangoV4.tsx
+++ b/components/instructions/programs/mangoV4.tsx
@@ -1,17 +1,14 @@
import {
Bank,
- MANGO_V4_ID,
- MangoClient,
OracleProvider,
USDC_MINT,
toUiDecimals,
} from '@blockworks-foundation/mango-v4'
import AdvancedOptionsDropdown from '@components/NewRealmWizard/components/AdvancedOptionsDropdown'
-import { AnchorProvider, BN, BorshInstructionCoder } from '@coral-xyz/anchor'
+import { BN, BorshInstructionCoder } from '@coral-xyz/anchor'
import { AccountMetaData } from '@solana/spl-governance'
-import { Connection, Keypair, PublicKey } from '@solana/web3.js'
-import EmptyWallet, {
- getSuggestedCoinTier,
+import { Connection, PublicKey } from '@solana/web3.js'
+import {
compareObjectsAndGetDifferentKeys,
FlatListingArgs,
ListingArgsFormatted,
@@ -23,6 +20,7 @@ import EmptyWallet, {
decodePriceFromOracleAi,
getFormattedBankValues,
REDUCE_ONLY_OPTIONS,
+ getSuggestedCoinPresetInfo,
} from '@utils/Mango/listingTools'
import { secondsToHours } from 'date-fns'
import WarningFilledIcon from '@carbon/icons-react/lib/WarningFilled'
@@ -32,17 +30,17 @@ import tokenPriceService, {
TokenInfoWithoutDecimals,
} from '@utils/services/tokenPrice'
import {
- LISTING_PRESETS,
- LISTING_PRESETS_KEYS,
- LISTING_PRESETS_PYTH,
+ LISTING_PRESETS_KEY,
MidPriceImpact,
coinTiersToNames,
getMidPriceImpacts,
- getProposedTier,
+ getProposedKey,
} from '@blockworks-foundation/mango-v4-settings/lib/helpers/listingTools'
import { tryParseKey } from '@tools/validators/pubkey'
import Loading from '@components/Loading'
-import queryClient from '@hooks/queries/queryClient'
+import { getClient, getGroupForClient } from '@utils/mangoV4Tools'
+import { tryGetMint } from '@utils/tokens'
+import { formatNumber } from '@utils/formatNumber'
// import { snakeCase } from 'snake-case'
// import { sha256 } from 'js-sha256'
@@ -234,11 +232,18 @@ const instructions = () => ({
const oracle = accounts[6].pubkey
const isMintOnCurve = PublicKey.isOnCurve(proposedMint)
- const [info, proposedOracle, args, oracleAi] = await Promise.all([
+ const [
+ info,
+ proposedOracle,
+ args,
+ oracleAi,
+ mintInfo,
+ ] = await Promise.all([
displayArgs(connection, data),
getOracle(connection, oracle),
getDataObjectFlattened
(connection, data),
connection.getAccountInfo(oracle),
+ tryGetMint(connection, proposedMint),
])
const oracleData = await decodePriceFromOracleAi(
@@ -247,27 +252,55 @@ const instructions = () => ({
proposedOracle.type
)
- const liqudityTier = await getSuggestedCoinTier(
+ const presetInfo = await getSuggestedCoinPresetInfo(
proposedMint.toBase58(),
proposedOracle.type === 'Pyth'
)
const formattedProposedArgs = getFormattedListingValues(args)
- const suggestedPreset = getFormattedListingPresets(
- proposedOracle.type === 'Pyth'
- )[liqudityTier.tier]
- const suggestedUntrusted = liqudityTier.tier === 'UNTRUSTED'
+ const formattedSuggestedPresets = getFormattedListingPresets(
+ proposedOracle.type === 'Pyth',
+ 0,
+ mintInfo?.account.decimals || 0,
+ oracleData.uiPrice
+ )
- const suggestedFormattedPreset: ListingArgsFormatted =
- Object.keys(suggestedPreset).length && !suggestedUntrusted
- ? getFormattedListingValues({
- tokenIndex: args.tokenIndex,
- name: args.name,
- oracle: args.oracle,
- ...suggestedPreset,
- })
- : ({} as ListingArgsFormatted)
+ const currentListingArgsMatchedTier = Object.values(
+ formattedSuggestedPresets
+ ).find((preset) => {
+ const formattedPreset = getFormattedListingValues({
+ tokenIndex: args.tokenIndex,
+ name: args.name,
+ oracle: args.oracle,
+ ...preset,
+ })
+
+ return (
+ JSON.stringify({
+ //deposit limit depends on current price so can be different a bit in proposal
+ ...formattedProposedArgs,
+ depositLimit: 0,
+ }) ===
+ JSON.stringify({
+ ...formattedPreset,
+ depositLimit: 0,
+ })
+ )
+ })
+
+ const suggestedPreset = formattedSuggestedPresets[presetInfo.presetKey]
+
+ const suggestedFormattedPreset: ListingArgsFormatted = Object.keys(
+ suggestedPreset
+ ).length
+ ? getFormattedListingValues({
+ tokenIndex: args.tokenIndex,
+ name: args.name,
+ oracle: args.oracle,
+ ...suggestedPreset,
+ })
+ : ({} as ListingArgsFormatted)
const invalidKeys: (keyof ListingArgsFormatted)[] = Object.keys(
suggestedPreset
@@ -277,24 +310,32 @@ const instructions = () => ({
suggestedFormattedPreset
)
: []
- const invalidFields: Partial = invalidKeys.reduce(
- (obj, key) => {
+
+ const invalidFields: Partial = invalidKeys
+ .filter((x) => {
+ //soft invalid keys - some of the keys can be off by some small maring
+ if (x === 'depositLimit') {
+ return !isDifferenceWithin5Percent(
+ Number(formattedProposedArgs['depositLimit'] || 0),
+ Number(suggestedFormattedPreset['depositLimit'] || 0)
+ )
+ }
+ return true
+ })
+ .reduce((obj, key) => {
return {
...obj,
[key]: suggestedFormattedPreset[key],
}
- },
- {}
- )
+ }, {})
+
const DisplayListingPropertyWrapped = ({
label,
- suggestedUntrusted,
valKey,
suffix,
prefix: perfix,
}: {
label: string
- suggestedUntrusted: boolean
valKey: string
suffix?: string
prefix?: string
@@ -302,7 +343,6 @@ const instructions = () => ({
return (
({
return (
- {suggestedUntrusted && (
+ {presetInfo.presetKey === 'UNTRUSTED' && (
<>
- Suggested token tier: UNTRUSTED.
+ Suggested token tier: C
- Very low liquidity Price impact of{' '}
- {liqudityTier.priceImpact}% on $1000 swap. This token should
- probably be listed using the Register Trustless Token
- instruction check params carefully
+ Very low liquidity check params carefully
>
)}
- {!suggestedUntrusted && !invalidKeys.length && (
+ {!invalidKeys.length && (
Proposal params match suggested token tier -{' '}
- {coinTiersToNames[liqudityTier.tier]}.
+ {coinTiersToNames[presetInfo.presetKey]}.
)}
- {!suggestedUntrusted && invalidKeys.length > 0 && (
+ {invalidKeys.length > 0 && (
Proposal params do not match suggested token tier -{' '}
- {coinTiersToNames[liqudityTier.tier]} check params carefully
+ {coinTiersToNames[presetInfo.presetKey]} check params
+ carefully
+
+ )}
+ {currentListingArgsMatchedTier && (
+
+
+ Full match found with tier {/* @ts-ignore */}
+ {currentListingArgsMatchedTier.preset_name}
)}
{isMintOnCurve && (
@@ -391,186 +436,184 @@ const instructions = () => ({
-
-
@@ -610,17 +653,17 @@ const instructions = () => ({
const info = await displayArgs(connection, data)
const client = await getClient(connection)
- const mangoGroup = await client.getGroup(group)
+ const mangoGroup = await getGroupForClient(client, group)
const banks = [...mangoGroup.banksMapByMint.values()].map((x) => x[0])
let baseMint = banks.find((x) => x.publicKey.equals(baseBank))?.mint
let quoteMint = banks.find((x) => x.publicKey.equals(quoteBank))?.mint
+ const currentMarket = await Market.load(
+ connection,
+ openbookMarketPk,
+ undefined,
+ openBookProgram
+ )
if (!baseMint || !quoteMint) {
- const currentMarket = await Market.load(
- connection,
- openbookMarketPk,
- undefined,
- openBookProgram
- )
baseMint = currentMarket.baseMintAddress
quoteMint = currentMarket.quoteMintAddress
}
@@ -635,7 +678,7 @@ const instructions = () => ({
try {
return (
- {bestMarket && openbookMarketPk.equals(bestMarket) && (
+ {bestMarket && openbookMarketPk.equals(bestMarket.pubKey) && (
Proposed market match the best market according to listing
@@ -648,7 +691,13 @@ const instructions = () => ({
Best market not found check market carefully
)}
- {bestMarket && !openbookMarketPk.equals(bestMarket) && (
+ {bestMarket?.error && (
+
+
+ {bestMarket?.error}
+
+ )}
+ {bestMarket && !openbookMarketPk.equals(bestMarket.pubKey) && (
+
+
+
Tick Size: {currentMarket.tickSize}
+
+ Base Lot Size: {currentMarket.decoded?.baseLotSize?.toNumber()}
+
+
+ Quote Lot Size:{' '}
+ {currentMarket.decoded?.quoteLotSize?.toNumber()}
+
+
+ Quote decimals: {currentMarket['_quoteSplTokenDecimals']}
+
+
Base decimals: {currentMarket['_baseSplTokenDecimals']}
+
{info}
)
@@ -779,15 +843,16 @@ const instructions = () => ({
displayArgs(connection, data),
getDataObjectFlattened
(connection, data),
])
+ let priceImpact: MidPriceImpact | undefined
const mint = [...mangoGroup.mintInfosMapByMint.values()].find((x) =>
x.publicKey.equals(mintInfo)
)?.mint
let liqudityTier: Partial<{
- tier: LISTING_PRESETS_KEYS
+ presetKey: LISTING_PRESETS_KEY
priceImpact: string
}> = {}
- let suggestedUntrusted = false
+
let invalidKeys: (keyof EditTokenArgsFormatted)[] = []
let invalidFields: Partial = {}
let bank: null | Bank = null
@@ -798,11 +863,15 @@ const instructions = () => ({
const parsedArgs: Partial = {
tokenIndex: args.tokenIndex,
tokenName: args.nameOpt,
- oracleConfidenceFilter:
- args['oracleConfigOpt.confFilter'] !== undefined
- ? (args['oracleConfigOpt.confFilter'] * 100)?.toFixed(2)
- : undefined,
- oracleMaxStalenessSlots: args['oracleConfigOpt.maxStalenessSlots'],
+ oracleConfidenceFilter: args['oracleConfigOpt.confFilter']
+ ? args['oracleConfigOpt.confFilter'] >= 100
+ ? args['oracleConfigOpt.confFilter'].toString()
+ : (args['oracleConfigOpt.confFilter'] * 100).toFixed(2)
+ : undefined,
+ oracleMaxStalenessSlots:
+ args['oracleConfigOpt.maxStalenessSlots'] === null
+ ? -1
+ : args['oracleConfigOpt.maxStalenessSlots'],
interestRateUtilizationPoint0:
args['interestRateParamsOpt.util0'] !== undefined
? (args['interestRateParamsOpt.util0'] * 100)?.toFixed(2)
@@ -873,7 +942,10 @@ const instructions = () => ({
args.tokenConditionalSwapMakerFeeRateOpt,
tokenConditionalSwapTakerFeeRate:
args.tokenConditionalSwapTakerFeeRateOpt,
- flashLoanSwapFeeRate: args.flashLoanSwapFeeRateOpt,
+ flashLoanSwapFeeRate:
+ args.flashLoanSwapFeeRateOpt !== undefined
+ ? (args.loanOriginationFeeRateOpt * 10000)?.toFixed(2)
+ : undefined,
reduceOnly:
args.reduceOnlyOpt !== undefined
? REDUCE_ONLY_OPTIONS[args.reduceOnlyOpt].name
@@ -894,12 +966,15 @@ const instructions = () => ({
bankFormattedValues = getFormattedBankValues(mangoGroup, bank)
mintData = tokenPriceService.getTokenInfo(mint.toBase58())
const isPyth = bank?.oracleProvider === OracleProvider.Pyth
- const midPriceImpacts = getMidPriceImpacts(mangoGroup.pis)
- const PRESETS = isPyth ? LISTING_PRESETS_PYTH : LISTING_PRESETS
+ const midPriceImpacts = getMidPriceImpacts(
+ mangoGroup.pis.length ? mangoGroup.pis : []
+ )
const tokenToPriceImpact = midPriceImpacts
- .filter((x) => x.avg_price_impact_percent < 1)
+ .filter(
+ (x) => x.avg_price_impact_percent < 1 || x.target_amount <= 1000
+ )
.reduce(
(acc: { [key: string]: MidPriceImpact }, val: MidPriceImpact) => {
if (
@@ -913,31 +988,35 @@ const instructions = () => ({
{}
)
- const priceImpact = tokenToPriceImpact[getApiTokenName(bank.name)]
+ priceImpact = tokenToPriceImpact[getApiTokenName(bank.name)]
- const suggestedTier = getProposedTier(
- PRESETS,
- priceImpact?.target_amount,
- bank.oracleProvider === OracleProvider.Pyth
- )
+ const suggestedPresetKey = priceImpact
+ ? getProposedKey(
+ priceImpact.avg_price_impact_percent < 1
+ ? priceImpact?.target_amount
+ : undefined,
+ bank.oracleProvider === OracleProvider.Pyth
+ )
+ : 'UNTRUSTED'
liqudityTier = !mint.equals(USDC_MINT)
? {
- tier: suggestedTier,
+ presetKey: suggestedPresetKey,
priceImpact: priceImpact
? priceImpact.avg_price_impact_percent.toString()
: '',
}
: {
- tier: 'ULTRA_PREMIUM',
+ presetKey: 'asset_250p',
priceImpact: '0',
}
const suggestedPreset = getFormattedListingPresets(
!!isPyth,
- bank.nativeDeposits().mul(bank.price).toNumber()
- )[liqudityTier.tier!]
- suggestedUntrusted = liqudityTier.tier === 'UNTRUSTED'
+ bank.uiDeposits(),
+ bank.mintDecimals,
+ bank.uiPrice
+ )[liqudityTier.presetKey!]
const suggestedFormattedPreset:
| EditTokenArgsFormatted
@@ -965,7 +1044,27 @@ const instructions = () => ({
Partial
>(parsedArgs, suggestedFormattedPreset)
: []
- ).filter((x) => parsedArgs[x] !== undefined)
+ )
+ .filter((x) => parsedArgs[x] !== undefined)
+ .filter((x) => {
+ //soft invalid keys - some of the keys can be off by some small maring
+ if (x === 'depositLimit') {
+ return !isDifferenceWithin5Percent(
+ Number(parsedArgs['depositLimit'] || 0),
+ Number(suggestedFormattedPreset['depositLimit'] || 0)
+ )
+ }
+ if (x === 'netBorrowLimitPerWindowQuote') {
+ return !isDifferenceWithin5Percent(
+ Number(parsedArgs['netBorrowLimitPerWindowQuote'] || 0),
+ Number(
+ suggestedFormattedPreset['netBorrowLimitPerWindowQuote'] ||
+ 0
+ )
+ )
+ }
+ return true
+ })
invalidFields = invalidKeys.reduce((obj, key) => {
return {
@@ -978,36 +1077,38 @@ const instructions = () => ({
return (
{mintData && Token: {mintData.symbol}
}
- {suggestedUntrusted && (
+ {!priceImpact && (
+
+
+ No price impact data in group
+
+ )}
+ {liqudityTier.presetKey === 'UNTRUSTED' && (
<>
- Suggested token tier: UNTRUSTED.
+ Suggested token tier: C
- Very low liquidity Price impact of {liqudityTier?.priceImpact}
- % on $1000 swap. Check params carefully token should be listed
- with untrusted instruction
+ Very low liquidity check params carefully
>
)}
- {!suggestedUntrusted && !invalidKeys.length && liqudityTier.tier && (
+ {!invalidKeys.length && liqudityTier.presetKey && (
Proposal params match suggested token tier -{' '}
- {coinTiersToNames[liqudityTier.tier]}.
+ {coinTiersToNames[liqudityTier.presetKey]}.
+
+ )}
+ {invalidKeys && invalidKeys!.length > 0 && liqudityTier.presetKey && (
+
+
+ Proposal params do not match suggested token tier -{' '}
+ {coinTiersToNames[liqudityTier.presetKey]} check params
+ carefully
)}
- {!suggestedUntrusted &&
- invalidKeys &&
- invalidKeys!.length > 0 &&
- liqudityTier.tier && (
-
-
- Proposal params do not match suggested token tier -{' '}
- {coinTiersToNames[liqudityTier.tier]} check params carefully
-
- )}
- Current values
@@ -1047,7 +1148,11 @@ const instructions = () => ({
({
`${invalidFields.netBorrowLimitWindowSizeTs}H`
}
/>
+
({
/>
({
suggestedVal={invalidFields.maintWeightShiftLiabTarget}
/>
{parsedArgs?.maintWeightShiftAbort && (
({
}
},
},
- 73195: {
+ 11366: {
name: 'Withdraw all token fees',
accounts: [
{ name: 'Group' },
@@ -1515,12 +1678,35 @@ const instructions = () => ({
],
getDataUI: async (
connection: Connection,
- data: Uint8Array
- //accounts: AccountMetaData[]
+ data: Uint8Array,
+ accounts: AccountMetaData[]
) => {
- const info = await displayArgs(connection, data)
+ const args = await getDataObjectFlattened(connection, data)
+ const accountInfo = await connection.getParsedAccountInfo(
+ accounts[6].pubkey
+ )
+ const mint = await tryGetMint(
+ connection,
+ new PublicKey(accountInfo.value?.data['parsed'].info.mint)
+ )
+ const tokenInfo = tokenPriceService.getTokenInfo(
+ accountInfo.value?.data['parsed'].info.mint
+ )
try {
- return {info}
+ return (
+
+
+ amount:{' '}
+ {mint?.account.decimals
+ ? formatNumber(
+ toUiDecimals(args.amount, mint?.account.decimals)
+ )
+ : args.amount}{' '}
+ {tokenInfo?.symbol}
+
+
reduce only: {args.reduceOnly.toString()}
+
+ )
} catch (e) {
console.log(e)
return {JSON.stringify(data)}
@@ -1553,79 +1739,52 @@ const instructions = () => ({
export const MANGO_V4_INSTRUCTIONS = {
'4MangoMjqJ2firMokCjjGgoK8d4MXcrgL7XJaL3w6fVg': instructions(),
-}
-
-const getClient = async (connection: Connection) => {
- const client = await queryClient.fetchQuery({
- queryKey: ['mangoClient', connection.rpcEndpoint],
- queryFn: async () => {
- const options = AnchorProvider.defaultOptions()
- const adminProvider = new AnchorProvider(
- connection,
- new EmptyWallet(Keypair.generate()),
- options
- )
- const client = await MangoClient.connect(
- adminProvider,
- 'mainnet-beta',
- MANGO_V4_ID['mainnet-beta']
- )
-
- return client
- },
- })
- return client
-}
-const getGroupForClient = async (client: MangoClient, groupPk: PublicKey) => {
- const group = await queryClient.fetchQuery({
- queryKey: ['mangoGroup', groupPk.toBase58(), client.connection.rpcEndpoint],
- queryFn: async () => {
- const response = await client.getGroup(groupPk)
- return response
- },
- })
- return group
+ zF2vSz6V9g1YHGmfrzsY497NJzbRr84QUrPry4bLQ25: instructions(),
}
async function getDataObjectFlattened(
connection: Connection,
data: Uint8Array
) {
- const client = await getClient(connection)
- const decodedInstructionData = new BorshInstructionCoder(
- client.program.idl
- ).decode(Buffer.from(data))?.data as any
+ try {
+ const client = await getClient(connection)
+ const decodedInstructionData = new BorshInstructionCoder(
+ client.program.idl
+ ).decode(Buffer.from(data))?.data as any
- // console.log(
- // client.program.idl.instructions.map((ix) => {
- // const sh = sighash('global', ix.name)
- // return {
- // name: ix.name,
- // sh: `${sh[0]}${sh[1]}`,
- // }
- // })
- // )
+ // console.log(
+ // client.program.idl.instructions.map((ix) => {
+ // const sh = sighash('global', ix.name)
+ // return {
+ // name: ix.name,
+ // sh: `${sh[0]}${sh[1]}`,
+ // }
+ // })
+ // )
- const args = {}
- for (const key of Object.keys(decodedInstructionData)) {
- const val = decodedInstructionData[key]
- if (val !== null) {
- if (
- typeof val === 'object' &&
- !Array.isArray(val) &&
- !(val instanceof BN) &&
- !(val instanceof PublicKey)
- ) {
- for (const innerKey of Object.keys(val)) {
- const innerVal = val[innerKey]
- args[`${key}.${innerKey}`] = innerVal
+ const args = {}
+ for (const key of Object.keys(decodedInstructionData)) {
+ const val = decodedInstructionData[key]
+ if (val !== null) {
+ if (
+ typeof val === 'object' &&
+ !Array.isArray(val) &&
+ !(val instanceof BN) &&
+ !(val instanceof PublicKey)
+ ) {
+ for (const innerKey of Object.keys(val)) {
+ const innerVal = val[innerKey]
+ args[`${key}.${innerKey}`] = innerVal
+ }
+ } else {
+ args[key] = val
}
- } else {
- args[key] = val
}
}
+ return args as T
+ } catch (e) {
+ return {} as T
}
- return args as T
}
const displayArgs = async (connection: Connection, data: Uint8Array) => {
@@ -1710,14 +1869,12 @@ const DisplayNullishProperty = ({
const DisplayListingProperty = ({
label,
- suggestedUntrusted,
val,
suggestedVal,
suffix,
prefix,
}: {
label: string
- suggestedUntrusted: boolean
val: any
suggestedVal?: any
suffix?: string
@@ -1726,9 +1883,7 @@ const DisplayListingProperty = ({
{label}:
-
+
{prefix}
{`${val}`}
{suffix}
@@ -1750,7 +1905,7 @@ const getFormattedListingValues = (args: FlatListingArgs) => {
const formattedArgs: ListingArgsFormatted = {
tokenIndex: args.tokenIndex,
tokenName: args.name,
- oracle: args.oracle?.toBase58(),
+ oracle: args.oracle?.toBase58 && args.oracle?.toBase58(),
oracleConfidenceFilter:
args['oracleConfig.confFilter'] >= 100
? args['oracleConfig.confFilter'].toString()
@@ -1798,7 +1953,7 @@ const getFormattedListingValues = (args: FlatListingArgs) => {
stablePriceGrowthLimit: (args.stablePriceGrowthLimit * 100).toFixed(2),
tokenConditionalSwapMakerFeeRate: args.tokenConditionalSwapMakerFeeRate,
tokenConditionalSwapTakerFeeRate: args.tokenConditionalSwapTakerFeeRate,
- flashLoanSwapFeeRate: args.flashLoanSwapFeeRate,
+ flashLoanSwapFeeRate: (args.flashLoanSwapFeeRate * 10000).toFixed(2),
reduceOnly: REDUCE_ONLY_OPTIONS[args.reduceOnly].name,
depositLimit: args.depositLimit.toString(),
interestTargetUtilization: args.interestTargetUtilization,
@@ -1821,3 +1976,17 @@ const getApiTokenName = (bankName: string) => {
}
return bankName
}
+
+function isDifferenceWithin5Percent(a: number, b: number): boolean {
+ // Calculate the absolute difference
+ const difference = Math.abs(a - b)
+
+ // Calculate the average of the two numbers
+ const average = (a + b) / 2
+
+ // Calculate the percentage difference
+ const percentageDifference = (difference / average) * 100
+
+ // Check if the difference is within 5%
+ return percentageDifference <= 5
+}
diff --git a/components/instructions/tools.tsx b/components/instructions/tools.tsx
index 418652698d..bb120a7095 100644
--- a/components/instructions/tools.tsx
+++ b/components/instructions/tools.tsx
@@ -137,6 +137,12 @@ export const ACCOUNT_NAMES = {
FAFDfoUkaxoMqiNur9F1iigdBNrXFf4uNmS5XrhMewvf:
'Friends and Family Community Mint',
+ // Dean's List DAO
+ '6Vjsy1KabnHtSuHZcXuuCQFWoBML9JscSy3L4NGjqmhM': 'Deans List DAO Treasury',
+ 'CLgzSdeNcf9CYHiAdmXaPaCw2vYBeiqEeZcgguqirVM9': 'DAO: (DEAN) Strategic Reserve',
+ 'bDgqY2Qt4y2jSsRNvD7FETkRJJNiYZT1Q3UnAYYzUCo': 'DAO: (DEAN) Community Reserve',
+ 'BtJaNZrZZmagHGzCU2VazSJWzBS9KY7tG41enBrT2NtU': 'DAO: (DEAN) Liquidity Reserve',
+
// Physis DAO
'29epeLvAMyRXtpA1HaoKB1hGcAnrc1NvMCbaZ8AVRwEi': 'Physis DAO Treasury',
'4i2Yjk5bUiLeVNwqBpkRdFSECSCvMgKoeCSdRSx1TPcz': 'DAO: Rewards (PHY)',
@@ -389,6 +395,12 @@ const HIDDEN_MNGO_TREASURES = [
'PuXf9LNrmtVDhBTxteNTWS8D2SpzbhYvidkSatjRArt',
]
+//badly created realms
+export const HIDDEN_REALMS = [
+ 'BWnVbUDohApiiaWBNNGcLH2KXRKEoTBJ7schsKQWYAtj',
+ 'FsoDEiZ9BoGTAaCLzXkyQWEqNKa5PW2iokzmuD7YsRdL',
+]
+
//owner and desired accounts we want to show
const MNGO_AUXILIARY_TOKEN_ACCOUNTS = [
{
diff --git a/components/treasuryV2/Details/TokenDetails/Investments.tsx b/components/treasuryV2/Details/TokenDetails/Investments.tsx
index 7e0bec0682..845b929a12 100644
--- a/components/treasuryV2/Details/TokenDetails/Investments.tsx
+++ b/components/treasuryV2/Details/TokenDetails/Investments.tsx
@@ -198,7 +198,6 @@ export default function Investments(props: Props) {
{alternativeInvestment === 'Mango' && (
setAlternativeInvestment(null)}
>
diff --git a/components/treasuryV2/WalletList/WalletListItem/AssetList/NFTList.tsx b/components/treasuryV2/WalletList/WalletListItem/AssetList/NFTList.tsx
index 5c011d80f2..8b9e7c9d79 100644
--- a/components/treasuryV2/WalletList/WalletListItem/AssetList/NFTList.tsx
+++ b/components/treasuryV2/WalletList/WalletListItem/AssetList/NFTList.tsx
@@ -33,7 +33,6 @@ export default function NFTList({ governance, ...props }: Props) {
.map((x) => new PublicKey(x)),
[nfts]
)
- console.log('collectionIds', JSON.stringify(collectionIds))
const hasNftWithoutCollection = nfts?.find((x) => x.grouping.length < 1)
diff --git a/hooks/PythNetwork/useScalingFactor.ts b/hooks/PythNetwork/useScalingFactor.ts
new file mode 100644
index 0000000000..7f76becfe7
--- /dev/null
+++ b/hooks/PythNetwork/useScalingFactor.ts
@@ -0,0 +1,33 @@
+import NodeWallet from "@coral-xyz/anchor/dist/cjs/nodewallet";
+import { determineVotingPowerType } from "@hooks/queries/governancePower";
+import useSelectedRealmPubkey from "@hooks/selectedRealm/useSelectedRealmPubkey";
+import { PythClient } from "@pythnetwork/staking";
+import { useConnection } from "@solana/wallet-adapter-react";
+import { useAsync } from "react-async-hook";
+import { useQuery } from "@tanstack/react-query";
+
+/**
+ * Returns undefined for everything except the Pyth DAO
+ */
+export default function usePythScalingFactor(): number | undefined {
+ const realm = useSelectedRealmPubkey()
+ const { connection } = useConnection()
+ const { result: plugin } = useAsync(
+ async () =>
+ realm && determineVotingPowerType(connection, realm, 'community'),
+ [connection, realm]
+ )
+
+ const { data: scalingFactor } = useQuery(["pyth-scaling-factor"],
+ async (): Promise => {
+ const pythClient = await PythClient.connect(connection, {} as NodeWallet)
+ return pythClient.getScalingFactor()
+ }, { enabled: plugin == "pyth" })
+
+ if (plugin == "pyth") {
+ return scalingFactor
+ } else {
+ return undefined
+ }
+}
+
diff --git a/hooks/queries/digitalAssets.ts b/hooks/queries/digitalAssets.ts
index 147283d936..76409803eb 100644
--- a/hooks/queries/digitalAssets.ts
+++ b/hooks/queries/digitalAssets.ts
@@ -217,24 +217,35 @@ const dasByOwnerQueryFn = async (network: Network, owner: PublicKey) => {
// https://docs.helius.xyz/solana-compression/digital-asset-standard-das-api/get-assets-by-owner
- const response = await fetch(url, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify({
- jsonrpc: '2.0',
- id: 'Realms user',
- method: 'getAssetsByOwner',
- params: {
- ownerAddress: owner.toString(),
- page: 1, // Starts at 1
- limit: 1000, // TODO support having >1k nfts
+ const PAGE_LIMIT = 1000
+ const items: DasNftObject[] = []
+ let moreNftsRemaining = true
+ let page = 1
+
+ while (moreNftsRemaining) {
+ const response = await fetch(url, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
},
- }),
- })
- const { result } = await response.json()
- return result.items as DasNftObject[]
+ body: JSON.stringify({
+ jsonrpc: '2.0',
+ id: 'Realms user',
+ method: 'getAssetsByOwner',
+ params: {
+ ownerAddress: owner.toString(),
+ page, // Starts at 1
+ limit: PAGE_LIMIT,
+ },
+ }),
+ })
+ const { result } = await response.json()
+ const pageItems = result.items as DasNftObject[]
+ items.push(...pageItems)
+ page++
+ if (pageItems.length < PAGE_LIMIT) moreNftsRemaining = false
+ }
+ return items
}
export const fetchDigitalAssetsByOwner = (network: Network, owner: PublicKey) =>
diff --git a/hooks/queries/jupiterPrice.ts b/hooks/queries/jupiterPrice.ts
index daf578e942..0c153837cc 100644
--- a/hooks/queries/jupiterPrice.ts
+++ b/hooks/queries/jupiterPrice.ts
@@ -92,6 +92,17 @@ export const useJupiterPricesByMintsQuery = (mints: PublicKey[]) => {
(acc, next) => ({ ...acc, ...next.data }),
{} as Response['data']
)
+
+ //override chai price if its broken
+ const chaiMint = '3jsFX1tx2Z8ewmamiwSU851GzyzM2DJMq7KWW5DM8Py3'
+ const chaiData = data[chaiMint]
+
+ if (chaiData?.price && (chaiData.price > 1.3 || chaiData.price < 0.9)) {
+ data[chaiMint] = {
+ ...chaiData,
+ price: 1,
+ }
+ }
return data
},
onSuccess: (data) => {
diff --git a/hooks/queries/plugins/nftVoter.ts b/hooks/queries/plugins/nftVoter.ts
index edc45a7d7b..4e56996482 100644
--- a/hooks/queries/plugins/nftVoter.ts
+++ b/hooks/queries/plugins/nftVoter.ts
@@ -24,6 +24,7 @@ export const useVotingNfts = (ownerPk: PublicKey | undefined) => {
const { connection } = useConnection()
const realmPk = useSelectedRealmPubkey()
const { data: nfts } = useDigitalAssetsByOwner(ownerPk)
+ console.log('nfts', nfts)
const registrar = useQuery(nftRegistrarQuery(connection, realmPk)).data
?.result
diff --git a/hooks/queries/realm.ts b/hooks/queries/realm.ts
index b750a1c51b..c55762c6e2 100644
--- a/hooks/queries/realm.ts
+++ b/hooks/queries/realm.ts
@@ -6,6 +6,7 @@ import { getNetworkFromEndpoint } from '@utils/connection'
import asFindable from '@utils/queries/asFindable'
import queryClient from './queryClient'
import { useConnection } from '@solana/wallet-adapter-react'
+import { HIDDEN_REALMS } from '@components/instructions/tools'
export const realmQueryKeys = {
all: (endpoint: string) => [endpoint, 'Realm'],
@@ -30,7 +31,10 @@ export const useRealmsByProgramQuery = (program: PublicKey) => {
: undefined,
queryFn: async () => {
if (!enabled) throw new Error()
- return getRealms(connection, program)
+ const realms = (await getRealms(connection, program)).filter(
+ (x) => !HIDDEN_REALMS.includes(x.pubkey.toBase58())
+ )
+ return realms
},
staleTime: 3600000, // 1 hour
cacheTime: 3600000 * 24 * 10,
diff --git a/hooks/queries/tokenOwnerRecord.ts b/hooks/queries/tokenOwnerRecord.ts
index 092a438153..6f25a3316f 100644
--- a/hooks/queries/tokenOwnerRecord.ts
+++ b/hooks/queries/tokenOwnerRecord.ts
@@ -3,6 +3,7 @@ import {
getGovernanceAccounts,
getTokenOwnerRecord,
pubkeyFilter,
+ booleanFilter,
} from '@solana/spl-governance'
import { Connection, PublicKey } from '@solana/web3.js'
import { useQuery } from '@tanstack/react-query'
@@ -12,7 +13,6 @@ import {
useAddressQuery_CouncilTokenOwner,
} from './addresses/tokenOwnerRecord'
import { useRealmQuery } from './realm'
-import { useMemo } from 'react'
import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext'
import useWalletOnePointOh from '@hooks/useWalletOnePointOh'
import queryClient from './queryClient'
@@ -27,14 +27,24 @@ export const tokenOwnerRecordQueryKeys = {
byRealm: (endpoint: string, realm: PublicKey) => [
...tokenOwnerRecordQueryKeys.all(endpoint),
'by Realm',
- realm,
+ realm.toString(),
],
+ byRealmXDelegate: (
+ endpoint: string,
+ realm: PublicKey,
+ delegate: PublicKey
+ ) => [
+ ...tokenOwnerRecordQueryKeys.byRealm(endpoint, realm),
+ 'by Delegate',
+ delegate.toString(),
+ ],
+
byProgramXOwner: (endpoint: string, program: PublicKey, owner: PublicKey) => [
...tokenOwnerRecordQueryKeys.all(endpoint),
'by Program',
- program,
+ program.toString(),
'by Owner',
- owner,
+ owner.toString(),
],
}
@@ -120,24 +130,58 @@ export const useTokenOwnerRecordsForRealmQuery = () => {
return query
}
-
+// 1 + 32 + 32 + 32 + 8 + 4 + 4 + 1 + 1 + 6
// TODO filter in the gPA (would need rpc to also index)
export const useTokenOwnerRecordsDelegatedToUser = () => {
- const { data: tors } = useTokenOwnerRecordsForRealmQuery()
+ const connection = useLegacyConnectionContext()
+ const realm = useRealmQuery().data?.result
const wallet = useWalletOnePointOh()
- const delagatingTors = useMemo(
- () =>
- tors?.filter(
- (x) =>
- wallet?.publicKey !== undefined &&
- wallet?.publicKey !== null &&
- x.account.governanceDelegate !== undefined &&
- x.account.governanceDelegate.equals(wallet.publicKey)
- ),
- [tors, wallet?.publicKey]
- )
+ const walletPk = wallet?.publicKey ?? undefined
+ const enabled = realm !== undefined && walletPk !== undefined
+ const query = useQuery({
+ queryKey: enabled
+ ? tokenOwnerRecordQueryKeys.byRealmXDelegate(
+ connection.current.rpcEndpoint,
+ realm.pubkey,
+ walletPk
+ )
+ : undefined,
+ queryFn: async () => {
+ if (!enabled) throw new Error()
- return delagatingTors
+ const realmFilter = pubkeyFilter(1, realm.pubkey)
+ const hasDelegateFilter = booleanFilter(
+ 1 + 32 + 32 + 32 + 8 + 4 + 4 + 1 + 1 + 6,
+ true
+ )
+ const delegatedToUserFilter = pubkeyFilter(
+ 1 + 32 + 32 + 32 + 8 + 4 + 4 + 1 + 1 + 6 + 1,
+ walletPk
+ )
+ if (!realmFilter || !delegatedToUserFilter) throw new Error() // unclear why this would ever happen, probably it just cannot
+
+ const results = await getGovernanceAccounts(
+ connection.current,
+ realm.owner,
+ TokenOwnerRecord,
+ [realmFilter, hasDelegateFilter, delegatedToUserFilter]
+ )
+
+ // This may or may not be resource intensive for big DAOs, and is not too useful
+ /*
+ results.forEach((x) => {
+ queryClient.setQueryData(
+ tokenOwnerRecordQueryKeys.byPubkey(connection.cluster, x.pubkey),
+ { found: true, result: x }
+ )
+ }) */
+
+ return results
+ },
+ enabled,
+ })
+
+ return query
}
const queryFn = (connection: Connection, pubkey: PublicKey) =>
diff --git a/hooks/selectedRealm/useSelectedRealmPubkey.ts b/hooks/selectedRealm/useSelectedRealmPubkey.ts
index c6d2edb191..e4fc3301ed 100644
--- a/hooks/selectedRealm/useSelectedRealmPubkey.ts
+++ b/hooks/selectedRealm/useSelectedRealmPubkey.ts
@@ -8,7 +8,13 @@ import MAINNET_REALMS from 'public/realms/mainnet-beta.json'
import { useMemo } from 'react'
const useSelectedRealmPubkey = () => {
- const { symbol, cluster } = useRouter().query
+ const { symbol } = useRouter().query
+
+ return useRealmPubkeyByPkOrSymbol(symbol as string)
+}
+
+export const useRealmPubkeyByPkOrSymbol = (symbol: string | undefined) => {
+ const { cluster } = useRouter().query
const parsed = useMemo(
() => (typeof symbol === 'string' ? tryParsePublicKey(symbol) : undefined),
diff --git a/hooks/useAccountInvestments/staticInvestments.ts b/hooks/useAccountInvestments/staticInvestments.ts
index 7c620067dd..f50325ec9e 100644
--- a/hooks/useAccountInvestments/staticInvestments.ts
+++ b/hooks/useAccountInvestments/staticInvestments.ts
@@ -46,17 +46,17 @@ export const getTokenInvestments = (tokenImg: string) => [
createProposalFcn: () => null,
noProtocol: true,
},
- // {
- // liquidity: 0,
- // protocolSymbol: '',
- // apy: '',
- // protocolName: 'Mango',
- // handledMint: '',
- // handledTokenSymbol: '',
- // handledTokenImgSrc: tokenImg,
- // protocolLogoSrc: 'https://alpha.mango.markets/logos/logo-mark.svg',
- // strategyName: 'Trade',
- // strategyDescription: '',
- // createProposalFcn: () => null,
- // },
+ {
+ liquidity: 0,
+ protocolSymbol: '',
+ apy: '',
+ protocolName: 'Mango',
+ handledMint: '',
+ handledTokenSymbol: '',
+ handledTokenImgSrc: tokenImg,
+ protocolLogoSrc: 'https://mango.markets/logos/logo-mark.svg',
+ strategyName: 'Trade',
+ strategyDescription: '',
+ createProposalFcn: () => null,
+ },
]
diff --git a/hooks/useGovernanceAssets.ts b/hooks/useGovernanceAssets.ts
index 08a8052c97..8ad15b3352 100644
--- a/hooks/useGovernanceAssets.ts
+++ b/hooks/useGovernanceAssets.ts
@@ -337,6 +337,21 @@ export default function useGovernanceAssets() {
name: 'Split Stake Validator',
packageId: PackageEnum.Common,
},
+ [Instructions.DaoVote]: {
+ name: 'Vote in another DAO',
+ isVisible: canUseTransferInstruction,
+ packageId: PackageEnum.Common,
+ },
+ [Instructions.DualFinanceDelegateWithdraw]: {
+ name: 'Withdraw Vote Deposit',
+ isVisible: canUseTransferInstruction,
+ packageId: PackageEnum.Common,
+ },
+ [Instructions.DualFinanceVoteDeposit]: {
+ name: 'Join a VSR DAO',
+ isVisible: canUseTransferInstruction,
+ packageId: PackageEnum.Common,
+ },
/*
██████ ██ ██ █████ ██ ███████ ██ ███ ██ █████ ███ ██ ██████ ███████
██ ██ ██ ██ ██ ██ ██ ██ ██ ████ ██ ██ ██ ████ ██ ██ ██
@@ -390,21 +405,6 @@ export default function useGovernanceAssets() {
isVisible: canUseTransferInstruction,
packageId: PackageEnum.Dual,
},
- [Instructions.DualFinanceDelegateWithdraw]: {
- name: 'Withdraw Vote Deposit',
- isVisible: canUseTransferInstruction,
- packageId: PackageEnum.Dual,
- },
- [Instructions.DualFinanceVoteDeposit]: {
- name: 'Vote Deposit',
- isVisible: canUseTransferInstruction,
- packageId: PackageEnum.Dual,
- },
- [Instructions.DualFinanceVote]: {
- name: 'Vote',
- isVisible: canUseTransferInstruction,
- packageId: PackageEnum.Dual,
- },
/*
███████ ██████ ██████ ███████ ███████ ██ ██████ ██ ██ ████████
@@ -515,11 +515,21 @@ export default function useGovernanceAssets() {
packageId: PackageEnum.MangoMarketV4,
isVisible: canUseAnyInstruction,
},
+ [Instructions.MangoV4PerpCreateV23]: {
+ name: 'Create Perp v23',
+ packageId: PackageEnum.MangoMarketV4,
+ isVisible: canUseAnyInstruction,
+ },
[Instructions.MangoV4PerpEdit]: {
name: 'Edit Perp',
packageId: PackageEnum.MangoMarketV4,
isVisible: canUseAnyInstruction,
},
+ [Instructions.MangoV4PerpEditV23]: {
+ name: 'Edit Perp v23',
+ packageId: PackageEnum.MangoMarketV4,
+ isVisible: canUseAnyInstruction,
+ },
[Instructions.MangoV4OpenBookRegisterMarket]: {
name: 'Register Openbook Market',
packageId: PackageEnum.MangoMarketV4,
@@ -530,11 +540,21 @@ export default function useGovernanceAssets() {
packageId: PackageEnum.MangoMarketV4,
isVisible: canUseAnyInstruction,
},
+ [Instructions.MangoV4TokenEditV23]: {
+ name: 'Edit Token v23',
+ packageId: PackageEnum.MangoMarketV4,
+ isVisible: canUseAnyInstruction,
+ },
[Instructions.MangoV4TokenRegister]: {
name: 'Register Token',
packageId: PackageEnum.MangoMarketV4,
isVisible: canUseAnyInstruction,
},
+ [Instructions.MangoV4TokenRegisterV23]: {
+ name: 'Register Token v23',
+ packageId: PackageEnum.MangoMarketV4,
+ isVisible: canUseAnyInstruction,
+ },
[Instructions.MangoV4TokenRegisterTrustless]: {
name: 'Register Trustless Token',
packageId: PackageEnum.MangoMarketV4,
@@ -545,6 +565,11 @@ export default function useGovernanceAssets() {
packageId: PackageEnum.MangoMarketV4,
isVisible: canUseAnyInstruction,
},
+ [Instructions.MangoV4GroupEditV23]: {
+ name: 'Edit Group v23',
+ packageId: PackageEnum.MangoMarketV4,
+ isVisible: canUseAnyInstruction,
+ },
[Instructions.MangoV4AdminWithdrawTokenFees]: {
name: 'Withdraw Token Fees',
packageId: PackageEnum.MangoMarketV4,
@@ -565,6 +590,11 @@ export default function useGovernanceAssets() {
packageId: PackageEnum.MangoMarketV4,
isVisible: canUseAnyInstruction,
},
+ [Instructions.MangoV4IxGateSetV23]: {
+ name: 'Enable/Disable individual instructions in Group v23',
+ packageId: PackageEnum.MangoMarketV4,
+ isVisible: canUseAnyInstruction,
+ },
[Instructions.MangoV4StubOracleCreate]: {
name: 'Create Stub Oracle',
packageId: PackageEnum.MangoMarketV4,
diff --git a/hooks/useMangoV4.tsx b/hooks/useMangoV4.tsx
index 9f2cbf3c91..4bb5f06bbc 100644
--- a/hooks/useMangoV4.tsx
+++ b/hooks/useMangoV4.tsx
@@ -11,7 +11,7 @@ import { useEffect, useState } from 'react'
import useWalletOnePointOh from './useWalletOnePointOh'
import useLegacyConnectionContext from './useLegacyConnectionContext'
-export default function UseMangoV4() {
+export default function UseMangoV4(programId?: PublicKey, group?: PublicKey) {
const connection = useLegacyConnectionContext()
const cluster = connection.cluster
const wallet = useWalletOnePointOh()
@@ -24,7 +24,13 @@ export default function UseMangoV4() {
'78b8f4cGCwmZ9ysPFMWLaLTkkaYnUjwMJYStWe5RTSSX'
)
const clientCluster = cluster === 'devnet' ? 'devnet' : 'mainnet-beta'
- const GROUP = cluster === 'devnet' ? DEVNET_GROUP : MAINNET_GROUP
+ const GROUP = group
+ ? group
+ : cluster === 'devnet'
+ ? DEVNET_GROUP
+ : MAINNET_GROUP
+
+ const program = programId ? programId : MANGO_V4_ID[clientCluster]
const [mangoClient, setMangoClient] = useState(null)
const [mangoGroup, setMangoGroup] = useState(null)
const getClient = async (
@@ -41,7 +47,7 @@ export default function UseMangoV4() {
const client = await MangoClient.connect(
adminProvider,
clientCluster,
- MANGO_V4_ID[clientCluster]
+ program
)
return client
@@ -54,11 +60,16 @@ export default function UseMangoV4() {
setMangoClient(client)
setMangoGroup(group)
}
- if (wallet?.publicKey && connection) {
+ if (wallet && connection) {
console.log('SET NEW CLIENT')
handleSetClient()
}
- }, [connection.cluster, wallet?.publicKey?.toBase58()])
+ }, [
+ connection.cluster,
+ wallet?.publicKey?.toBase58(),
+ GROUP.toBase58(),
+ program.toBase58(),
+ ])
const docs = mangoClient?.program.idl.accounts
.flatMap((x) => x.type.fields as any)
@@ -86,3 +97,14 @@ export default function UseMangoV4() {
getAdditionalLabelInfo,
}
}
+
+export const MANGO_BOOST_PROGRAM_ID = new PublicKey(
+ 'zF2vSz6V9g1YHGmfrzsY497NJzbRr84QUrPry4bLQ25'
+)
+export const BOOST_MAINNET_GROUP = new PublicKey(
+ 'AKeMSYiJekyKfwCc3CUfVNDVAiqk9FfbQVMY3G7RUZUf'
+)
+
+export const MANGO_V4_MAINNET_GROUP = new PublicKey(
+ '78b8f4cGCwmZ9ysPFMWLaLTkkaYnUjwMJYStWe5RTSSX'
+)
diff --git a/hooks/useMangoV4V23.tsx b/hooks/useMangoV4V23.tsx
new file mode 100644
index 0000000000..52c5634660
--- /dev/null
+++ b/hooks/useMangoV4V23.tsx
@@ -0,0 +1,113 @@
+import { AnchorProvider } from '@coral-xyz/anchor'
+import { PublicKey } from '@solana/web3.js'
+import { ConnectionContext } from '@utils/connection'
+import { WalletSigner } from '@solana/spl-governance'
+import {
+ Group,
+ MangoClient,
+ MANGO_V4_ID,
+} from '@blockworks-foundation/mango-v4-rc'
+import { useEffect, useState } from 'react'
+import useWalletOnePointOh from './useWalletOnePointOh'
+import useLegacyConnectionContext from './useLegacyConnectionContext'
+
+export default function UseMangoV4V23(
+ programId?: PublicKey,
+ group?: PublicKey
+) {
+ const connection = useLegacyConnectionContext()
+ const cluster = connection.cluster
+ const wallet = useWalletOnePointOh()
+ const GROUP_NUM = 0
+ const ADMIN_PK = new PublicKey('BJFYN2ZbcxRSTFGCAVkUEn4aJF99xaPFuyQj2rq5pFpo')
+ const DEVNET_GROUP = new PublicKey(
+ 'Bpk8VzppSEkygd4KgXSgVzgVHib4EArhbDzyRpiS4yaf'
+ )
+ const MAINNET_GROUP = new PublicKey(
+ '78b8f4cGCwmZ9ysPFMWLaLTkkaYnUjwMJYStWe5RTSSX'
+ )
+ const clientCluster = cluster === 'devnet' ? 'devnet' : 'mainnet-beta'
+ const GROUP = group
+ ? group
+ : cluster === 'devnet'
+ ? DEVNET_GROUP
+ : MAINNET_GROUP
+
+ const program = programId ? programId : MANGO_V4_ID[clientCluster]
+ const [mangoClient, setMangoClient] = useState(null)
+ const [mangoGroup, setMangoGroup] = useState(null)
+ const getClient = async (
+ connection: ConnectionContext,
+ wallet: WalletSigner
+ ) => {
+ const options = AnchorProvider.defaultOptions()
+ const adminProvider = new AnchorProvider(
+ connection.current,
+ wallet as any,
+ options
+ )
+
+ const client = await MangoClient.connect(
+ adminProvider,
+ clientCluster,
+ program
+ )
+
+ return client
+ }
+
+ useEffect(() => {
+ const handleSetClient = async () => {
+ const client = await getClient(connection, wallet!)
+ const group = await client.getGroup(GROUP)
+ setMangoClient(client)
+ setMangoGroup(group)
+ }
+ if (wallet && connection) {
+ console.log('SET NEW CLIENT')
+ handleSetClient()
+ }
+ }, [
+ connection.cluster,
+ wallet?.publicKey?.toBase58(),
+ GROUP.toBase58(),
+ program.toBase58(),
+ ])
+
+ const docs = mangoClient?.program.idl.accounts
+ .flatMap((x) => x.type.fields as any)
+ .filter((x) => x)
+ .filter((x) => (x as any).docs?.length)
+ .map((x) => ({ ...x, docs: x.docs.join(' ') }))
+
+ const getAdditionalLabelInfo = (name: string) => {
+ const val = docs?.find((x) => x.name === name)
+
+ if (val) {
+ return `${val.docs}`
+ } else {
+ return ''
+ }
+ }
+
+ return {
+ ADMIN_PK,
+ GROUP_NUM,
+ GROUP,
+ getClient,
+ mangoClient,
+ mangoGroup,
+ getAdditionalLabelInfo,
+ }
+}
+
+export const MANGO_BOOST_PROGRAM_ID = new PublicKey(
+ 'zF2vSz6V9g1YHGmfrzsY497NJzbRr84QUrPry4bLQ25'
+)
+export const BOOST_MAINNET_GROUP = new PublicKey(
+ 'AKeMSYiJekyKfwCc3CUfVNDVAiqk9FfbQVMY3G7RUZUf'
+)
+
+export const MANGO_V4_MAINNET_GROUP = new PublicKey(
+ '78b8f4cGCwmZ9ysPFMWLaLTkkaYnUjwMJYStWe5RTSSX'
+)
diff --git a/hooks/useProposalVotes.tsx b/hooks/useProposalVotes.tsx
index 5113b42bd9..390b5f7ca1 100644
--- a/hooks/useProposalVotes.tsx
+++ b/hooks/useProposalVotes.tsx
@@ -10,21 +10,25 @@ import {
useRealmCouncilMintInfoQuery,
} from './queries/mintInfo'
import { useGovernanceByPubkeyQuery } from './queries/governance'
+import usePythScalingFactor from './PythNetwork/useScalingFactor'
// TODO support council plugins
export default function useProposalVotes(proposal?: Proposal) {
+
const realm = useRealmQuery().data?.result
const mint = useRealmCommunityMintInfoQuery().data?.result
const councilMint = useRealmCouncilMintInfoQuery().data?.result
const maxVoteRecord = useMaxVoteRecord()
const governance = useGovernanceByPubkeyQuery(proposal?.governance).data
?.result?.account
+ // This is always undefined except for Pyth
+ const pythScalingFactor: number | undefined = usePythScalingFactor();
const programVersion = useProgramVersion()
const proposalMint =
proposal?.governingTokenMint.toBase58() ===
- realm?.account.communityMint.toBase58()
+ realm?.account.communityMint.toBase58()
? mint
: councilMint
// TODO: optimize using memo
@@ -52,8 +56,8 @@ export default function useProposalVotes(proposal?: Proposal) {
? governance.config.communityVoteThreshold.value
: 0
: programVersion > 2
- ? governance.config.councilVoteThreshold.value || 0
- : governance.config.communityVoteThreshold.value || 0
+ ? governance.config.councilVoteThreshold.value || 0
+ : governance.config.communityVoteThreshold.value || 0
if (voteThresholdPct === undefined)
throw new Error(
@@ -100,12 +104,12 @@ export default function useProposalVotes(proposal?: Proposal) {
voteThresholdPct,
yesVotePct,
yesVoteProgress,
- yesVoteCount,
- noVoteCount,
+ yesVoteCount: Math.floor(yesVoteCount * (pythScalingFactor || 1)),
+ noVoteCount: Math.floor(noVoteCount * (pythScalingFactor || 1)),
relativeYesVotes,
relativeNoVotes,
minimumYesVotes,
- yesVotesRequired,
+ yesVotesRequired: yesVotesRequired * (pythScalingFactor || 1),
}
// @asktree: you may be asking yourself, "is this different from the more succinct way to write this?"
@@ -166,11 +170,11 @@ export default function useProposalVotes(proposal?: Proposal) {
const vetoMaxVoteWeight = isPluginCommunityVeto
? maxVoteRecord.account.maxVoterWeight
: getProposalMaxVoteWeight(
- realm.account,
- proposal,
- vetoMintInfo,
- vetoMintPk
- )
+ realm.account,
+ proposal,
+ vetoMintInfo,
+ vetoMintPk
+ )
const vetoVoteProgress = calculatePct(
proposal.vetoVoteWeight,
diff --git a/hooks/useTreasuryInfo/getDomains.ts b/hooks/useTreasuryInfo/getDomains.ts
index 3d3133ed64..06be01ee72 100644
--- a/hooks/useTreasuryInfo/getDomains.ts
+++ b/hooks/useTreasuryInfo/getDomains.ts
@@ -10,19 +10,23 @@ const getAccountDomains = async (
account: AssetAccount,
connection: Connection
): Promise => {
- const domains = await getAllDomains(connection, account.pubkey)
+ try {
+ const domains = await getAllDomains(connection, account.pubkey)
- if (!domains.length) {
- return []
- }
+ if (!domains.length) {
+ return []
+ }
- const reverse = await performReverseLookupBatch(connection, domains)
+ const reverse = await performReverseLookupBatch(connection, domains)
- return domains.map((domain, index) => ({
- name: reverse[index],
- address: domain.toBase58(),
- owner: account.pubkey.toBase58(),
- }))
+ return domains.map((domain, index) => ({
+ name: reverse[index],
+ address: domain.toBase58(),
+ owner: account.pubkey.toBase58(),
+ }))
+ } catch (e) {
+ return []
+ }
}
export const getDomains = async (
diff --git a/hooks/useVotingTokenOwnerRecords.ts b/hooks/useVotingTokenOwnerRecords.ts
index d5712f1979..891b07e8ad 100644
--- a/hooks/useVotingTokenOwnerRecords.ts
+++ b/hooks/useVotingTokenOwnerRecords.ts
@@ -9,7 +9,7 @@ import { getTokenOwnerRecordAddress } from '@solana/spl-governance'
* Namely, this would be the user + any delegates that are enabled (by default, they all are)
*/
const useVotingTokenOwnerRecords = () => {
- const delegated = useTokenOwnerRecordsDelegatedToUser()
+ const { data: delegated } = useTokenOwnerRecordsDelegatedToUser()
const realm = useRealmQuery().data?.result
const wallet = useWalletOnePointOh()
diff --git a/hooks/useVsrMode.ts b/hooks/useVsrMode.ts
index 39005bf032..7134513c48 100644
--- a/hooks/useVsrMode.ts
+++ b/hooks/useVsrMode.ts
@@ -1,8 +1,8 @@
import { useMemo } from 'react'
-import { HELIUM_VSR_PLUGINS_PKS, VSR_PLUGIN_PKS } from '../constants/plugins'
+import { HELIUM_VSR_PLUGINS_PKS, PYTH_PLUGIN_PK, VSR_PLUGIN_PKS } from '../constants/plugins'
import { useRealmConfigQuery } from './queries/realmConfig'
-export const useVsrMode = (): undefined | 'default' | 'helium' => {
+export const useVsrMode = (): undefined | 'default' | 'helium' | 'pyth' => {
const config = useRealmConfigQuery().data?.result
const mode = useMemo(() => {
const currentPluginPk =
@@ -11,6 +11,7 @@ export const useVsrMode = (): undefined | 'default' | 'helium' => {
if (VSR_PLUGIN_PKS.includes(currentPluginPk?.toBase58())) return 'default'
if (HELIUM_VSR_PLUGINS_PKS.includes(currentPluginPk?.toBase58()))
return 'helium'
+ if (PYTH_PLUGIN_PK.includes(currentPluginPk?.toBase58())) return 'pyth'
}, [config?.account?.communityTokenConfig])
return mode
diff --git a/hub/components/EditRealmConfig/CommunityStructure/index.tsx b/hub/components/EditRealmConfig/CommunityStructure/index.tsx
index d1395f9328..b110bed608 100644
--- a/hub/components/EditRealmConfig/CommunityStructure/index.tsx
+++ b/hub/components/EditRealmConfig/CommunityStructure/index.tsx
@@ -25,11 +25,13 @@ interface Props
nftCollection?: PublicKey;
nftCollectionSize: number;
nftCollectionWeight: BN;
+ civicPassType: Config['civicPassType'];
}> {
currentConfigAccount: Config['configAccount'];
currentNftCollection?: PublicKey;
currentNftCollectionSize: number;
currentNftCollectionWeight: BN;
+ currentCivicPassType: Config['civicPassType'];
communityMint: Config['communityMint'];
className?: string;
}
@@ -43,6 +45,7 @@ export function CommunityStructure(props: Props) {
nftCollection: props.currentNftCollection,
nftCollectionSize: props.currentNftCollectionSize,
nftCollectionWeight: props.currentNftCollectionWeight,
+ civicPassType: props.currentCivicPassType,
};
const votingStructure = {
@@ -52,6 +55,7 @@ export function CommunityStructure(props: Props) {
nftCollection: props.nftCollection,
nftCollectionSize: props.nftCollectionSize,
nftCollectionWeight: props.nftCollectionWeight,
+ civicPassType: props.civicPassType,
};
const minTokensToManage = new BigNumber(
@@ -211,6 +215,7 @@ export function CommunityStructure(props: Props) {
nftCollection,
nftCollectionSize,
nftCollectionWeight,
+ civicPassType,
}) => {
const newConfig = produce(
{ ...props.configAccount },
@@ -246,6 +251,13 @@ export function CommunityStructure(props: Props) {
) {
props.onNftCollectionWeightChange?.(nftCollectionWeight);
}
+
+ if (
+ typeof civicPassType !== 'undefined' &&
+ !props.civicPassType?.equals(civicPassType)
+ ) {
+ props.onCivicPassTypeChange?.(civicPassType);
+ }
}, 0);
}}
/>
diff --git a/hub/components/EditRealmConfig/Form/index.tsx b/hub/components/EditRealmConfig/Form/index.tsx
index bd008aae9a..5f13d3df2a 100644
--- a/hub/components/EditRealmConfig/Form/index.tsx
+++ b/hub/components/EditRealmConfig/Form/index.tsx
@@ -67,9 +67,11 @@ export function Form(props: Props) {
currentNftCollection={props.currentConfig.nftCollection}
currentNftCollectionSize={props.currentConfig.nftCollectionSize}
currentNftCollectionWeight={props.currentConfig.nftCollectionWeight}
+ currentCivicPassType={props.currentConfig.civicPassType}
nftCollection={props.config.nftCollection}
nftCollectionSize={props.config.nftCollectionSize}
nftCollectionWeight={props.config.nftCollectionWeight}
+ civicPassType={props.config.civicPassType}
onConfigChange={(config) => {
const newConfig = produce(props.config, (data) => {
data.config = config;
@@ -103,6 +105,13 @@ export function Form(props: Props) {
data.nftCollectionWeight = nftCollectionWeight;
});
+ props.onConfigChange?.(newConfig);
+ }}
+ onCivicPassTypeChange={(civicPassType) => {
+ const newConfig = produce(props.config, (data) => {
+ data.civicPassType = civicPassType;
+ });
+
props.onConfigChange?.(newConfig);
}}
/>
diff --git a/hub/components/EditRealmConfig/UpdatesList/index.tsx b/hub/components/EditRealmConfig/UpdatesList/index.tsx
index 489e4eb219..f6e7d3e723 100644
--- a/hub/components/EditRealmConfig/UpdatesList/index.tsx
+++ b/hub/components/EditRealmConfig/UpdatesList/index.tsx
@@ -10,6 +10,7 @@ import { PublicKey } from '@solana/web3.js';
import { BigNumber } from 'bignumber.js';
import BN from 'bn.js';
+import { availablePasses } from '../../../../GatewayPlugin/config';
import { Config } from '../fetchConfig';
import { getLabel } from '../TokenTypeSelector';
import {
@@ -45,6 +46,7 @@ export function buildUpdates(config: Config) {
nftCollection: config.nftCollection,
nftCollectionSize: config.nftCollectionSize,
nftCollectionWeight: config.nftCollectionWeight,
+ civicPassType: config.civicPassType,
};
}
@@ -81,6 +83,16 @@ export function diff(
return diffs;
}
+const civicPassTypeLabel = (civicPassType: PublicKey | undefined): string => {
+ if (!civicPassType) return 'None';
+ const foundPass = availablePasses.find(
+ (pass) => pass.value === civicPassType?.toBase58(),
+ );
+
+ if (!foundPass) return 'Other (' + abbreviateAddress(civicPassType) + ')';
+ return foundPass.name;
+};
+
function votingStructureText(
votingPluginDiff: [PublicKey | undefined, PublicKey | undefined],
maxVotingPluginDiff: [PublicKey | undefined, PublicKey | undefined],
@@ -156,7 +168,8 @@ export function UpdatesList(props: Props) {
'communityMaxVotingPlugin' in updates ||
'nftCollection' in updates ||
'nftCollectionSize' in updates ||
- 'nftCollectionWeight' in updates;
+ 'nftCollectionWeight' in updates ||
+ 'civicPassType' in updates;
const hasCouncilUpdates =
'councilTokenType' in updates ||
@@ -420,6 +433,19 @@ export function UpdatesList(props: Props) {
}
/>
)}
+ {'civicPassType' in updates && (
+
+ {civicPassTypeLabel(updates.civicPassType[1])}
+
+ {civicPassTypeLabel(updates.civicPassType[0])}
+
+
+ }
+ />
+ )}
)}
diff --git a/hub/components/EditRealmConfig/VotingStructureSelector/CivicConfigurator.tsx b/hub/components/EditRealmConfig/VotingStructureSelector/CivicConfigurator.tsx
new file mode 100644
index 0000000000..83a6fdaef3
--- /dev/null
+++ b/hub/components/EditRealmConfig/VotingStructureSelector/CivicConfigurator.tsx
@@ -0,0 +1,219 @@
+import ChevronDownIcon from '@carbon/icons-react/lib/ChevronDown';
+import * as DropdownMenu from '@radix-ui/react-dropdown-menu';
+
+import { PublicKey } from '@solana/web3.js';
+import React, { FC, useRef, useState } from 'react';
+
+import { availablePasses } from '../../../../GatewayPlugin/config';
+import Input from '@components/inputs/Input';
+import cx from '@hub/lib/cx';
+
+const itemStyles = cx(
+ 'border',
+ 'cursor-pointer',
+ 'gap-x-4',
+ 'grid-cols-[150px,1fr,20px]',
+ 'grid',
+ 'h-14',
+ 'items-center',
+ 'px-4',
+ 'w-full',
+ 'rounded-md',
+ 'text-left',
+ 'transition-colors',
+ 'dark:bg-neutral-800',
+ 'dark:border-neutral-700',
+ 'dark:hover:bg-neutral-700',
+);
+
+const labelStyles = cx('font-700', 'dark:text-neutral-50', 'w-full');
+const descriptionStyles = cx('dark:text-neutral-400 text-sm');
+const iconStyles = cx('fill-neutral-500', 'h-5', 'transition-transform', 'w-4');
+
+// Infer the types from the available passes, giving type safety on the `other` and `default` pass types
+type ArrayElement<
+ ArrayType extends readonly unknown[]
+> = ArrayType extends readonly (infer ElementType)[] ? ElementType : never;
+type CivicPass = ArrayElement
;
+
+const isOther = (pass: CivicPass | undefined): boolean =>
+ pass?.name === 'Other';
+const other = availablePasses.find(isOther) as CivicPass;
+
+// if nothing is selected, Uniqueness is most likely what the user wants
+const defaultPass = availablePasses.find(
+ (pass) => pass.name === 'Uniqueness',
+) as CivicPass;
+
+// If Other is selected, allow the user to enter a custom pass address here.
+const ManualPassEntry: FC<{
+ manualPassType?: PublicKey;
+ onChange: (newManualPassType?: PublicKey) => void;
+}> = ({ manualPassType, onChange }) => {
+ const [error, setError] = useState();
+ const [inputValue, setInputValue] = useState(
+ manualPassType?.toBase58() || '',
+ );
+
+ return (
+
+
+
+
+
+
{
+ const value = evt.target.value;
+ setInputValue(value);
+ try {
+ const pk = new PublicKey(value);
+ onChange(pk);
+ setError(undefined);
+ } catch {
+ setError('Invalid address');
+ }
+ }}
+ error={error}
+ />
+
+
+
+ );
+};
+
+// A dropdown of all the available Civic Passes
+const CivicPassDropdown: FC<{
+ className?: string;
+ previousSelected?: PublicKey;
+ onPassTypeChange(value: PublicKey | undefined): void;
+}> = (props) => {
+ const [open, setOpen] = useState(false);
+ const trigger = useRef(null);
+ const [selectedPass, setSelectedPass] = useState(
+ !!props.previousSelected
+ ? availablePasses.find(
+ (pass) => pass.value === props.previousSelected?.toBase58(),
+ ) ?? other
+ : defaultPass,
+ );
+
+ return (
+
+
+
+
+ {selectedPass?.name || 'Select a Civic Pass'}
+
+
+ {selectedPass?.description || ''}
+
+
+
+
+
+ {availablePasses.map((config, i) => (
+ {
+ setSelectedPass(config);
+ props.onPassTypeChange(
+ config?.value ? new PublicKey(config.value) : undefined,
+ );
+ }}
+ >
+ {config.name}
+ {config.description}
+
+ ))}
+
+
+
+ {isOther(selectedPass) && (
+ {
+ setSelectedPass(other);
+ props.onPassTypeChange(manualPassType);
+ }}
+ manualPassType={
+ props.previousSelected && selectedPass !== other
+ ? props.previousSelected
+ : undefined
+ }
+ />
+ )}
+
+ );
+};
+
+interface Props {
+ className?: string;
+ currentPassType?: PublicKey;
+ onPassTypeChange(value: PublicKey | undefined): void;
+}
+
+export function CivicConfigurator(props: Props) {
+ return (
+
+
+
+
+
+ What type of verification?
+
+
+
+
+
+ );
+}
diff --git a/hub/components/EditRealmConfig/VotingStructureSelector/index.tsx b/hub/components/EditRealmConfig/VotingStructureSelector/index.tsx
index a8706d676d..3b1ecd2a84 100644
--- a/hub/components/EditRealmConfig/VotingStructureSelector/index.tsx
+++ b/hub/components/EditRealmConfig/VotingStructureSelector/index.tsx
@@ -10,6 +10,7 @@ import cx from '@hub/lib/cx';
import { DEFAULT_NFT_VOTER_PLUGIN } from '@tools/constants';
+import { CivicConfigurator } from './CivicConfigurator';
import { Custom } from './Custom';
import { NFT } from './NFT';
@@ -51,33 +52,24 @@ const labelStyles = cx('font-700', 'dark:text-neutral-50');
const descriptionStyles = cx('dark:text-neutral-400');
const iconStyles = cx('fill-neutral-500', 'h-5', 'transition-transform', 'w-4');
+type VotingStructure = {
+ votingProgramId?: PublicKey;
+ maxVotingProgramId?: PublicKey;
+ nftCollection?: PublicKey;
+ nftCollectionSize?: number;
+ nftCollectionWeight?: BN;
+ civicPassType?: PublicKey;
+};
+
interface Props {
allowNFT?: boolean;
allowCivic?: boolean;
allowVSR?: boolean;
className?: string;
communityMint: Config['communityMint'];
- currentStructure: {
- votingProgramId?: PublicKey;
- maxVotingProgramId?: PublicKey;
- nftCollection?: PublicKey;
- nftCollectionSize?: number;
- nftCollectionWeight?: BN;
- };
- structure: {
- votingProgramId?: PublicKey;
- maxVotingProgramId?: PublicKey;
- nftCollection?: PublicKey;
- nftCollectionSize?: number;
- nftCollectionWeight?: BN;
- };
- onChange?(value: {
- votingProgramId?: PublicKey;
- maxVotingProgramId?: PublicKey;
- nftCollection?: PublicKey;
- nftCollectionSize?: number;
- nftCollectionWeight?: BN;
- }): void;
+ currentStructure: VotingStructure;
+ structure: VotingStructure;
+ onChange?(value: VotingStructure): void;
}
function areConfigsEqual(a: Props['structure'], b: Props['structure']) {
@@ -258,6 +250,18 @@ export function VotingStructureSelector(props: Props) {
}}
/>
)}
+ {isCivicConfig(props.structure) && (
+ {
+ const newConfig = produce({ ...props.structure }, (data) => {
+ data.civicPassType = value ?? undefined;
+ });
+ props.onChange?.(newConfig);
+ }}
+ />
+ )}
=7.23.2",
"port-sdk/@saberhq/token-utils": "1.12.53",
- "@solana/web3.js": "1.73.3",
"react": "18.2.0",
"@solana/spl-token-registry": "0.2.3775",
"@solana/buffer-layout": "4.0.0",
@@ -237,7 +240,8 @@
"@bundlr-network/client": "0.7.15",
"@carbon/icons-react": "11.7.0",
"@cardinal/namespaces-components": "2.5.5",
- "crypto-js": ">=4.1.1"
+ "crypto-js": ">=4.1.1",
+ "@solana/web3.js": "1.78.2"
},
"browser": {
"child_process": false
@@ -268,5 +272,8 @@
"draft-js>fbjs>core-js": false,
"@switchboard-xyz/solana.js>@switchboard-xyz/common>protobufjs": false
}
+ },
+ "volta": {
+ "node": "18.19.0"
}
}
diff --git a/pages/_error.js b/pages/_error.js
index 1068f15f10..1254ef1be4 100644
--- a/pages/_error.js
+++ b/pages/_error.js
@@ -23,8 +23,8 @@ MyError.getInitialProps = async (context) => {
// getInitialProps has run
errorInitialProps.hasGetInitialPropsRun = true
- // Returning early because we don't want to log 404 errors to Sentry.
- if (res?.statusCode === 404) {
+ // Returning early because we don't want to log 404 or 403 errors to Sentry.
+ if (res?.statusCode === 404 || res?.statusCode === 403) {
return errorInitialProps
}
diff --git a/pages/dao/[symbol]/account/DelegatorOptions.tsx b/pages/dao/[symbol]/account/DelegatorOptions.tsx
index 42fce22055..c31e3af33c 100644
--- a/pages/dao/[symbol]/account/DelegatorOptions.tsx
+++ b/pages/dao/[symbol]/account/DelegatorOptions.tsx
@@ -4,7 +4,7 @@ import { useTokenOwnerRecordsDelegatedToUser } from '@hooks/queries/tokenOwnerRe
import DelegatorsList from './DelegatorsList'
const DelegatorOptions = () => {
- const delegatesArray = useTokenOwnerRecordsDelegatedToUser()
+ const { data: delegatesArray } = useTokenOwnerRecordsDelegatedToUser()
return delegatesArray === undefined || delegatesArray.length < 1 ? null : (
diff --git a/pages/dao/[symbol]/account/DelegatorsList.tsx b/pages/dao/[symbol]/account/DelegatorsList.tsx
index b28d1de796..05a3d979ae 100644
--- a/pages/dao/[symbol]/account/DelegatorsList.tsx
+++ b/pages/dao/[symbol]/account/DelegatorsList.tsx
@@ -37,7 +37,7 @@ const DelegatorCheckbox = ({
const DelegatorsList = () => {
const realm = useRealmQuery().data?.result
- const delegatesArray = useTokenOwnerRecordsDelegatedToUser()
+ const { data: delegatesArray } = useTokenOwnerRecordsDelegatedToUser()
// returns array of community tokenOwnerRecords that connected wallet has been delegated
const communityTorsDelegatedToUser = useMemo(
diff --git a/pages/dao/[symbol]/account/me.tsx b/pages/dao/[symbol]/account/me.tsx
index b2bc6786ac..0c75b41d7a 100644
--- a/pages/dao/[symbol]/account/me.tsx
+++ b/pages/dao/[symbol]/account/me.tsx
@@ -11,6 +11,10 @@ const AccountPage: React.FC = () => {
const ownTokenRecord = useUserCommunityTokenOwnerRecord().data?.result
const { data: tokenOwnerRecordPk } = useAddressQuery_CommunityTokenOwner()
+ if (vsrMode === 'pyth') {
+ return
+ }
+
if (
vsrMode &&
(!ownTokenRecord ||
@@ -23,7 +27,6 @@ const AccountPage: React.FC = () => {
)
}
-
return tokenOwnerRecordPk ? (
diff --git a/pages/dao/[symbol]/index.tsx b/pages/dao/[symbol]/index.tsx
index 9d37b739da..7f9c38c00c 100644
--- a/pages/dao/[symbol]/index.tsx
+++ b/pages/dao/[symbol]/index.tsx
@@ -54,6 +54,8 @@ import {
} from '@hooks/queries/proposal'
import queryClient from '@hooks/queries/queryClient'
import { useLegacyVoterWeight } from '@hooks/queries/governancePower'
+import { getFeeEstimate } from '@tools/feeEstimate'
+import { createComputeBudgetIx } from '@blockworks-foundation/mango-v4'
const AccountsCompactWrapper = dynamic(
() => import('@components/TreasuryAccount/AccountsCompactWrapper')
@@ -263,9 +265,10 @@ const REALM = () => {
try {
setIsMultiVoting(true)
- const {
- blockhash: recentBlockhash,
- } = await connection.getLatestBlockhash()
+ const [{ blockhash: recentBlockhash }, fee] = await Promise.all([
+ connection.getLatestBlockhash(),
+ getFeeEstimate(connection),
+ ])
const transactions: Transaction[] = []
for (let i = 0; i < selectedProposals.length; i++) {
@@ -311,8 +314,9 @@ const REALM = () => {
}
const transaction = new Transaction()
- transaction.add(...instructions)
+ transaction.add(...[createComputeBudgetIx(fee), ...instructions])
transaction.recentBlockhash = recentBlockhash
+ transaction.feePayer = wallet.publicKey!
transaction.setSigners(
// fee payed by the wallet owner
wallet.publicKey!
diff --git a/pages/dao/[symbol]/members/Members.tsx b/pages/dao/[symbol]/members/Members.tsx
index ef230c195b..7ae9cadf49 100644
--- a/pages/dao/[symbol]/members/Members.tsx
+++ b/pages/dao/[symbol]/members/Members.tsx
@@ -1,5 +1,5 @@
import useRealm from '@hooks/useRealm'
-import { useEffect, useRef, useState } from 'react'
+import { useEffect, useMemo, useRef, useState } from 'react'
import MemberOverview from '@components/Members/MemberOverview'
import { PlusCircleIcon, SearchIcon, UsersIcon } from '@heroicons/react/outline'
import useGovernanceAssets from '@hooks/useGovernanceAssets'
@@ -15,6 +15,10 @@ import { Member } from '@utils/uiTypes/members'
import PaginationComponent from '@components/Pagination'
import useWalletOnePointOh from '@hooks/useWalletOnePointOh'
import { useMembersQuery } from '@components/Members/useMembers'
+import { useConnection } from '@solana/wallet-adapter-react'
+import useSelectedRealmPubkey from '@hooks/selectedRealm/useSelectedRealmPubkey'
+import { determineVotingPowerType } from '@hooks/queries/governancePower'
+import { useAsync } from 'react-async-hook'
const Members = () => {
const {
@@ -25,7 +29,6 @@ const Members = () => {
const pagination = useRef<{ setPage: (val) => void }>(null)
const membersPerPage = 10
- const { data: activeMembers } = useMembersQuery()
const wallet = useWalletOnePointOh()
const connected = !!wallet?.connected
const {
@@ -38,6 +41,25 @@ const Members = () => {
const [searchString, setSearchString] = useState('')
const [filteredMembers, setFilteredMembers] = useState([])
+ const { connection } = useConnection()
+ const realmPk = useSelectedRealmPubkey()
+ const { data: activeMembersData } = useMembersQuery()
+
+ const { result: kind } = useAsync(async () => {
+ if (realmPk === undefined) return undefined
+ return determineVotingPowerType(connection, realmPk, 'community')
+ }, [connection, realmPk])
+
+ // if this is not vanilla or NFT, this view is used only to show council. filter accordingly.
+ const councilOnly = !(kind === 'vanilla' || kind === 'NFT')
+ const activeMembers = useMemo(
+ () =>
+ councilOnly
+ ? activeMembersData?.filter((x) => x.councilVotes.gtn(0))
+ : activeMembersData,
+ [activeMembersData, councilOnly]
+ )
+
const filterMembers = (v) => {
if (activeMembers !== undefined) {
setSearchString(v)
@@ -98,7 +120,7 @@ const Members = () => {
) : null}
{realmInfo?.displayName}
-
Members
+
{councilOnly ? 'Council ' : ''}Members
diff --git a/pages/dao/[symbol]/members/index.tsx b/pages/dao/[symbol]/members/index.tsx
index 27f1b06c3d..5a84af1007 100644
--- a/pages/dao/[symbol]/members/index.tsx
+++ b/pages/dao/[symbol]/members/index.tsx
@@ -1,18 +1,8 @@
-import { NFT_PLUGINS_PKS } from '@constants/plugins'
import Members from './Members'
-import { useRealmConfigQuery } from '@hooks/queries/realmConfig'
const MembersPage = () => {
- const config = useRealmConfigQuery().data?.result
- const currentPluginPk = config?.account.communityTokenConfig.voterWeightAddin
- const isNftMode =
- (currentPluginPk &&
- NFT_PLUGINS_PKS.includes(currentPluginPk?.toBase58())) ||
- false
return (
- {!config?.account.communityTokenConfig.voterWeightAddin || isNftMode ? (
-
- ) : null}
+
)
}
diff --git a/pages/dao/[symbol]/proposal/[pk]/index.tsx b/pages/dao/[symbol]/proposal/[pk]/index.tsx
index 40f03beca6..df6d65f4b1 100644
--- a/pages/dao/[symbol]/proposal/[pk]/index.tsx
+++ b/pages/dao/[symbol]/proposal/[pk]/index.tsx
@@ -85,7 +85,7 @@ const Proposal = () => {
proposal.account.state === ProposalState.ExecutingWithErrors)
return (
-
+
{proposal ? (
<>
diff --git a/pages/dao/[symbol]/proposal/components/MyProposalsBtn.tsx b/pages/dao/[symbol]/proposal/components/MyProposalsBtn.tsx
index 72af7f0574..590eadaa19 100644
--- a/pages/dao/[symbol]/proposal/components/MyProposalsBtn.tsx
+++ b/pages/dao/[symbol]/proposal/components/MyProposalsBtn.tsx
@@ -51,6 +51,8 @@ import {
useRealmProposalsQuery,
} from '@hooks/queries/proposal'
import queryClient from '@hooks/queries/queryClient'
+import { getFeeEstimate } from '@tools/feeEstimate'
+import { createComputeBudgetIx } from '@blockworks-foundation/mango-v4'
const MyProposalsBn = () => {
const [modalIsOpen, setModalIsOpen] = useState(false)
@@ -163,9 +165,10 @@ const MyProposalsBn = () => {
if (!wallet || !programId || !realm) return
setIsLoading(true)
try {
- const {
- blockhash: recentBlockhash,
- } = await connection.getLatestBlockhash()
+ const [{ blockhash: recentBlockhash }, fee] = await Promise.all([
+ connection.getLatestBlockhash(),
+ getFeeEstimate(connection),
+ ])
const transactions: Transaction[] = []
const instructions: TransactionInstruction[] = []
@@ -180,7 +183,7 @@ const MyProposalsBn = () => {
recentBlockhash,
feePayer: wallet.publicKey!,
})
- transaction.add(...chunk)
+ transaction.add(...[createComputeBudgetIx(fee), ...chunk])
transaction.recentBlockhash = recentBlockhash
transaction.setSigners(
// fee payed by the wallet owner
diff --git a/pages/dao/[symbol]/proposal/components/instructions/DistrubtionProgram/FillVaults.tsx b/pages/dao/[symbol]/proposal/components/instructions/DistrubtionProgram/FillVaults.tsx
index fed05758a5..75642e4f61 100644
--- a/pages/dao/[symbol]/proposal/components/instructions/DistrubtionProgram/FillVaults.tsx
+++ b/pages/dao/[symbol]/proposal/components/instructions/DistrubtionProgram/FillVaults.tsx
@@ -33,7 +33,7 @@ import { parseMintNaturalAmountFromDecimal } from '@tools/sdk/units'
import { validateInstruction } from '@utils/instructionTools'
import useGovernanceNfts from '@components/treasuryV2/WalletList/WalletListItem/AssetList/useGovernanceNfts'
-export const SEASON_PREFIX = 117
+export const SEASON_PREFIX = 119
interface FillVaultsForm {
governedAccount: AssetAccount | null
diff --git a/pages/dao/[symbol]/proposal/components/instructions/Dual/DualGso.tsx b/pages/dao/[symbol]/proposal/components/instructions/Dual/DualGso.tsx
index b944bca69d..8d7aa580b0 100644
--- a/pages/dao/[symbol]/proposal/components/instructions/Dual/DualGso.tsx
+++ b/pages/dao/[symbol]/proposal/components/instructions/Dual/DualGso.tsx
@@ -26,6 +26,7 @@ const DualGso = ({
optionExpirationUnixSeconds: 0,
numTokens: 0,
lotSize: 0,
+ lockupMint: '',
baseTreasury: undefined,
quoteTreasury: undefined,
payer: undefined,
@@ -91,6 +92,18 @@ const DualGso = ({
error={formErrors['soName']}
/>
+
+ handleSetForm({
+ value: evt.target.value,
+ propertyName: 'lockupMint',
+ })
+ }
+ error={formErrors['lockupMint']}
+ />
{
const [form, setForm] = useState({
numTokens: 0,
- realm: 'EGYbpow8V9gt8JFmadFYai4sjfwc7Vc9gazU735hE6u7',
+ realm: '',
delegateToken: undefined,
})
const connection = useLegacyConnectionContext()
const wallet = useWalletOnePointOh()
const shouldBeGoverned = !!(index !== 0 && governance)
const { assetAccounts } = useGovernanceAssets()
- const [governedAccount, setGovernedAccount] = useState<
- ProgramAccount | undefined
- >(undefined)
+
const [formErrors, setFormErrors] = useState({})
const { handleSetInstructions } = useContext(NewProposalContext)
const handleSetForm = ({ propertyName, value }) => {
setFormErrors({})
setForm({ ...form, [propertyName]: value })
}
- function getInstruction(): Promise {
- return getVoteDepositInstruction({
- connection,
- form,
- schema,
- setFormErrors,
- wallet,
- })
- }
- const schema = useMemo(getDualFinanceVoteDepositSchema, [])
+
+ const realmInputParsed = useRealmPubkeyByPkOrSymbol(form.realm)
+
useEffect(() => {
+ const schema = getDualFinanceVoteDepositSchema()
+ function getInstruction(): Promise {
+ return getVoteDepositInstruction({
+ connection,
+ form,
+ schema,
+ setFormErrors,
+ wallet,
+ realmPk: realmInputParsed,
+ })
+ }
handleSetInstructions(
- { governedAccount: governedAccount, getInstruction },
+ { governedAccount: form.delegateToken?.governance, getInstruction },
index
)
- }, [form, governedAccount, handleSetInstructions, index, connection, wallet])
- useEffect(() => {
- handleSetForm({ value: undefined, propertyName: 'mintPk' })
- }, [form.delegateToken])
- useEffect(() => {
- setGovernedAccount(form.delegateToken?.governance)
- }, [form.delegateToken])
+ }, [form, handleSetInstructions, index, connection, wallet, realmInputParsed])
// TODO: Include this in the config instruction which can optionally be done
// if the project doesnt need to change where the tokens get returned to.
@@ -85,7 +82,6 @@ const DualVoteDeposit = ({
label="Realm"
value={form.realm}
type="text"
- disabled={true}
onChange={(evt) =>
handleSetForm({
value: evt.target.value,
diff --git a/pages/dao/[symbol]/proposal/components/instructions/Dual/StakingOption.tsx b/pages/dao/[symbol]/proposal/components/instructions/Dual/StakingOption.tsx
index 6ef9cf33d5..5bb64c82e1 100644
--- a/pages/dao/[symbol]/proposal/components/instructions/Dual/StakingOption.tsx
+++ b/pages/dao/[symbol]/proposal/components/instructions/Dual/StakingOption.tsx
@@ -34,7 +34,7 @@ const StakingOption = ({
const [form, setForm] = useState({
soName: undefined,
optionExpirationUnixSeconds: 0,
- numTokens: 0,
+ numTokens: '0',
lotSize: 1,
baseTreasury: undefined,
quoteTreasury: undefined,
@@ -255,7 +255,7 @@ const StakingOption = ({
{baseMetadata && quoteMetadata && (
<>
- {form.strike / form.lotSize * 10 ** (-quoteMetadata.decimals + baseMetadata.decimals) * (form.numTokens / 10 ** baseMetadata.decimals)}
+ {form.strike / form.lotSize * 10 ** (-quoteMetadata.decimals + baseMetadata.decimals) * (Number(form.numTokens) / 10 ** baseMetadata.decimals)}
=
- {form.numTokens / 10 ** baseMetadata.decimals}
+ {Number(form.numTokens) / 10 ** baseMetadata.decimals}
| null
}) => {
const realm = useRealmQuery().data?.result
- const { realmInfo } = useRealm()
const gatewayClient = useVotePluginsClientStore((s) => s.state.gatewayClient)
const { assetAccounts } = useGovernanceAssets()
const wallet = useWalletOnePointOh()
@@ -63,30 +61,12 @@ const CreateGatewayPluginRegistrar = ({
form!.governedAccount?.governance?.account &&
wallet?.publicKey
) {
- const { registrar } = await getRegistrarPDA(
- realm!.pubkey,
- realm!.account.communityMint,
- gatewayClient!.program.programId
+ const createRegistrarIx = await createCivicRegistrarIx(
+ realm!,
+ wallet.publicKey!,
+ gatewayClient!,
+ chosenGatekeeperNetwork!,
)
-
- const remainingAccounts = form!.predecessor
- ? [{ pubkey: form!.predecessor, isSigner: false, isWritable: false }]
- : []
-
- const createRegistrarIx = await gatewayClient!.program.methods
- .createRegistrar(false)
- .accounts({
- registrar,
- realm: realm!.pubkey,
- governanceProgramId: realmInfo!.programId,
- realmAuthority: realm!.account.authority!,
- governingTokenMint: realm!.account.communityMint!,
- gatekeeperNetwork: chosenGatekeeperNetwork,
- payer: wallet.publicKey!,
- systemProgram: SYSTEM_PROGRAM_ID,
- })
- .remainingAccounts(remainingAccounts)
- .instruction()
serializedInstruction = serializeInstructionToBase64(createRegistrarIx)
}
return {
@@ -146,28 +126,7 @@ const CreateGatewayPluginRegistrar = ({
),
- options: [
- {
- name: 'Bot Resistance',
- value: 'ignREusXmGrscGNUesoU9mxfds9AiYTezUKex2PsZV6',
- },
- {
- name: 'Uniqueness',
- value: 'uniqobk8oGh4XBLMqM68K8M2zNu3CdYX7q5go7whQiv',
- },
- {
- name: 'ID Verification',
- value: 'bni1ewus6aMxTxBi5SAfzEmmXLf8KcVFRmTfproJuKw',
- },
- {
- name: 'ID Verification for DeFi',
- value: 'gatbGF9DvLAw3kWyn1EmH5Nh1Sqp8sTukF7yaQpSc71',
- },
- {
- name: 'Other',
- value: '',
- },
- ],
+ options: availablePasses as any,
},
{
label: 'Other Pass',
diff --git a/pages/dao/[symbol]/proposal/components/instructions/JoinDAO.tsx b/pages/dao/[symbol]/proposal/components/instructions/JoinDAO.tsx
index da950b76d0..af10290233 100644
--- a/pages/dao/[symbol]/proposal/components/instructions/JoinDAO.tsx
+++ b/pages/dao/[symbol]/proposal/components/instructions/JoinDAO.tsx
@@ -162,7 +162,7 @@ const JoinDAO = ({
((routeHasClusterInPath && cluster) || !routeHasClusterInPath)
) {
const realms = getCertifiedRealmInfos(connection)
- setCertifiedRealms(realms.filter((r) => !!r.communityMint))
+ setCertifiedRealms(realms)
} else setCertifiedRealms([])
// 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
}, [connection.current.rpcEndpoint])
@@ -201,7 +201,11 @@ const JoinDAO = ({
error={formErrors['realm']}
>
{certifiedRealms.map((r) => (
-
+
{r.displayName}
))}
diff --git a/pages/dao/[symbol]/proposal/components/instructions/Mango/MangoV4/AltExtend.tsx b/pages/dao/[symbol]/proposal/components/instructions/Mango/MangoV4/AltExtend.tsx
index 57585a84b8..0e7363c81a 100644
--- a/pages/dao/[symbol]/proposal/components/instructions/Mango/MangoV4/AltExtend.tsx
+++ b/pages/dao/[symbol]/proposal/components/instructions/Mango/MangoV4/AltExtend.tsx
@@ -14,6 +14,8 @@ import InstructionForm, { InstructionInput } from '../../FormCreator'
import { InstructionInputType } from '../../inputInstructionType'
import UseMangoV4 from '../../../../../../../../hooks/useMangoV4'
import useWalletOnePointOh from '@hooks/useWalletOnePointOh'
+import ProgramSelector from '@components/Mango/ProgramSelector'
+import useProgramSelector from '@components/Mango/useProgramSelector'
interface AltExtendForm {
governedAccount: AssetAccount | null
@@ -31,7 +33,13 @@ const AltExtend = ({
governance: ProgramAccount | null
}) => {
const wallet = useWalletOnePointOh()
- const { mangoClient, mangoGroup } = UseMangoV4()
+ const programSelectorHook = useProgramSelector()
+
+ const { mangoClient, mangoGroup } = UseMangoV4(
+ programSelectorHook.program?.val,
+ programSelectorHook.program?.group
+ )
+
const { assetAccounts } = useGovernanceAssets()
const solAccounts = assetAccounts.filter(
(x) =>
@@ -148,6 +156,9 @@ const AltExtend = ({
return (
<>
+
{form && (
| null
}) => {
const wallet = useWalletOnePointOh()
- const { mangoClient, mangoGroup } = UseMangoV4()
+ const programSelectorHook = useProgramSelector()
+
+ const { mangoClient, mangoGroup } = UseMangoV4(
+ programSelectorHook.program?.val,
+ programSelectorHook.program?.group
+ )
const { assetAccounts } = useGovernanceAssets()
const solAccounts = assetAccounts.filter(
(x) =>
@@ -135,6 +141,9 @@ const AltSet = ({
return (
<>
+
{form && (
| null
}) => {
const wallet = useWalletOnePointOh()
- const { getAdditionalLabelInfo, mangoClient, mangoGroup } = UseMangoV4()
+ const programSelectorHook = useProgramSelector()
+
+ const { getAdditionalLabelInfo, mangoClient, mangoGroup } = UseMangoV4(
+ programSelectorHook.program?.val,
+ programSelectorHook.program?.group
+ )
const { assetAccounts } = useGovernanceAssets()
const [forcedValues, setForcedValues] = useState([])
const forwarderProgramHelpers = useForwarderProgramHelpers()
@@ -387,7 +394,11 @@ const EditToken = ({
const formTokenPk = form.token?.value.toBase58()
useEffect(() => {
- if (formTokenPk && mangoGroup) {
+ if (
+ formTokenPk &&
+ mangoGroup &&
+ mangoGroup!.banksMapByMint.get(formTokenPk)
+ ) {
const currentToken = mangoGroup!.banksMapByMint.get(formTokenPk)![0]
const groupInsuranceFund = mangoGroup.mintInfosMapByMint.get(formTokenPk)
?.groupInsuranceFund
@@ -827,6 +838,9 @@ const EditToken = ({
return (
<>
+
{form && (
<>
| null
+}) => {
+ const wallet = useWalletOnePointOh()
+ const programSelectorHook = useProgramSelector()
+
+ const { getAdditionalLabelInfo, mangoClient, mangoGroup } = UseMangoV4(
+ programSelectorHook.program?.val,
+ programSelectorHook.program?.group
+ )
+ const { assetAccounts } = useGovernanceAssets()
+ const [forcedValues, setForcedValues] = useState([])
+ const forwarderProgramHelpers = useForwarderProgramHelpers()
+ const solAccounts = assetAccounts.filter(
+ (x) =>
+ x.type === AccountType.SOL &&
+ ((mangoGroup?.admin &&
+ x.extensions.transferAddress?.equals(mangoGroup.admin)) ||
+ (mangoGroup?.securityAdmin &&
+ x.extensions.transferAddress?.equals(mangoGroup.securityAdmin)))
+ )
+ const shouldBeGoverned = !!(index !== 0 && governance)
+ const [tokens, setTokens] = useState([])
+ const [originalFormValues, setOriginalFormValues] = useState({
+ ...defaultFormValues,
+ })
+ const [form, setForm] = useState({
+ ...defaultFormValues,
+ })
+ const [formErrors, setFormErrors] = useState({})
+ const { handleSetInstructions } = useContext(NewProposalContext)
+
+ const validateInstruction = async (): Promise => {
+ const { isValid, validationErrors } = await isFormValid(schema, form)
+ setFormErrors(validationErrors)
+ return isValid
+ }
+ async function getInstruction(): Promise {
+ const isValid = await validateInstruction()
+ let serializedInstruction = ''
+ if (
+ isValid &&
+ form.governedAccount?.governance?.account &&
+ wallet?.publicKey
+ ) {
+ const bank = mangoGroup!.getFirstBankByMint(new PublicKey(form.mintPk))
+ const mintInfo = mangoGroup!.mintInfosMapByTokenIndex.get(
+ bank.tokenIndex
+ )!
+ const values = getChangedValues<
+ Omit & { reduceOnly: number }
+ >(
+ {
+ ...originalFormValues,
+ reduceOnly: originalFormValues.reduceOnly.value,
+ },
+ {
+ ...form,
+ reduceOnly: form.reduceOnly.value,
+ },
+ forcedValues
+ )
+
+ const oracleConfFilter =
+ (form.oracleConfFilter as number | string) === ''
+ ? null
+ : form.oracleConfFilter
+ const maxStalenessSlots =
+ (form.maxStalenessSlots as number | string) === '' ||
+ form.maxStalenessSlots === -1
+ ? null
+ : form.maxStalenessSlots
+
+ const isThereNeedOfSendingOracleConfig =
+ originalFormValues.oracleConfFilter !== oracleConfFilter ||
+ originalFormValues.maxStalenessSlots !== maxStalenessSlots
+ const rateConfigs = {
+ adjustmentFactor: getNullOrTransform(
+ values.adjustmentFactor,
+ null,
+ Number
+ ),
+ util0: getNullOrTransform(values.util0, null, Number),
+ rate0: getNullOrTransform(values.rate0, null, Number),
+ util1: getNullOrTransform(values.util1, null, Number),
+ rate1: getNullOrTransform(values.rate1, null, Number),
+ maxRate: getNullOrTransform(values.maxRate, null, Number),
+ }
+ const isThereNeedOfSendingRateConfigs = Object.values(rateConfigs).filter(
+ (x) => x !== null
+ ).length
+ //Mango instruction call and serialize
+ const ix = await mangoClient!.program.methods
+ .tokenEdit(
+ getNullOrTransform(values.oraclePk, PublicKey),
+ isThereNeedOfSendingOracleConfig
+ ? {
+ confFilter: Number(form.oracleConfFilter),
+ maxStalenessSlots: maxStalenessSlots,
+ }
+ : null,
+ values.groupInsuranceFund!,
+ isThereNeedOfSendingRateConfigs
+ ? {
+ adjustmentFactor: Number(form.adjustmentFactor),
+ util0: Number(form.util0),
+ rate0: Number(form.rate0),
+ util1: Number(form.util1),
+ rate1: Number(form.rate1),
+ maxRate: Number(form.maxRate),
+ }
+ : null,
+ getNullOrTransform(values.loanFeeRate, null, Number),
+ getNullOrTransform(values.loanOriginationFeeRate, null, Number),
+ getNullOrTransform(values.maintAssetWeight, null, Number),
+ getNullOrTransform(values.initAssetWeight, null, Number),
+ getNullOrTransform(values.maintLiabWeight, null, Number),
+ getNullOrTransform(values.initLiabWeight, null, Number),
+ getNullOrTransform(values.liquidationFee, null, Number),
+ getNullOrTransform(
+ values.stablePriceDelayIntervalSeconds,
+ null,
+ Number
+ ),
+ getNullOrTransform(values.stablePriceDelayGrowthLimit, null, Number),
+ getNullOrTransform(values.stablePriceGrowthLimit, null, Number),
+ getNullOrTransform(values.minVaultToDepositsRatio, null, Number),
+ getNullOrTransform(values.netBorrowLimitPerWindowQuote, BN),
+ getNullOrTransform(values.netBorrowLimitWindowSizeTs, BN),
+ getNullOrTransform(values.borrowWeightScaleStartQuote, null, Number),
+ getNullOrTransform(values.depositWeightScaleStartQuote, null, Number),
+ values.resetStablePrice!,
+ values.resetNetBorrowLimit!,
+ getNullOrTransform(values.reduceOnly, null, Number),
+ getNullOrTransform(values.name, null, String),
+ values.forceClose!,
+ getNullOrTransform(
+ values.tokenConditionalSwapTakerFeeRate,
+ null,
+ Number
+ ),
+ getNullOrTransform(
+ values.tokenConditionalSwapMakerFeeRate,
+ null,
+ Number
+ ),
+ getNullOrTransform(values.flashLoanSwapFeeRate, null, Number),
+ getNullOrTransform(values.interestCurveScaling, null, Number),
+ getNullOrTransform(values.interestTargetUtilization, null, Number),
+ getNullOrTransform(values.maintWeightShiftStart, BN),
+ getNullOrTransform(values.maintWeightShiftEnd, BN),
+ getNullOrTransform(values.maintWeightShiftAssetTarget, null, Number),
+ getNullOrTransform(values.maintWeightShiftLiabTarget, null, Number),
+ values.maintWeightShiftAbort!,
+ values.setFallbackOracle!,
+ getNullOrTransform(values.depositLimit, BN),
+ getNullOrTransform(values.zeroUtilRate, null, Number),
+ getNullOrTransform(values.platformLiquidationFee, null, Number),
+ values.disableAssetLiquidation!,
+ getNullOrTransform(values.collateralFeePerDay, null, Number),
+ values.forceWithdraw!
+ )
+ .accounts({
+ group: mangoGroup!.publicKey,
+ oracle: form.oraclePk ? new PublicKey(form.oraclePk) : bank.oracle,
+ admin: form.governedAccount.extensions.transferAddress,
+ mintInfo: mintInfo.publicKey,
+ fallbackOracle: form.fallbackOracle
+ ? new PublicKey(form.fallbackOracle)
+ : bank.fallbackOracle,
+ })
+ .remainingAccounts([
+ {
+ pubkey: bank.publicKey,
+ isWritable: true,
+ isSigner: false,
+ } as AccountMeta,
+ ])
+ .instruction()
+
+ serializedInstruction = serializeInstructionToBase64(
+ forwarderProgramHelpers.withForwarderWrapper(ix)
+ )
+ }
+ const obj: UiInstruction = {
+ serializedInstruction: serializedInstruction,
+ isValid,
+ chunkBy: 1,
+ governance: form.governedAccount?.governance,
+ customHoldUpTime: form.holdupTime,
+ }
+ return obj
+ }
+
+ useEffect(() => {
+ handleSetInstructions(
+ { governedAccount: form.governedAccount?.governance, getInstruction },
+ index
+ )
+ // 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
+ }, [
+ form,
+ forcedValues,
+ forwarderProgramHelpers.form,
+ forwarderProgramHelpers.withForwarderWrapper,
+ ])
+
+ useEffect(() => {
+ const getTokens = async () => {
+ const currentTokens = [...mangoGroup!.banksMapByMint.values()].map(
+ (x) => ({
+ name: x[0].name,
+ value: x[0].mint,
+ })
+ )
+ setTokens(currentTokens)
+ }
+ if (wallet?.publicKey && mangoGroup) {
+ getTokens()
+ }
+ }, [mangoGroup, wallet?.publicKey])
+
+ const formTokenPk = form.token?.value.toBase58()
+ useEffect(() => {
+ if (
+ formTokenPk &&
+ mangoGroup &&
+ mangoGroup!.banksMapByMint.get(formTokenPk)
+ ) {
+ const currentToken = mangoGroup!.banksMapByMint.get(formTokenPk)![0]
+ const groupInsuranceFund = mangoGroup.mintInfosMapByMint.get(formTokenPk)
+ ?.groupInsuranceFund
+
+ const vals = {
+ oraclePk: currentToken.oracle.toBase58(),
+ fallbackOracle: currentToken.fallbackOracle.toBase58(),
+ oracleConfFilter: currentToken.oracleConfig.confFilter.toNumber(),
+ maxStalenessSlots: currentToken.oracleConfig.maxStalenessSlots.toNumber(),
+ mintPk: currentToken.mint.toBase58(),
+ name: currentToken.name,
+ adjustmentFactor: currentToken.adjustmentFactor.toNumber(),
+ util0: currentToken.util0.toNumber(),
+ rate0: currentToken.rate0.toNumber(),
+ util1: currentToken.util1.toNumber(),
+ rate1: currentToken.rate1.toNumber(),
+ maxRate: currentToken.maxRate.toNumber(),
+ loanFeeRate: currentToken.loanFeeRate.toNumber(),
+ loanOriginationFeeRate: currentToken.loanOriginationFeeRate.toNumber(),
+ maintAssetWeight: currentToken.maintAssetWeight.toNumber(),
+ initAssetWeight: currentToken.initAssetWeight.toNumber(),
+ maintLiabWeight: currentToken.maintLiabWeight.toNumber(),
+ initLiabWeight: currentToken.initLiabWeight.toNumber(),
+ liquidationFee: currentToken.liquidationFee.toNumber(),
+ stablePriceDelayIntervalSeconds:
+ currentToken.stablePriceModel.delayIntervalSeconds,
+ stablePriceDelayGrowthLimit:
+ currentToken.stablePriceModel.delayGrowthLimit,
+ stablePriceGrowthLimit: currentToken.stablePriceModel.stableGrowthLimit,
+ minVaultToDepositsRatio: currentToken.minVaultToDepositsRatio,
+ netBorrowLimitPerWindowQuote: currentToken.netBorrowLimitPerWindowQuote.toNumber(),
+ netBorrowLimitWindowSizeTs: currentToken.netBorrowLimitWindowSizeTs.toNumber(),
+ borrowWeightScaleStartQuote: currentToken.borrowWeightScaleStartQuote,
+ depositWeightScaleStartQuote: currentToken.depositWeightScaleStartQuote,
+ groupInsuranceFund: !!groupInsuranceFund,
+ reduceOnly: REDUCE_ONLY_OPTIONS.find(
+ (x) => x.value === currentToken.reduceOnly
+ )!,
+ forceClose: currentToken.forceClose,
+ tokenConditionalSwapTakerFeeRate:
+ currentToken.tokenConditionalSwapTakerFeeRate,
+ tokenConditionalSwapMakerFeeRate:
+ currentToken.tokenConditionalSwapMakerFeeRate,
+ flashLoanSwapFeeRate: currentToken.flashLoanSwapFeeRate,
+ interestCurveScaling: currentToken.interestCurveScaling,
+ interestTargetUtilization: currentToken.interestTargetUtilization,
+ maintWeightShiftStart: currentToken.maintWeightShiftStart.toNumber(),
+ maintWeightShiftEnd: currentToken.maintWeightShiftEnd.toNumber(),
+ maintWeightShiftAssetTarget: currentToken.maintWeightShiftAssetTarget.toNumber(),
+ maintWeightShiftLiabTarget: currentToken.maintWeightShiftLiabTarget.toNumber(),
+ depositLimit: currentToken.depositLimit.toNumber(),
+ zeroUtilRate: currentToken.zeroUtilRate.toNumber(),
+ platformLiquidationFeeOpt: currentToken.platformLiquidationFee.toNumber(),
+ collateralFeePerDayOpt: currentToken.collateralFeePerDay,
+ }
+ setForm((prevForm) => ({
+ ...prevForm,
+ ...vals,
+ }))
+ setOriginalFormValues((prevForm) => ({ ...prevForm, ...vals }))
+ }
+ }, [formTokenPk, mangoGroup])
+
+ const schema = yup.object().shape({
+ governedAccount: yup
+ .object()
+ .nullable()
+ .required('Program governed account is required'),
+ mintPk: yup
+ .string()
+ .required()
+ .test('is-valid-address1', 'Please enter a valid PublicKey', (value) =>
+ value ? validatePubkey(value) : true
+ ),
+ oraclePk: yup
+ .string()
+ .required()
+ .test('is-valid-address2', 'Please enter a valid PublicKey', (value) =>
+ value ? validatePubkey(value) : true
+ ),
+ name: yup.string().required(),
+ })
+
+ const inputs: InstructionInput[] = [
+ {
+ label: 'Governance',
+ initialValue: form.governedAccount,
+ name: 'governedAccount',
+ type: InstructionInputType.GOVERNED_ACCOUNT,
+ shouldBeGoverned: shouldBeGoverned as any,
+ governance: governance,
+ options: solAccounts,
+ },
+ {
+ label: 'Instruction hold up time (days)',
+ initialValue: form.holdupTime,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'holdupTime',
+ },
+ {
+ label: 'Token',
+ name: 'token',
+ type: InstructionInputType.SELECT,
+ initialValue: form.token,
+ options: tokens,
+ },
+ {
+ label: keyToLabel['mintPk'],
+ initialValue: form.mintPk,
+ type: InstructionInputType.INPUT,
+ name: 'mintPk',
+ },
+ {
+ label: keyToLabel['oraclePk'],
+ initialValue: form.oraclePk,
+ type: InstructionInputType.INPUT,
+ name: 'oraclePk',
+ },
+ {
+ label: keyToLabel['fallbackOracle'],
+ initialValue: form.fallbackOracle,
+ type: InstructionInputType.INPUT,
+ name: 'fallbackOracle',
+ },
+ {
+ label: keyToLabel['oracleConfFilter'],
+ subtitle: getAdditionalLabelInfo('oracleConfFilter'),
+ initialValue: form.oracleConfFilter,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'oracleConfFilter',
+ },
+ {
+ label: keyToLabel['maxStalenessSlots'],
+ subtitle: getAdditionalLabelInfo('maxStalenessSlots'),
+ initialValue: form.maxStalenessSlots,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'maxStalenessSlots',
+ },
+ {
+ label: keyToLabel['name'],
+ initialValue: form.name,
+ type: InstructionInputType.INPUT,
+ name: 'name',
+ },
+ {
+ label: keyToLabel['adjustmentFactor'],
+ subtitle: getAdditionalLabelInfo('adjustmentFactor'),
+ initialValue: form.adjustmentFactor,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'adjustmentFactor',
+ },
+ {
+ label: keyToLabel['util0'],
+ initialValue: form.util0,
+ subtitle: getAdditionalLabelInfo('util0'),
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'util0',
+ },
+ {
+ label: keyToLabel['rate0'],
+ subtitle: getAdditionalLabelInfo('rate0'),
+ initialValue: form.rate0,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'rate0',
+ },
+ {
+ label: keyToLabel['util1'],
+ subtitle: getAdditionalLabelInfo('util1'),
+ initialValue: form.util1,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'util1',
+ },
+ {
+ label: keyToLabel['rate1'],
+ subtitle: getAdditionalLabelInfo('rate1'),
+ initialValue: form.rate1,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'rate1',
+ },
+ {
+ label: keyToLabel['maxRate'],
+ subtitle: getAdditionalLabelInfo('maxRate'),
+ initialValue: form.maxRate,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'maxRate',
+ },
+ {
+ label: keyToLabel['loanFeeRate'],
+ subtitle: getAdditionalLabelInfo('loanFeeRate'),
+ initialValue: form.loanFeeRate,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'loanFeeRate',
+ },
+ {
+ label: keyToLabel['loanOriginationFeeRate'],
+ subtitle: getAdditionalLabelInfo('loanOriginationFeeRate'),
+ initialValue: form.loanOriginationFeeRate,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'loanOriginationFeeRate',
+ },
+ {
+ label: keyToLabel['maintAssetWeight'],
+ subtitle: getAdditionalLabelInfo('maintAssetWeight'),
+ initialValue: form.maintAssetWeight,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'maintAssetWeight',
+ },
+ {
+ label: keyToLabel['initAssetWeight'],
+ subtitle: getAdditionalLabelInfo('initAssetWeight'),
+ initialValue: form.initAssetWeight,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'initAssetWeight',
+ },
+ {
+ label: keyToLabel['maintLiabWeight'],
+ subtitle: getAdditionalLabelInfo('maintLiabWeight'),
+ initialValue: form.maintLiabWeight,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'maintLiabWeight',
+ },
+ {
+ label: keyToLabel['initLiabWeight'],
+ subtitle: getAdditionalLabelInfo('initLiabWeight'),
+ initialValue: form.initLiabWeight,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'initLiabWeight',
+ },
+ {
+ label: keyToLabel['liquidationFee'],
+ subtitle: getAdditionalLabelInfo('liquidationFee'),
+ initialValue: form.liquidationFee,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'liquidationFee',
+ },
+ {
+ label: keyToLabel['groupInsuranceFund'],
+ subtitle: getAdditionalLabelInfo('groupInsuranceFund'),
+ initialValue: form.groupInsuranceFund,
+ type: InstructionInputType.SWITCH,
+ name: 'groupInsuranceFund',
+ },
+ {
+ label: keyToLabel['stablePriceDelayIntervalSeconds'],
+ subtitle: getAdditionalLabelInfo('stablePriceDelayIntervalSeconds'),
+ initialValue: form.stablePriceDelayIntervalSeconds,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'stablePriceDelayIntervalSeconds',
+ },
+ {
+ label: keyToLabel['stablePriceDelayGrowthLimit'],
+ subtitle: getAdditionalLabelInfo('stablePriceDelayGrowthLimit'),
+ initialValue: form.stablePriceDelayGrowthLimit,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'stablePriceDelayGrowthLimit',
+ },
+ {
+ label: keyToLabel['stablePriceGrowthLimit'],
+ subtitle: getAdditionalLabelInfo('stablePriceGrowthLimit'),
+ initialValue: form.stablePriceGrowthLimit,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'stablePriceGrowthLimit',
+ },
+ {
+ label: keyToLabel['minVaultToDepositsRatio'],
+ subtitle: getAdditionalLabelInfo('minVaultToDepositsRatio'),
+ initialValue: form.minVaultToDepositsRatio,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'minVaultToDepositsRatio',
+ },
+ {
+ label: keyToLabel['netBorrowLimitPerWindowQuote'],
+ subtitle: getAdditionalLabelInfo('netBorrowLimitPerWindowQuote'),
+ initialValue: form.netBorrowLimitPerWindowQuote,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'netBorrowLimitPerWindowQuote',
+ },
+ {
+ label: keyToLabel['netBorrowLimitWindowSizeTs'],
+ subtitle: getAdditionalLabelInfo('netBorrowLimitWindowSizeTs'),
+ initialValue: form.netBorrowLimitWindowSizeTs,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'netBorrowLimitWindowSizeTs',
+ },
+ {
+ label: keyToLabel['borrowWeightScaleStartQuote'],
+ subtitle: getAdditionalLabelInfo('borrowWeightScaleStartQuote'),
+ initialValue: form.borrowWeightScaleStartQuote,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'borrowWeightScaleStartQuote',
+ },
+ {
+ label: keyToLabel['depositWeightScaleStartQuote'],
+ subtitle: getAdditionalLabelInfo('depositWeightScaleStartQuote'),
+ initialValue: form.depositWeightScaleStartQuote,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'depositWeightScaleStartQuote',
+ },
+ {
+ label: keyToLabel['resetStablePrice'],
+ subtitle: getAdditionalLabelInfo('resetStablePrice'),
+ initialValue: form.resetStablePrice,
+ type: InstructionInputType.SWITCH,
+ name: 'resetStablePrice',
+ },
+ {
+ label: keyToLabel['resetNetBorrowLimit'],
+ subtitle: getAdditionalLabelInfo('resetNetBorrowLimit'),
+ initialValue: form.resetNetBorrowLimit,
+ type: InstructionInputType.SWITCH,
+ name: 'resetNetBorrowLimit',
+ },
+ {
+ label: keyToLabel['reduceOnly'],
+ subtitle: getAdditionalLabelInfo('reduceOnly'),
+ initialValue: form.reduceOnly,
+ type: InstructionInputType.SELECT,
+ options: REDUCE_ONLY_OPTIONS,
+ name: 'reduceOnly',
+ },
+ {
+ label: keyToLabel['forceClose'],
+ subtitle: getAdditionalLabelInfo('forceClose'),
+ initialValue: form.forceClose,
+ type: InstructionInputType.SWITCH,
+ name: 'forceClose',
+ },
+ {
+ label: keyToLabel['tokenConditionalSwapMakerFeeRate'],
+ subtitle: getAdditionalLabelInfo('tokenConditionalSwapMakerFeeRate'),
+ initialValue: form.tokenConditionalSwapMakerFeeRate,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'tokenConditionalSwapMakerFeeRate',
+ },
+ {
+ label: keyToLabel['tokenConditionalSwapTakerFeeRate'],
+ subtitle: getAdditionalLabelInfo('tokenConditionalSwapTakerFeeRate'),
+ initialValue: form.tokenConditionalSwapTakerFeeRate,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'tokenConditionalSwapTakerFeeRate',
+ },
+ {
+ label: keyToLabel['flashLoanSwapFeeRate'],
+ subtitle: getAdditionalLabelInfo('flashLoanSwapFeeRate'),
+ initialValue: form.flashLoanSwapFeeRate,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'flashLoanSwapFeeRate',
+ },
+ {
+ label: keyToLabel['interestCurveScaling'],
+ subtitle: getAdditionalLabelInfo('interestCurveScaling'),
+ initialValue: form.interestCurveScaling,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'interestCurveScaling',
+ },
+ {
+ label: keyToLabel['interestTargetUtilization'],
+ subtitle: getAdditionalLabelInfo('interestTargetUtilization'),
+ initialValue: form.interestTargetUtilization,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'interestTargetUtilization',
+ },
+ {
+ label: keyToLabel['maintWeightShiftStart'],
+ subtitle: getAdditionalLabelInfo('maintWeightShiftStart'),
+ initialValue: form.maintWeightShiftStart,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'maintWeightShiftStart',
+ },
+ {
+ label: keyToLabel['maintWeightShiftEnd'],
+ subtitle: getAdditionalLabelInfo('maintWeightShiftEnd'),
+ initialValue: form.maintWeightShiftEnd,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'maintWeightShiftEnd',
+ },
+ {
+ label: keyToLabel['maintWeightShiftAssetTarget'],
+ subtitle: getAdditionalLabelInfo('maintWeightShiftAssetTarget'),
+ initialValue: form.maintWeightShiftAssetTarget,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'maintWeightShiftAssetTarget',
+ },
+ {
+ label: keyToLabel['maintWeightShiftLiabTarget'],
+ subtitle: getAdditionalLabelInfo('maintWeightShiftLiabTarget'),
+ initialValue: form.maintWeightShiftLiabTarget,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'maintWeightShiftLiabTarget',
+ },
+ {
+ label: keyToLabel['maintWeightShiftAbort'],
+ subtitle: getAdditionalLabelInfo('maintWeightShiftAbort'),
+ initialValue: form.maintWeightShiftAbort,
+ type: InstructionInputType.SWITCH,
+ name: 'maintWeightShiftAbort',
+ },
+ {
+ label: keyToLabel['setFallbackOracle'],
+ subtitle: getAdditionalLabelInfo('setFallbackOracle'),
+ initialValue: form.setFallbackOracle,
+ type: InstructionInputType.SWITCH,
+ name: 'setFallbackOracle',
+ },
+ {
+ label: keyToLabel['depositLimit'],
+ subtitle: getAdditionalLabelInfo('depositLimit'),
+ initialValue: form.depositLimit,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'depositLimit',
+ },
+ {
+ label: keyToLabel['zeroUtilRate'],
+ subtitle: getAdditionalLabelInfo('zeroUtilRate'),
+ initialValue: form.zeroUtilRate,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'zeroUtilRate',
+ },
+ {
+ label: keyToLabel['platformLiquidationFee'],
+ subtitle: getAdditionalLabelInfo('platformLiquidationFee'),
+ initialValue: form.platformLiquidationFee,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'platformLiquidationFee',
+ },
+ {
+ label: keyToLabel['disableAssetLiquidation'],
+ subtitle: getAdditionalLabelInfo('disableAssetLiquidation'),
+ initialValue: form.disableAssetLiquidation,
+ type: InstructionInputType.SWITCH,
+ name: 'disableAssetLiquidation',
+ },
+ {
+ label: keyToLabel['collateralFeePerDay'],
+ subtitle: getAdditionalLabelInfo('collateralFeePerDay'),
+ initialValue: form.collateralFeePerDay,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'collateralFeePerDay',
+ },
+ {
+ label: keyToLabel['forceWithdraw'],
+ subtitle: getAdditionalLabelInfo('forceWithdraw'),
+ initialValue: form.forceWithdraw,
+ type: InstructionInputType.SWITCH,
+ name: 'forceWithdraw',
+ },
+ ]
+
+ return (
+ <>
+
+ {form && (
+ <>
+
+
+
+ Force values
+
+ {Object.keys(defaultFormValues)
+ .filter((x) => x !== 'governedAccount')
+ .filter((x) => x !== 'token')
+ .filter((x) => x !== 'holdupTime')
+ .map((key) => (
+
+
{keyToLabel[key]}
+
+ x === key) ? true : false
+ }
+ onChange={(checked) => {
+ if (checked) {
+ setForcedValues([...forcedValues, key])
+ } else {
+ setForcedValues([
+ ...forcedValues.filter((x) => x !== key),
+ ])
+ }
+ }}
+ />
+
+
+ ))}
+
+
+ >
+ )}
+ >
+ )
+}
+
+export default EditToken
diff --git a/pages/dao/[symbol]/proposal/components/instructions/Mango/MangoV4/GroupEdit.tsx b/pages/dao/[symbol]/proposal/components/instructions/Mango/MangoV4/GroupEdit.tsx
index 426bf98a7b..37f76268a9 100644
--- a/pages/dao/[symbol]/proposal/components/instructions/Mango/MangoV4/GroupEdit.tsx
+++ b/pages/dao/[symbol]/proposal/components/instructions/Mango/MangoV4/GroupEdit.tsx
@@ -17,6 +17,8 @@ import { getChangedValues, getNullOrTransform } from '@utils/mangoV4Tools'
import AdvancedOptionsDropdown from '@components/NewRealmWizard/components/AdvancedOptionsDropdown'
import Switch from '@components/Switch'
import useWalletOnePointOh from '@hooks/useWalletOnePointOh'
+import ProgramSelector from '@components/Mango/ProgramSelector'
+import useProgramSelector from '@components/Mango/useProgramSelector'
const keyToLabel = {
admin: 'Admin',
@@ -74,7 +76,11 @@ const GroupEdit = ({
governance: ProgramAccount | null
}) => {
const wallet = useWalletOnePointOh()
- const { mangoClient, mangoGroup, getAdditionalLabelInfo } = UseMangoV4()
+ const programSelectorHook = useProgramSelector()
+ const { mangoClient, mangoGroup, getAdditionalLabelInfo } = UseMangoV4(
+ programSelectorHook.program?.val,
+ programSelectorHook.program?.group
+ )
const { assetAccounts } = useGovernanceAssets()
const solAccounts = assetAccounts.filter(
(x) =>
@@ -328,6 +334,9 @@ const GroupEdit = ({
return (
<>
+
{form && (
<>
| null
+}) => {
+ const wallet = useWalletOnePointOh()
+ const programSelectorHook = useProgramSelector()
+ const { mangoClient, mangoGroup, getAdditionalLabelInfo } = UseMangoV4(
+ programSelectorHook.program?.val,
+ programSelectorHook.program?.group
+ )
+ const { assetAccounts } = useGovernanceAssets()
+ const solAccounts = assetAccounts.filter(
+ (x) =>
+ x.type === AccountType.SOL &&
+ ((mangoGroup?.admin &&
+ x.extensions.transferAddress?.equals(mangoGroup.admin)) ||
+ (mangoGroup?.securityAdmin &&
+ x.extensions.transferAddress?.equals(mangoGroup.securityAdmin)))
+ )
+ const shouldBeGoverned = !!(index !== 0 && governance)
+ const [originalFormValues, setOriginalFormValues] = useState({
+ ...defaultFormValues,
+ })
+ const [form, setForm] = useState({ ...defaultFormValues })
+ const [forcedValues, setForcedValues] = useState([])
+ const [formErrors, setFormErrors] = useState({})
+ const { handleSetInstructions } = useContext(NewProposalContext)
+
+ const validateInstruction = async (): Promise => {
+ const { isValid, validationErrors } = await isFormValid(schema, form)
+ setFormErrors(validationErrors)
+ return isValid
+ }
+ async function getInstruction(): Promise {
+ const isValid = await validateInstruction()
+ let serializedInstruction = ''
+ if (
+ isValid &&
+ form.governedAccount?.governance?.account &&
+ wallet?.publicKey
+ ) {
+ const values = getChangedValues(
+ originalFormValues,
+ form,
+ forcedValues
+ )
+ //Mango instruction call and serialize
+ const ix = await mangoClient!.program.methods
+ .groupEdit(
+ getNullOrTransform(values.admin, PublicKey),
+ getNullOrTransform(values.fastListingAdmin, PublicKey),
+ getNullOrTransform(values.securityAdmin, PublicKey),
+ getNullOrTransform(values.testing, null, Number),
+ getNullOrTransform(values.version, null, Number),
+ getNullOrTransform(values.depositLimitQuote, BN),
+ getNullOrTransform(values.feePayWithMngo, null, Boolean),
+ getNullOrTransform(values.feesMngoBonusRate, null, Number),
+ getNullOrTransform(values.feesSwapMangoAccount, PublicKey),
+ getNullOrTransform(values.feesMngoTokenIndex, null, Number),
+ getNullOrTransform(values.feesExpiryInterval, BN),
+ getNullOrTransform(
+ values.allowedFastListingsPerInterval,
+ null,
+ Number
+ ),
+ getNullOrTransform(values.collateralFeeInterval, BN)
+ )
+ .accounts({
+ group: mangoGroup!.publicKey,
+ admin: mangoGroup!.admin,
+ })
+ .instruction()
+
+ serializedInstruction = serializeInstructionToBase64(ix)
+ }
+ const obj: UiInstruction = {
+ serializedInstruction: serializedInstruction,
+ isValid,
+ governance: form.governedAccount?.governance,
+ customHoldUpTime: form.holdupTime,
+ }
+ return obj
+ }
+
+ useEffect(() => {
+ handleSetInstructions(
+ { governedAccount: form.governedAccount?.governance, getInstruction },
+ index
+ )
+ // 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
+ }, [form, forcedValues])
+ const schema = yup.object().shape({
+ governedAccount: yup
+ .object()
+ .nullable()
+ .required('Program governed account is required'),
+ admin: yup
+ .string()
+ .required()
+ .test('is-valid-address', 'Please enter a valid PublicKey', (value) =>
+ value ? validatePubkey(value) : true
+ ),
+ fastListingAdmin: yup
+ .string()
+ .required()
+ .test('is-valid-address1', 'Please enter a valid PublicKey', (value) =>
+ value ? validatePubkey(value) : true
+ ),
+ securityAdmin: yup
+ .string()
+ .required()
+ .test('is-valid-address2', 'Please enter a valid PublicKey', (value) =>
+ value ? validatePubkey(value) : true
+ ),
+ feesSwapMangoAccount: yup
+ .string()
+ .nullable()
+ .test('is-valid-address3', 'Please enter a valid PublicKey', (value) =>
+ value ? validatePubkey(value) : true
+ ),
+ testing: yup.string().required(),
+ version: yup.string().required(),
+ depositLimitQuote: yup.string().required(),
+ })
+
+ useEffect(() => {
+ const getGroupParams = async () => {
+ const vals = {
+ admin: mangoGroup!.admin.toBase58(),
+ fastListingAdmin: mangoGroup!.fastListingAdmin.toBase58(),
+ securityAdmin: mangoGroup!.securityAdmin.toBase58(),
+ testing: mangoGroup!.testing,
+ version: mangoGroup!.version,
+ feePayWithMngo: mangoGroup!.buybackFees,
+ feesMngoBonusRate: mangoGroup!.buybackFeesMngoBonusFactor,
+ feesSwapMangoAccount: mangoGroup!.buybackFeesSwapMangoAccount?.toBase58(),
+ feesMngoTokenIndex: mangoGroup!.mngoTokenIndex,
+ feesExpiryInterval: mangoGroup!.buybackFeesExpiryInterval?.toNumber(),
+ allowedFastListingsPerInterval: mangoGroup!
+ .allowedFastListingsPerInterval,
+ collateralFeeInterval: mangoGroup!.collateralFeeInterval.toNumber(),
+ }
+ setForm((prevForm) => ({
+ ...prevForm,
+ ...vals,
+ }))
+ setOriginalFormValues((prevForm) => ({ ...prevForm, ...vals }))
+ }
+ if (mangoGroup) {
+ getGroupParams()
+ }
+ }, [mangoGroup])
+
+ const inputs: InstructionInput[] = [
+ {
+ label: 'Governance',
+ initialValue: form.governedAccount,
+ name: 'governedAccount',
+ type: InstructionInputType.GOVERNED_ACCOUNT,
+ shouldBeGoverned: shouldBeGoverned as any,
+ governance: governance,
+ options: solAccounts,
+ },
+ {
+ label: 'Instruction hold up time (days)',
+ initialValue: form.holdupTime,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'holdupTime',
+ },
+ {
+ label: keyToLabel['admin'],
+ subtitle: getAdditionalLabelInfo('admin'),
+ initialValue: form.admin,
+ type: InstructionInputType.INPUT,
+ name: 'admin',
+ },
+ {
+ label: keyToLabel['fastListingAdmin'],
+ subtitle: getAdditionalLabelInfo('fastListingAdmin'),
+ initialValue: form.fastListingAdmin,
+ type: InstructionInputType.INPUT,
+ name: 'fastListingAdmin',
+ },
+ {
+ label: keyToLabel['securityAdmin'],
+ subtitle: getAdditionalLabelInfo('securityAdmin'),
+ initialValue: form.securityAdmin,
+ type: InstructionInputType.INPUT,
+ name: 'securityAdmin',
+ },
+ {
+ label: keyToLabel['testing'],
+ subtitle: getAdditionalLabelInfo('testing'),
+ initialValue: form.testing,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'testing',
+ },
+ {
+ label: keyToLabel['version'],
+ subtitle: getAdditionalLabelInfo('version'),
+ initialValue: form.version,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'version',
+ },
+ {
+ label: keyToLabel['depositLimitQuote'],
+ subtitle: getAdditionalLabelInfo('depositLimitQuote'),
+ initialValue: form.depositLimitQuote,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'depositLimitQuote',
+ },
+ {
+ label: keyToLabel['feePayWithMngo'],
+ initialValue: form.feePayWithMngo,
+ subtitle: getAdditionalLabelInfo('buybackFees'),
+ type: InstructionInputType.SWITCH,
+ name: 'feePayWithMngo',
+ },
+ {
+ label: keyToLabel['feesMngoBonusRate'],
+ subtitle: getAdditionalLabelInfo('buybackFeesMngoBonusFactor'),
+ initialValue: form.feesMngoBonusRate,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'feesMngoBonusRate',
+ },
+ {
+ label: keyToLabel['feesSwapMangoAccount'],
+ subtitle: getAdditionalLabelInfo('buybackFeesSwapMangoAccount'),
+ initialValue: form.feesSwapMangoAccount,
+ type: InstructionInputType.INPUT,
+ name: 'feesSwapMangoAccount',
+ },
+ {
+ label: keyToLabel['feesMngoTokenIndex'],
+ subtitle: getAdditionalLabelInfo('mngoTokenIndex'),
+ initialValue: form.feesMngoTokenIndex,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'feesMngoTokenIndex',
+ },
+ {
+ label: keyToLabel['feesExpiryInterval'],
+ subtitle: getAdditionalLabelInfo('feesExpiryInterval'),
+ initialValue: form.feesExpiryInterval,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'feesExpiryInterval',
+ },
+ {
+ label: keyToLabel['allowedFastListingsPerInterval'],
+ subtitle: getAdditionalLabelInfo('allowedFastListingsPerInterval'),
+ initialValue: form.allowedFastListingsPerInterval,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'allowedFastListingsPerInterval',
+ },
+ {
+ label: keyToLabel['collateralFeeInterval'],
+ subtitle: getAdditionalLabelInfo('collateralFeeInterval'),
+ initialValue: form.collateralFeeInterval,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'collateralFeeInterval',
+ },
+ ]
+
+ return (
+ <>
+
+ {form && (
+ <>
+
+
+ Force values
+
+ {Object.keys(defaultFormValues)
+ .filter((x) => x !== 'governedAccount')
+ .filter((x) => x !== 'holdupTime')
+ .map((key) => (
+
+
{keyToLabel[key]}
+
+ x === key) ? true : false
+ }
+ onChange={(checked) => {
+ if (checked) {
+ setForcedValues([...forcedValues, key])
+ } else {
+ setForcedValues([
+ ...forcedValues.filter((x) => x !== key),
+ ])
+ }
+ }}
+ />
+
+
+ ))}
+
+
+ >
+ )}
+ >
+ )
+}
+
+export default GroupEdit
diff --git a/pages/dao/[symbol]/proposal/components/instructions/Mango/MangoV4/IxGateSet.tsx b/pages/dao/[symbol]/proposal/components/instructions/Mango/MangoV4/IxGateSet.tsx
index 01890ab643..ea37e78ac4 100644
--- a/pages/dao/[symbol]/proposal/components/instructions/Mango/MangoV4/IxGateSet.tsx
+++ b/pages/dao/[symbol]/proposal/components/instructions/Mango/MangoV4/IxGateSet.tsx
@@ -15,6 +15,8 @@ import UseMangoV4 from '../../../../../../../../hooks/useMangoV4'
import { buildIxGate } from '@blockworks-foundation/mango-v4'
import { IxGateParams } from '@blockworks-foundation/mango-v4/dist/types/src/clientIxParamBuilder'
import useWalletOnePointOh from '@hooks/useWalletOnePointOh'
+import ProgramSelector from '@components/Mango/ProgramSelector'
+import useProgramSelector from '@components/Mango/useProgramSelector'
type IxGateSetForm = IxGateParams & {
governedAccount: AssetAccount | null
@@ -29,7 +31,11 @@ const IxGateSet = ({
governance: ProgramAccount | null
}) => {
const wallet = useWalletOnePointOh()
- const { mangoClient, mangoGroup } = UseMangoV4()
+ const programSelectorHook = useProgramSelector()
+ const { mangoClient, mangoGroup } = UseMangoV4(
+ programSelectorHook.program?.val,
+ programSelectorHook.program?.group
+ )
const { assetAccounts } = useGovernanceAssets()
const solAccounts = assetAccounts.filter(
(x) =>
@@ -638,6 +644,9 @@ const IxGateSet = ({
return (
<>
+
{form && (
| null
+}) => {
+ const wallet = useWalletOnePointOh()
+ const programSelectorHook = useProgramSelector()
+ const { mangoClient, mangoGroup } = UseMangoV4(
+ programSelectorHook.program?.val,
+ programSelectorHook.program?.group
+ )
+ const { assetAccounts } = useGovernanceAssets()
+ const solAccounts = assetAccounts.filter(
+ (x) =>
+ x.type === AccountType.SOL &&
+ ((mangoGroup?.admin &&
+ x.extensions.transferAddress?.equals(mangoGroup.admin)) ||
+ (mangoGroup?.securityAdmin &&
+ x.extensions.transferAddress?.equals(mangoGroup.securityAdmin)))
+ )
+ const shouldBeGoverned = !!(index !== 0 && governance)
+ const [form, setForm] = useState({
+ governedAccount: null,
+ holdupTime: 0,
+ AccountClose: true,
+ AccountCreate: true,
+ AccountEdit: true,
+ AccountExpand: true,
+ AccountToggleFreeze: true,
+ AltExtend: true,
+ AltSet: true,
+ FlashLoan: true,
+ GroupClose: true,
+ GroupCreate: true,
+ GroupToggleHalt: true,
+ HealthRegion: true,
+ PerpCancelAllOrders: true,
+ PerpCancelAllOrdersBySide: true,
+ PerpCancelOrder: true,
+ PerpCancelOrderByClientOrderId: true,
+ PerpCloseMarket: true,
+ PerpConsumeEvents: true,
+ PerpCreateMarket: true,
+ PerpDeactivatePosition: true,
+ PerpEditMarket: true,
+ PerpLiqBaseOrPositivePnl: true,
+ PerpLiqForceCancelOrders: true,
+ PerpLiqNegativePnlOrBankruptcy: true,
+ PerpPlaceOrder: true,
+ PerpSettleFees: true,
+ PerpSettlePnl: true,
+ PerpUpdateFunding: true,
+ Serum3CancelAllOrders: true,
+ Serum3CancelOrder: true,
+ Serum3CloseOpenOrders: true,
+ Serum3CreateOpenOrders: true,
+ Serum3DeregisterMarket: true,
+ Serum3EditMarket: true,
+ Serum3LiqForceCancelOrders: true,
+ Serum3PlaceOrder: true,
+ Serum3RegisterMarket: true,
+ Serum3SettleFunds: true,
+ StubOracleClose: true,
+ StubOracleCreate: true,
+ StubOracleSet: true,
+ TokenAddBank: true,
+ TokenDeposit: true,
+ TokenDeregister: true,
+ TokenEdit: true,
+ TokenLiqBankruptcy: true,
+ TokenLiqWithToken: true,
+ TokenRegister: true,
+ TokenRegisterTrustless: true,
+ TokenUpdateIndexAndRate: true,
+ TokenWithdraw: true,
+ AccountBuybackFeesWithMngo: true,
+ TokenForceCloseBorrowsWithToken: true,
+ PerpForceClosePosition: true,
+ GroupWithdrawInsuranceFund: true,
+ TokenConditionalSwapCreate: true,
+ TokenConditionalSwapTrigger: true,
+ TokenConditionalSwapCancel: true,
+ OpenbookV2CancelOrder: true,
+ OpenbookV2CloseOpenOrders: true,
+ OpenbookV2CreateOpenOrders: true,
+ OpenbookV2DeregisterMarket: true,
+ OpenbookV2EditMarket: true,
+ OpenbookV2LiqForceCancelOrders: true,
+ OpenbookV2PlaceOrder: true,
+ OpenbookV2PlaceTakeOrder: true,
+ OpenbookV2RegisterMarket: true,
+ OpenbookV2SettleFunds: true,
+ AdminTokenWithdrawFees: true,
+ AdminPerpWithdrawFees: true,
+ AccountSizeMigration: true,
+ TokenConditionalSwapStart: true,
+ TokenConditionalSwapCreatePremiumAuction: true,
+ TokenConditionalSwapCreateLinearAuction: true,
+ Serum3PlaceOrderV2: true,
+ TokenForceWithdraw: true,
+ })
+ const [formErrors, setFormErrors] = useState({})
+ const { handleSetInstructions } = useContext(NewProposalContext)
+
+ const validateInstruction = async (): Promise => {
+ const { isValid, validationErrors } = await isFormValid(schema, form)
+ setFormErrors(validationErrors)
+ return isValid
+ }
+ async function getInstruction(): Promise {
+ const isValid = await validateInstruction()
+ let serializedInstruction = ''
+ if (
+ isValid &&
+ form.governedAccount?.governance?.account &&
+ wallet?.publicKey
+ ) {
+ const ix = await mangoClient!.program.methods
+ .ixGateSet(buildIxGate(form))
+ .accounts({
+ group: mangoGroup!.publicKey,
+ admin: form.governedAccount.extensions.transferAddress,
+ })
+ .instruction()
+
+ serializedInstruction = serializeInstructionToBase64(ix)
+ }
+ const obj: UiInstruction = {
+ serializedInstruction: serializedInstruction,
+ isValid,
+ governance: form.governedAccount?.governance,
+ customHoldUpTime: form.holdupTime,
+ }
+ return obj
+ }
+
+ useEffect(() => {
+ handleSetInstructions(
+ { governedAccount: form.governedAccount?.governance, getInstruction },
+ index
+ )
+ // 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
+ }, [form])
+ const schema = yup.object().shape({
+ governedAccount: yup
+ .object()
+ .nullable()
+ .required('Program governed account is required'),
+ })
+ const inputs: InstructionInput[] = [
+ {
+ label: 'Governance',
+ initialValue: form.governedAccount,
+ name: 'governedAccount',
+ type: InstructionInputType.GOVERNED_ACCOUNT,
+ shouldBeGoverned: shouldBeGoverned as any,
+ governance: governance,
+ options: solAccounts,
+ },
+ {
+ label: 'Instruction hold up time (days)',
+ initialValue: form.holdupTime,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'holdupTime',
+ },
+ {
+ label: 'Account Close',
+ initialValue: form.AccountClose,
+ type: InstructionInputType.SWITCH,
+ name: 'AccountClose',
+ },
+ {
+ label: 'Account Create',
+ initialValue: form.AccountCreate,
+ type: InstructionInputType.SWITCH,
+ name: 'AccountCreate',
+ },
+ {
+ label: 'Account Edit',
+ initialValue: form.AccountEdit,
+ type: InstructionInputType.SWITCH,
+ name: 'AccountEdit',
+ },
+ {
+ label: 'Account Expand',
+ initialValue: form.AccountExpand,
+ type: InstructionInputType.SWITCH,
+ name: 'AccountExpand',
+ },
+ {
+ label: 'Account Toggle Freeze',
+ initialValue: form.AccountToggleFreeze,
+ type: InstructionInputType.SWITCH,
+ name: 'AccountToggleFreeze',
+ },
+ {
+ label: 'Alt Extend',
+ initialValue: form.AltExtend,
+ type: InstructionInputType.SWITCH,
+ name: 'AltExtend',
+ },
+ {
+ label: 'Alt Set',
+ initialValue: form.AltSet,
+ type: InstructionInputType.SWITCH,
+ name: 'AltSet',
+ },
+ {
+ label: 'Flash Loan',
+ initialValue: form.FlashLoan,
+ type: InstructionInputType.SWITCH,
+ name: 'FlashLoan',
+ },
+ {
+ label: 'Group Close',
+ initialValue: form.GroupClose,
+ type: InstructionInputType.SWITCH,
+ name: 'GroupClose',
+ },
+ {
+ label: 'Group Create',
+ initialValue: form.GroupCreate,
+ type: InstructionInputType.SWITCH,
+ name: 'GroupCreate',
+ },
+ {
+ label: 'Group Toggle Halt',
+ initialValue: form.GroupToggleHalt,
+ type: InstructionInputType.SWITCH,
+ name: 'GroupToggleHalt',
+ },
+ {
+ label: 'Health Region',
+ initialValue: form.HealthRegion,
+ type: InstructionInputType.SWITCH,
+ name: 'HealthRegion',
+ },
+ {
+ label: 'Perp Cancel All Orders',
+ initialValue: form.PerpCancelAllOrders,
+ type: InstructionInputType.SWITCH,
+ name: 'PerpCancelAllOrders',
+ },
+ {
+ label: 'Perp Cancel All Orders By Side',
+ initialValue: form.PerpCancelAllOrdersBySide,
+ type: InstructionInputType.SWITCH,
+ name: 'PerpCancelAllOrdersBySide',
+ },
+ {
+ label: 'Perp Cancel Order',
+ initialValue: form.PerpCancelOrder,
+ type: InstructionInputType.SWITCH,
+ name: 'PerpCancelOrder',
+ },
+ {
+ label: 'Perp Cancel Order By Client Order Id',
+ initialValue: form.PerpCancelOrderByClientOrderId,
+ type: InstructionInputType.SWITCH,
+ name: 'PerpCancelOrderByClientOrderId',
+ },
+ {
+ label: 'Perp Close Market',
+ initialValue: form.PerpCloseMarket,
+ type: InstructionInputType.SWITCH,
+ name: 'PerpCloseMarket',
+ },
+ {
+ label: 'Perp Consume Events',
+ initialValue: form.PerpConsumeEvents,
+ type: InstructionInputType.SWITCH,
+ name: 'PerpConsumeEvents',
+ },
+ {
+ label: 'Perp Create Market',
+ initialValue: form.PerpCreateMarket,
+ type: InstructionInputType.SWITCH,
+ name: 'PerpCreateMarket',
+ },
+ {
+ label: 'Perp Deactivate Position',
+ initialValue: form.PerpDeactivatePosition,
+ type: InstructionInputType.SWITCH,
+ name: 'PerpDeactivatePosition',
+ },
+ {
+ label: 'Perp Edit Market',
+ initialValue: form.PerpEditMarket,
+ type: InstructionInputType.SWITCH,
+ name: 'PerpEditMarket',
+ },
+ {
+ label: 'Perp Liq Base Or Positive Pnl',
+ initialValue: form.PerpLiqBaseOrPositivePnl,
+ type: InstructionInputType.SWITCH,
+ name: 'PerpLiqBaseOrPositivePnl',
+ },
+ {
+ label: 'Perp Liq Negative Pnl Or Bankruptcy',
+ initialValue: form.PerpLiqNegativePnlOrBankruptcy,
+ type: InstructionInputType.SWITCH,
+ name: 'PerpLiqNegativePnlOrBankruptcy',
+ },
+ {
+ label: 'Perp Liq Force Cancel Orders',
+ initialValue: form.PerpLiqForceCancelOrders,
+ type: InstructionInputType.SWITCH,
+ name: 'PerpLiqForceCancelOrders',
+ },
+ {
+ label: 'Perp Place Order',
+ initialValue: form.PerpPlaceOrder,
+ type: InstructionInputType.SWITCH,
+ name: 'PerpPlaceOrder',
+ },
+ {
+ label: 'Perp Settle Fees',
+ initialValue: form.PerpSettleFees,
+ type: InstructionInputType.SWITCH,
+ name: 'PerpSettleFees',
+ },
+ {
+ label: 'Perp Settle Pnl',
+ initialValue: form.PerpSettlePnl,
+ type: InstructionInputType.SWITCH,
+ name: 'PerpSettlePnl',
+ },
+ {
+ label: 'Perp Update Funding',
+ initialValue: form.PerpUpdateFunding,
+ type: InstructionInputType.SWITCH,
+ name: 'PerpUpdateFunding',
+ },
+ {
+ label: 'Serum 3 Cancel All Orders',
+ initialValue: form.Serum3CancelAllOrders,
+ type: InstructionInputType.SWITCH,
+ name: 'Serum3CancelAllOrders',
+ },
+ {
+ label: 'Serum 3 Cancel Order',
+ initialValue: form.Serum3CancelOrder,
+ type: InstructionInputType.SWITCH,
+ name: 'Serum3CancelOrder',
+ },
+ {
+ label: 'Serum 3 Close Open Orders',
+ initialValue: form.Serum3CloseOpenOrders,
+ type: InstructionInputType.SWITCH,
+ name: 'Serum3CloseOpenOrders',
+ },
+ {
+ label: 'Serum 3 Create Open Orders',
+ initialValue: form.Serum3CreateOpenOrders,
+ type: InstructionInputType.SWITCH,
+ name: 'Serum3CreateOpenOrders',
+ },
+ {
+ label: 'Serum 3 Deregister Market',
+ initialValue: form.Serum3DeregisterMarket,
+ type: InstructionInputType.SWITCH,
+ name: 'Serum3DeregisterMarket',
+ },
+ {
+ label: 'Serum 3 Edit Market',
+ initialValue: form.Serum3EditMarket,
+ type: InstructionInputType.SWITCH,
+ name: 'Serum3EditMarket',
+ },
+ {
+ label: 'Serum 3 Liq Force Cancel Orders',
+ initialValue: form.Serum3LiqForceCancelOrders,
+ type: InstructionInputType.SWITCH,
+ name: 'Serum3LiqForceCancelOrders',
+ },
+ {
+ label: 'Serum 3 Place Order',
+ initialValue: form.Serum3PlaceOrder,
+ type: InstructionInputType.SWITCH,
+ name: 'Serum3PlaceOrder',
+ },
+ {
+ label: 'Serum 3 Register Market',
+ initialValue: form.Serum3RegisterMarket,
+ type: InstructionInputType.SWITCH,
+ name: 'Serum3RegisterMarket',
+ },
+ {
+ label: 'Serum 3 Settle Funds',
+ initialValue: form.Serum3SettleFunds,
+ type: InstructionInputType.SWITCH,
+ name: 'Serum3SettleFunds',
+ },
+ {
+ label: 'Stub Oracle Close',
+ initialValue: form.StubOracleClose,
+ type: InstructionInputType.SWITCH,
+ name: 'StubOracleClose',
+ },
+ {
+ label: 'Stub Oracle Create',
+ initialValue: form.StubOracleCreate,
+ type: InstructionInputType.SWITCH,
+ name: 'StubOracleCreate',
+ },
+ {
+ label: 'Stub Oracle Set',
+ initialValue: form.StubOracleSet,
+ type: InstructionInputType.SWITCH,
+ name: 'StubOracleSet',
+ },
+ {
+ label: 'Token Add Bank',
+ initialValue: form.TokenAddBank,
+ type: InstructionInputType.SWITCH,
+ name: 'TokenAddBank',
+ },
+ {
+ label: 'Token Deposit',
+ initialValue: form.TokenDeposit,
+ type: InstructionInputType.SWITCH,
+ name: 'TokenDeposit',
+ },
+ {
+ label: 'Token Deregister',
+ initialValue: form.TokenDeregister,
+ type: InstructionInputType.SWITCH,
+ name: 'TokenDeregister',
+ },
+ {
+ label: 'Token Edit',
+ initialValue: form.TokenEdit,
+ type: InstructionInputType.SWITCH,
+ name: 'TokenEdit',
+ },
+ {
+ label: 'Token Liq Bankruptcy',
+ initialValue: form.TokenLiqBankruptcy,
+ type: InstructionInputType.SWITCH,
+ name: 'TokenLiqBankruptcy',
+ },
+ {
+ label: 'Token Liq With Token',
+ initialValue: form.TokenLiqWithToken,
+ type: InstructionInputType.SWITCH,
+ name: 'TokenLiqWithToken',
+ },
+ {
+ label: 'Token Register',
+ initialValue: form.TokenRegister,
+ type: InstructionInputType.SWITCH,
+ name: 'TokenRegister',
+ },
+ {
+ label: 'Token Register Trustless',
+ initialValue: form.TokenRegisterTrustless,
+ type: InstructionInputType.SWITCH,
+ name: 'TokenRegisterTrustless',
+ },
+ {
+ label: 'Token Update Index And Rate',
+ initialValue: form.TokenUpdateIndexAndRate,
+ type: InstructionInputType.SWITCH,
+ name: 'TokenUpdateIndexAndRate',
+ },
+ {
+ label: 'Token Withdraw',
+ initialValue: form.TokenWithdraw,
+ type: InstructionInputType.SWITCH,
+ name: 'TokenWithdraw',
+ },
+ {
+ label: 'Account Buyback Fees With Mngo',
+ initialValue: form.AccountBuybackFeesWithMngo,
+ type: InstructionInputType.SWITCH,
+ name: 'AccountBuybackFeesWithMngo',
+ },
+ {
+ label: 'Token Force Close Borrows With Token',
+ initialValue: form.TokenForceCloseBorrowsWithToken,
+ type: InstructionInputType.SWITCH,
+ name: 'TokenForceCloseBorrowsWithToken',
+ },
+ {
+ label: 'Perp Force Close Position',
+ initialValue: form.PerpForceClosePosition,
+ type: InstructionInputType.SWITCH,
+ name: 'PerpForceClosePosition',
+ },
+ {
+ label: 'Group Withdraw Insurance Fund',
+ initialValue: form.GroupWithdrawInsuranceFund,
+ type: InstructionInputType.SWITCH,
+ name: 'GroupWithdrawInsuranceFund',
+ },
+ {
+ label: 'Token Conditional Swap Create',
+ initialValue: form.TokenConditionalSwapCreate,
+ type: InstructionInputType.SWITCH,
+ name: 'TokenConditionalSwapCreate',
+ },
+ {
+ label: 'Token Conditional Swap Trigger',
+ initialValue: form.TokenConditionalSwapTrigger,
+ type: InstructionInputType.SWITCH,
+ name: 'TokenConditionalSwapTrigger',
+ },
+ {
+ label: 'Token Conditional Swap Cancel',
+ initialValue: form.TokenConditionalSwapCancel,
+ type: InstructionInputType.SWITCH,
+ name: 'TokenConditionalSwapCancel',
+ },
+ {
+ label: 'Openbook V2 Cancel Order',
+ initialValue: form.OpenbookV2CancelOrder,
+ type: InstructionInputType.SWITCH,
+ name: 'OpenbookV2CancelOrder',
+ },
+ {
+ label: 'Openbook V2 Close Open Orders',
+ initialValue: form.OpenbookV2CloseOpenOrders,
+ type: InstructionInputType.SWITCH,
+ name: 'OpenbookV2CloseOpenOrders',
+ },
+ {
+ label: 'Openbook V2 Create Open Orders',
+ initialValue: form.OpenbookV2CreateOpenOrders,
+ type: InstructionInputType.SWITCH,
+ name: 'OpenbookV2CreateOpenOrders',
+ },
+ {
+ label: 'Openbook V2 Deregister Market',
+ initialValue: form.OpenbookV2DeregisterMarket,
+ type: InstructionInputType.SWITCH,
+ name: 'OpenbookV2DeregisterMarket',
+ },
+ {
+ label: 'Openbook V2 Edit Market',
+ initialValue: form.OpenbookV2EditMarket,
+ type: InstructionInputType.SWITCH,
+ name: 'OpenbookV2EditMarket',
+ },
+ {
+ label: 'Openbook V2 Liq Force Cancel Orders',
+ initialValue: form.OpenbookV2LiqForceCancelOrders,
+ type: InstructionInputType.SWITCH,
+ name: 'OpenbookV2LiqForceCancelOrders',
+ },
+ {
+ label: 'Openbook V2 Place Order',
+ initialValue: form.OpenbookV2PlaceOrder,
+ type: InstructionInputType.SWITCH,
+ name: 'OpenbookV2PlaceOrder',
+ },
+ {
+ label: 'Openbook V2 Place Take Order',
+ initialValue: form.OpenbookV2PlaceTakeOrder,
+ type: InstructionInputType.SWITCH,
+ name: 'OpenbookV2PlaceTakeOrder',
+ },
+ {
+ label: 'Openbook V2 Register Market',
+ initialValue: form.OpenbookV2RegisterMarket,
+ type: InstructionInputType.SWITCH,
+ name: 'OpenbookV2RegisterMarket',
+ },
+ {
+ label: 'Openbook V2 Settle Funds',
+ initialValue: form.OpenbookV2SettleFunds,
+ type: InstructionInputType.SWITCH,
+ name: 'OpenbookV2SettleFunds',
+ },
+ {
+ label: 'Admin Token Withdraw Fees',
+ initialValue: form.AdminTokenWithdrawFees,
+ type: InstructionInputType.SWITCH,
+ name: 'AdminTokenWithdrawFees',
+ },
+ {
+ label: 'Admin Perp Withdraw Fees',
+ initialValue: form.AdminPerpWithdrawFees,
+ type: InstructionInputType.SWITCH,
+ name: 'AdminPerpWithdrawFees',
+ },
+ {
+ label: 'Account Size Migration',
+ initialValue: form.AccountSizeMigration,
+ type: InstructionInputType.SWITCH,
+ name: 'AccountSizeMigration',
+ },
+ {
+ label: 'Token Conditional Swap Start',
+ initialValue: form.TokenConditionalSwapStart,
+ type: InstructionInputType.SWITCH,
+ name: 'TokenConditionalSwapStart',
+ },
+ {
+ label: 'Token Conditional Swap Create Premium Auction',
+ initialValue: form.TokenConditionalSwapCreatePremiumAuction,
+ type: InstructionInputType.SWITCH,
+ name: 'TokenConditionalSwapCreatePremiumAuction',
+ },
+ {
+ label: 'Token Conditional Swap Create Linear Auction',
+ initialValue: form.TokenConditionalSwapCreateLinearAuction,
+ type: InstructionInputType.SWITCH,
+ name: 'TokenConditionalSwapCreateLinearAuction',
+ },
+ {
+ label: 'Serum 3 Place Order V2',
+ initialValue: form.Serum3PlaceOrderV2,
+ type: InstructionInputType.SWITCH,
+ name: 'Serum3PlaceOrderV2',
+ },
+ {
+ label: 'Token Force withdraw',
+ initialValue: form.TokenForceWithdraw,
+ type: InstructionInputType.SWITCH,
+ name: 'TokenForceWithdraw',
+ },
+ ]
+
+ return (
+ <>
+
+ {form && (
+
+ )}
+ >
+ )
+}
+
+export default IxGateSet
diff --git a/pages/dao/[symbol]/proposal/components/instructions/Mango/MangoV4/OpenBookEditMarket.tsx b/pages/dao/[symbol]/proposal/components/instructions/Mango/MangoV4/OpenBookEditMarket.tsx
index 6295d02792..086156199c 100644
--- a/pages/dao/[symbol]/proposal/components/instructions/Mango/MangoV4/OpenBookEditMarket.tsx
+++ b/pages/dao/[symbol]/proposal/components/instructions/Mango/MangoV4/OpenBookEditMarket.tsx
@@ -17,6 +17,8 @@ import useWalletOnePointOh from '@hooks/useWalletOnePointOh'
import ForwarderProgram, {
useForwarderProgramHelpers,
} from '@components/ForwarderProgram/ForwarderProgram'
+import ProgramSelector from '@components/Mango/ProgramSelector'
+import useProgramSelector from '@components/Mango/useProgramSelector'
type NameMarketIndexVal = {
name: string
@@ -41,7 +43,11 @@ const OpenBookEditMarket = ({
governance: ProgramAccount | null
}) => {
const wallet = useWalletOnePointOh()
- const { mangoClient, mangoGroup } = UseMangoV4()
+ const programSelectorHook = useProgramSelector()
+ const { mangoClient, mangoGroup } = UseMangoV4(
+ programSelectorHook.program?.val,
+ programSelectorHook.program?.group
+ )
const { assetAccounts } = useGovernanceAssets()
const forwarderProgramHelpers = useForwarderProgramHelpers()
const solAccounts = assetAccounts.filter(
@@ -142,7 +148,7 @@ const OpenBookEditMarket = ({
)
setForm((prevForm) => ({
...prevForm,
- oraclePriceBand: 0,
+ oraclePriceBand: Number(market?.oraclePriceBand) || 0,
reduceOnly: market?.reduceOnly || false,
forceClose: market?.forceClose || false,
name: market?.name || '',
@@ -176,6 +182,13 @@ const OpenBookEditMarket = ({
inputType: 'number',
name: 'holdupTime',
},
+ {
+ label: 'Price band',
+ initialValue: form.oraclePriceBand,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'oraclePriceBand',
+ },
{
label: 'Market',
name: 'market',
@@ -206,6 +219,9 @@ const OpenBookEditMarket = ({
return (
<>
+
{form && (
| null
}) => {
const wallet = useWalletOnePointOh()
- const { mangoClient, mangoGroup } = UseMangoV4()
+ const programSelectorHook = useProgramSelector()
+ const { mangoClient, mangoGroup } = UseMangoV4(
+ programSelectorHook.program?.val,
+ programSelectorHook.program?.group
+ )
const { assetAccounts } = useGovernanceAssets()
const forwarderProgramHelpers = useForwarderProgramHelpers()
const solAccounts = assetAccounts.filter(
@@ -231,6 +237,9 @@ const OpenBookRegisterMarket = ({
return (
<>
+
{form && (
| null
}) => {
const wallet = useWalletOnePointOh()
- const { mangoClient, mangoGroup, getAdditionalLabelInfo } = UseMangoV4()
+ const programSelectorHook = useProgramSelector()
+ const { mangoClient, mangoGroup, getAdditionalLabelInfo } = UseMangoV4(
+ programSelectorHook.program?.val,
+ programSelectorHook.program?.group
+ )
const { assetAccounts } = useGovernanceAssets()
const solAccounts = assetAccounts.filter(
(x) =>
@@ -516,6 +522,9 @@ const PerpCreate = ({
]
return (
<>
+
{form && (
| null
+}) => {
+ const wallet = useWalletOnePointOh()
+ const programSelectorHook = useProgramSelector()
+ const { mangoClient, mangoGroup, getAdditionalLabelInfo } = UseMangoV4(
+ programSelectorHook.program?.val,
+ programSelectorHook.program?.group
+ )
+ const { assetAccounts } = useGovernanceAssets()
+ const solAccounts = assetAccounts.filter(
+ (x) =>
+ x.type === AccountType.SOL &&
+ mangoGroup?.admin &&
+ x.extensions.transferAddress?.equals(mangoGroup?.admin)
+ )
+ const connection = useLegacyConnectionContext()
+ const shouldBeGoverned = !!(index !== 0 && governance)
+ const [form, setForm] = useState({
+ governedAccount: null,
+ oracleConfFilter: 0.1,
+ maxStalenessSlots: '',
+ oraclePk: '',
+ name: '',
+ perpMarketIndex: 0,
+ baseDecimals: 6,
+ quoteLotSize: 10,
+ baseLotSize: 100,
+ maintBaseAssetWeight: 0.975,
+ initBaseAssetWeight: 0.95,
+ maintBaseLiabWeight: 1.025,
+ initBaseLiabWeight: 1.05,
+ maintOverallAssetWeight: 1,
+ initOverallAssetWeight: 1,
+ baseLiquidationFee: 0.0125,
+ makerFee: -0.0001,
+ takerFee: 0.0004,
+ feePenalty: 5,
+ minFunding: -0.05,
+ maxFunding: 0.05,
+ impactQuantity: 100,
+ groupInsuranceFund: true,
+ settleFeeFlat: 1000,
+ settleFeeAmountThreshold: 1000000,
+ settleFeeFractionLowHealth: 0.01,
+ settleTokenIndex: 0,
+ settlePnlLimitFactor: 1.0,
+ settlePnlLimitWindowSize: 60 * 60,
+ positivePnlLiquidationFee: 0,
+ holdupTime: 0,
+ platformLiquidationFee: 0,
+ })
+ const [formErrors, setFormErrors] = useState({})
+ const { handleSetInstructions } = useContext(NewProposalContext)
+ const forwarderProgramHelpers = useForwarderProgramHelpers()
+
+ const validateInstruction = async (): Promise => {
+ const { isValid, validationErrors } = await isFormValid(schema, form)
+ setFormErrors(validationErrors)
+ return isValid
+ }
+ async function getInstruction(): Promise {
+ const isValid = await validateInstruction()
+ let serializedInstruction = ''
+ let prerequisiteInstructions: TransactionInstruction[] = []
+ let prerequisiteInstructionsSigners: Keypair[] = []
+ if (
+ isValid &&
+ form.governedAccount?.governance?.account &&
+ wallet?.publicKey
+ ) {
+ const bids = new Keypair()
+ const asks = new Keypair()
+ const eventQueue = new Keypair()
+
+ const bookSideSize = mangoClient!.program.coder.accounts.size(
+ (mangoClient!.program.account.bookSide as any)._idlAccount
+ )
+ const eventQueueSize = mangoClient!.program.coder.accounts.size(
+ (mangoClient!.program.account.eventQueue as any)._idlAccount
+ )
+ prerequisiteInstructionsSigners = [bids, asks, eventQueue]
+ prerequisiteInstructions = [
+ SystemProgram.createAccount({
+ programId: mangoClient!.program.programId,
+ space: bookSideSize,
+ lamports: await connection.current.getMinimumBalanceForRentExemption(
+ bookSideSize
+ ),
+ fromPubkey: wallet.publicKey,
+ newAccountPubkey: bids.publicKey,
+ }),
+ SystemProgram.createAccount({
+ programId: mangoClient!.program.programId,
+ space: bookSideSize,
+ lamports: await connection.current.getMinimumBalanceForRentExemption(
+ bookSideSize
+ ),
+ fromPubkey: wallet.publicKey,
+ newAccountPubkey: asks.publicKey,
+ }),
+ SystemProgram.createAccount({
+ programId: mangoClient!.program.programId,
+ space: eventQueueSize,
+ lamports: await connection.current.getMinimumBalanceForRentExemption(
+ eventQueueSize
+ ),
+ fromPubkey: wallet.publicKey,
+ newAccountPubkey: eventQueue.publicKey,
+ }),
+ ]
+ const ix = await mangoClient!.program.methods
+ .perpCreateMarket(
+ Number(form.perpMarketIndex),
+ form.name,
+ {
+ confFilter: Number(form.oracleConfFilter),
+ maxStalenessSlots:
+ form.maxStalenessSlots !== ''
+ ? Number(form.maxStalenessSlots)
+ : null,
+ },
+ Number(form.baseDecimals),
+ new BN(form.quoteLotSize),
+ new BN(form.baseLotSize),
+ Number(form.maintBaseAssetWeight),
+ Number(form.initBaseAssetWeight),
+ Number(form.maintBaseLiabWeight),
+ Number(form.initBaseLiabWeight),
+ Number(form.maintOverallAssetWeight),
+ Number(form.initOverallAssetWeight),
+ Number(form.baseLiquidationFee),
+ Number(form.makerFee),
+ Number(form.takerFee),
+ Number(form.minFunding),
+ Number(form.maxFunding),
+ new BN(form.impactQuantity),
+ form.groupInsuranceFund,
+ Number(form.feePenalty),
+ Number(form.settleFeeFlat),
+ Number(form.settleFeeAmountThreshold),
+ Number(form.settleFeeFractionLowHealth),
+ Number(form.settleTokenIndex),
+ Number(form.settlePnlLimitFactor),
+ new BN(form.settlePnlLimitWindowSize),
+ Number(form.positivePnlLiquidationFee),
+ Number(form.platformLiquidationFee)
+ )
+ .accounts({
+ group: mangoGroup!.publicKey,
+ admin: form.governedAccount.extensions.transferAddress,
+ oracle: new PublicKey(form.oraclePk),
+ bids: bids.publicKey,
+ asks: asks.publicKey,
+ eventQueue: eventQueue.publicKey,
+ payer: form.governedAccount.extensions.transferAddress,
+ })
+ .signers([bids, asks, eventQueue])
+ .instruction()
+
+ serializedInstruction = serializeInstructionToBase64(
+ forwarderProgramHelpers.withForwarderWrapper(ix)
+ )
+ }
+ const obj: UiInstruction = {
+ prerequisiteInstructions: prerequisiteInstructions,
+ prerequisiteInstructionsSigners: prerequisiteInstructionsSigners,
+ serializedInstruction: serializedInstruction,
+ isValid,
+ chunkBy: 1,
+ governance: form.governedAccount?.governance,
+ customHoldUpTime: form.holdupTime,
+ }
+ return obj
+ }
+
+ useEffect(() => {
+ handleSetInstructions(
+ { governedAccount: form.governedAccount?.governance, getInstruction },
+ index
+ )
+ // 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
+ }, [
+ form,
+ forwarderProgramHelpers.form,
+ forwarderProgramHelpers.withForwarderWrapper,
+ ])
+ const schema = yup.object().shape({
+ governedAccount: yup
+ .object()
+ .nullable()
+ .required('Program governed account is required'),
+ name: yup.string().required(),
+ perpMarketIndex: yup.string().required(),
+ oraclePk: yup
+ .string()
+ .required()
+ .test('is-valid-address', 'Please enter a valid PublicKey', (value) =>
+ value ? validatePubkey(value) : true
+ ),
+ })
+
+ useEffect(() => {
+ const perpMarketIndex =
+ !mangoGroup || mangoGroup?.perpMarketsMapByMarketIndex.size === 0
+ ? 0
+ : Math.max(...[...mangoGroup!.perpMarketsMapByMarketIndex.keys()]) + 1
+ setForm((prevForm) => ({
+ ...prevForm,
+ perpMarketIndex: perpMarketIndex,
+ }))
+ }, [mangoGroup])
+
+ const inputs: InstructionInput[] = [
+ {
+ label: 'Governance',
+ initialValue: form.governedAccount,
+ name: 'governedAccount',
+ type: InstructionInputType.GOVERNED_ACCOUNT,
+ shouldBeGoverned: shouldBeGoverned as any,
+ governance: governance,
+ options: solAccounts,
+ },
+ {
+ label: 'Instruction hold up time (days)',
+ initialValue: form.holdupTime,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'holdupTime',
+ },
+ {
+ label: 'Perp Name',
+ initialValue: form.name,
+ type: InstructionInputType.INPUT,
+ name: 'name',
+ },
+ {
+ label: `Perp Market Index`,
+ initialValue: form.perpMarketIndex,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'perpMarketIndex',
+ },
+ {
+ label: 'Oracle PublicKey',
+ initialValue: form.oraclePk,
+ type: InstructionInputType.INPUT,
+ name: 'oraclePk',
+ },
+ {
+ label: `Oracle Confidence Filter`,
+ subtitle: getAdditionalLabelInfo('confFilter'),
+ initialValue: form.oracleConfFilter,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'oracleConfFilter',
+ },
+
+ {
+ label: `Max Staleness Slots`,
+ subtitle: getAdditionalLabelInfo('maxStalenessSlots'),
+ initialValue: form.maxStalenessSlots,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'maxStalenessSlots',
+ },
+ {
+ label: 'Base Decimals',
+ initialValue: form.baseDecimals,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'baseDecimals',
+ },
+ {
+ label: `Quote Lot Size`,
+ subtitle: getAdditionalLabelInfo('quoteLotSize'),
+ initialValue: form.quoteLotSize,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'quoteLotSize',
+ },
+ {
+ label: `Base Lot Size`,
+ subtitle: getAdditionalLabelInfo('baseLotSize'),
+ initialValue: form.baseLotSize,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'baseLotSize',
+ },
+ {
+ label: `Maintenance Base Asset Weight`,
+ subtitle: getAdditionalLabelInfo('maintBaseAssetWeight'),
+ initialValue: form.maintBaseAssetWeight,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'maintBaseAssetWeight',
+ },
+ {
+ label: `Init Base Asset Weight`,
+ subtitle: getAdditionalLabelInfo('initBaseAssetWeight'),
+ initialValue: form.initBaseAssetWeight,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'initBaseAssetWeight',
+ },
+ {
+ label: `Maintenance Base Liab Weight`,
+ subtitle: getAdditionalLabelInfo('maintBaseLiabWeight'),
+ initialValue: form.maintBaseLiabWeight,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'maintBaseLiabWeight',
+ },
+ {
+ label: `Init Base Liab Weight`,
+ subtitle: getAdditionalLabelInfo('initBaseLiabWeight'),
+ initialValue: form.initBaseLiabWeight,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'initBaseLiabWeight',
+ },
+ {
+ label: `Maint Overall Asset Weight`,
+ subtitle: getAdditionalLabelInfo('maintOverallAssetWeight'),
+ initialValue: form.maintOverallAssetWeight,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'maintOverallAssetWeight',
+ },
+ {
+ label: `Init Overall Asset Weight`,
+ subtitle: getAdditionalLabelInfo('initOverallAssetWeight'),
+ initialValue: form.initOverallAssetWeight,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'initOverallAssetWeight',
+ },
+ {
+ label: `Base Liquidation Fee`,
+ subtitle: getAdditionalLabelInfo('baseLiquidationFee'),
+ initialValue: form.baseLiquidationFee,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'baseLiquidationFee',
+ },
+ {
+ label: `Maker Fee`,
+ subtitle: getAdditionalLabelInfo('makerFee'),
+ initialValue: form.makerFee,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'makerFee',
+ },
+ {
+ label: `Taker Fee`,
+ subtitle: getAdditionalLabelInfo('takerFee'),
+ initialValue: form.takerFee,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'takerFee',
+ },
+ {
+ label: `Fee Penalty`,
+ subtitle: getAdditionalLabelInfo('feePenalty'),
+ initialValue: form.feePenalty,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'feePenalty',
+ },
+ {
+ label: `Group Insurance Fund`,
+ subtitle: getAdditionalLabelInfo('groupInsuranceFund'),
+ initialValue: form.groupInsuranceFund,
+ type: InstructionInputType.SWITCH,
+ name: 'groupInsuranceFund',
+ },
+ {
+ label: `Settle Fee Flat`,
+ subtitle: getAdditionalLabelInfo('settleFeeFlat'),
+ initialValue: form.settleFeeFlat,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'settleFeeFlat',
+ },
+ {
+ label: `Settle Fee Amount Threshold`,
+ subtitle: getAdditionalLabelInfo('settleFeeAmountThreshold'),
+ initialValue: form.settleFeeAmountThreshold,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'settleFeeAmountThreshold',
+ },
+ {
+ label: `Settle Fee Fraction Low Health`,
+ subtitle: getAdditionalLabelInfo('settleFeeFractionLowHealth'),
+ initialValue: form.settleFeeFractionLowHealth,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'settleFeeFractionLowHealth',
+ },
+ {
+ label: `Settle Token Index`,
+ subtitle: getAdditionalLabelInfo('settleTokenIndex'),
+ initialValue: form.settleTokenIndex,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'settleTokenIndex',
+ },
+ {
+ label: `Settle Pnl Limit Factor`,
+ subtitle: getAdditionalLabelInfo('settlePnlLimitFactor'),
+ initialValue: form.settlePnlLimitFactor,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'settlePnlLimitFactor',
+ },
+ {
+ label: `Settle Pnl Limit Window Size`,
+ subtitle: getAdditionalLabelInfo('settlePnlLimitWindowSize'),
+ initialValue: form.settlePnlLimitWindowSize,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'settlePnlLimitWindowSize',
+ },
+ {
+ label: `Min Funding`,
+ subtitle: getAdditionalLabelInfo('minFunding'),
+ initialValue: form.minFunding,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'minFunding',
+ },
+ {
+ label: `Max Funding`,
+ subtitle: getAdditionalLabelInfo('maxFunding'),
+ initialValue: form.maxFunding,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'maxFunding',
+ },
+ {
+ label: `Impact Quantity`,
+ subtitle: getAdditionalLabelInfo('impactQuantity'),
+ initialValue: form.impactQuantity,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'impactQuantity',
+ },
+ {
+ label: `Positive Pnl Liquidation Fee`,
+ subtitle: getAdditionalLabelInfo('positivePnlLiquidationFee'),
+ initialValue: form.positivePnlLiquidationFee,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'positivePnlLiquidationFee',
+ },
+ {
+ label: `Platform Liquidation Fee`,
+ subtitle: getAdditionalLabelInfo('platformLiquidationFee'),
+ initialValue: form.platformLiquidationFee,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'platformLiquidationFee',
+ },
+ ]
+ return (
+ <>
+
+ {form && (
+
+ )}
+
+ >
+ )
+}
+
+export default PerpCreate
diff --git a/pages/dao/[symbol]/proposal/components/instructions/Mango/MangoV4/PerpEdit.tsx b/pages/dao/[symbol]/proposal/components/instructions/Mango/MangoV4/PerpEdit.tsx
index dbab5d8230..cbfc2632e1 100644
--- a/pages/dao/[symbol]/proposal/components/instructions/Mango/MangoV4/PerpEdit.tsx
+++ b/pages/dao/[symbol]/proposal/components/instructions/Mango/MangoV4/PerpEdit.tsx
@@ -22,6 +22,8 @@ import useWalletOnePointOh from '@hooks/useWalletOnePointOh'
import ForwarderProgram, {
useForwarderProgramHelpers,
} from '@components/ForwarderProgram/ForwarderProgram'
+import ProgramSelector from '@components/Mango/ProgramSelector'
+import useProgramSelector from '@components/Mango/useProgramSelector'
const keyToLabel = {
oraclePk: 'Oracle',
@@ -144,7 +146,11 @@ const PerpEdit = ({
governance: ProgramAccount | null
}) => {
const wallet = useWalletOnePointOh()
- const { mangoClient, mangoGroup, getAdditionalLabelInfo } = UseMangoV4()
+ const programSelectorHook = useProgramSelector()
+ const { mangoClient, mangoGroup, getAdditionalLabelInfo } = UseMangoV4(
+ programSelectorHook.program?.val,
+ programSelectorHook.program?.group
+ )
const { assetAccounts } = useGovernanceAssets()
const [perps, setPerps] = useState([])
const [forcedValues, setForcedValues] = useState([])
@@ -305,7 +311,11 @@ const PerpEdit = ({
}, [mangoGroup])
useEffect(() => {
- if (form.perp && mangoGroup) {
+ if (
+ form.perp &&
+ mangoGroup &&
+ mangoGroup!.perpMarketsMapByMarketIndex.get(form.perp.value)
+ ) {
const currentPerp = mangoGroup!.perpMarketsMapByMarketIndex.get(
form.perp.value
)!
@@ -618,6 +628,9 @@ const PerpEdit = ({
]
return (
<>
+
{form && (
<>
| null
+}) => {
+ const wallet = useWalletOnePointOh()
+ const programSelectorHook = useProgramSelector()
+ const { mangoClient, mangoGroup, getAdditionalLabelInfo } = UseMangoV4(
+ programSelectorHook.program?.val,
+ programSelectorHook.program?.group
+ )
+ const { assetAccounts } = useGovernanceAssets()
+ const [perps, setPerps] = useState([])
+ const [forcedValues, setForcedValues] = useState([])
+ const forwarderProgramHelpers = useForwarderProgramHelpers()
+ const solAccounts = assetAccounts.filter(
+ (x) =>
+ x.type === AccountType.SOL &&
+ ((mangoGroup?.admin &&
+ x.extensions.transferAddress?.equals(mangoGroup.admin)) ||
+ (mangoGroup?.securityAdmin &&
+ x.extensions.transferAddress?.equals(mangoGroup.securityAdmin)))
+ )
+ const shouldBeGoverned = !!(index !== 0 && governance)
+ const [form, setForm] = useState({ ...defaultFormValues })
+ const [originalFormValues, setOriginalFormValues] = useState({
+ ...defaultFormValues,
+ })
+ const [formErrors, setFormErrors] = useState({})
+ const { handleSetInstructions } = useContext(NewProposalContext)
+
+ const validateInstruction = async (): Promise => {
+ const { isValid, validationErrors } = await isFormValid(schema, form)
+ setFormErrors(validationErrors)
+ return isValid
+ }
+ async function getInstruction(): Promise {
+ const isValid = await validateInstruction()
+ let serializedInstruction = ''
+ if (
+ isValid &&
+ form.governedAccount?.governance?.account &&
+ wallet?.publicKey
+ ) {
+ const perpMarket = mangoGroup!.perpMarketsMapByMarketIndex.get(
+ form.perp!.value
+ )!
+ const values = getChangedValues(
+ originalFormValues,
+ form,
+ forcedValues
+ )
+
+ const oracleConfFilter =
+ (form.oracleConfFilter as number | string) === ''
+ ? null
+ : form.oracleConfFilter
+ const maxStalenessSlots =
+ (form.maxStalenessSlots as number | string) === ''
+ ? null
+ : form.maxStalenessSlots
+
+ const isThereNeedOfSendingOracleConfig =
+ originalFormValues.oracleConfFilter !== oracleConfFilter ||
+ originalFormValues.maxStalenessSlots !== maxStalenessSlots
+ //Mango instruction call and serialize
+ const ix = await mangoClient!.program.methods
+ .perpEditMarket(
+ getNullOrTransform(values.oraclePk, PublicKey),
+ isThereNeedOfSendingOracleConfig
+ ? {
+ confFilter: Number(form.oracleConfFilter),
+ maxStalenessSlots: maxStalenessSlots,
+ }
+ : null,
+ getNullOrTransform(values.baseDecimals, null, Number),
+ getNullOrTransform(values.maintBaseAssetWeight, null, Number),
+ getNullOrTransform(values.initBaseAssetWeight, null, Number),
+ getNullOrTransform(values.maintBaseLiabWeight, null, Number),
+ getNullOrTransform(values.initBaseLiabWeight, null, Number),
+ getNullOrTransform(values.maintOverallAssetWeight, null, Number),
+ getNullOrTransform(values.initOverallAssetWeight, null, Number),
+ getNullOrTransform(values.baseLiquidationFee, null, Number),
+ getNullOrTransform(values.makerFee, null, Number),
+ getNullOrTransform(values.takerFee, null, Number),
+ getNullOrTransform(values.minFunding, null, Number),
+ getNullOrTransform(values.maxFunding, null, Number),
+ getNullOrTransform(values.impactQuantity, BN),
+ values.groupInsuranceFund!,
+ getNullOrTransform(values.feePenalty, null, Number),
+ getNullOrTransform(values.settleFeeFlat, null, Number),
+ getNullOrTransform(values.settleFeeAmountThreshold, null, Number),
+ getNullOrTransform(values.settleFeeFractionLowHealth, null, Number),
+ getNullOrTransform(
+ values.stablePriceDelayIntervalSeconds,
+ null,
+ Number
+ ),
+ getNullOrTransform(values.stablePriceDelayGrowthLimit, null, Number),
+ getNullOrTransform(values.stablePriceGrowthLimit, null, Number),
+ getNullOrTransform(values.settlePnlLimitFactor, null, Number),
+ getNullOrTransform(values.settlePnlLimitWindowSize, BN),
+ values.reduceOnly!,
+ values.resetStablePrice!,
+ getNullOrTransform(values.positivePnlLiquidationFee, null, Number),
+ getNullOrTransform(values.name, null, String),
+ values.forceClose!,
+ getNullOrTransform(values.platformLiquidationFee, null, Number)
+ )
+ .accounts({
+ group: mangoGroup!.publicKey,
+ admin: form.governedAccount.extensions.transferAddress,
+ perpMarket: perpMarket.publicKey,
+ oracle:
+ getNullOrTransform(values.oraclePk, PublicKey) || perpMarket.oracle,
+ })
+ .instruction()
+
+ serializedInstruction = serializeInstructionToBase64(
+ forwarderProgramHelpers.withForwarderWrapper(ix)
+ )
+ }
+ const obj: UiInstruction = {
+ serializedInstruction: serializedInstruction,
+ isValid,
+ chunkBy: 1,
+ governance: form.governedAccount?.governance,
+ customHoldUpTime: form.holdupTime,
+ }
+ return obj
+ }
+
+ useEffect(() => {
+ handleSetInstructions(
+ { governedAccount: form.governedAccount?.governance, getInstruction },
+ index
+ )
+ // 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
+ }, [
+ form,
+ forcedValues,
+ forwarderProgramHelpers.form,
+ forwarderProgramHelpers.withForwarderWrapper,
+ ])
+ const schema = yup.object().shape({
+ governedAccount: yup
+ .object()
+ .nullable()
+ .required('Program governed account is required'),
+ oraclePk: yup
+ .string()
+ .required()
+ .test('is-valid-address', 'Please enter a valid PublicKey', (value) =>
+ value ? validatePubkey(value) : true
+ ),
+ })
+ useEffect(() => {
+ const getTokens = async () => {
+ const currentTokens = [
+ ...mangoGroup!.perpMarketsMapByMarketIndex.values(),
+ ].map((x) => ({
+ name: x.name,
+ value: x.perpMarketIndex,
+ }))
+ setPerps(currentTokens)
+ }
+ if (mangoGroup) {
+ getTokens()
+ }
+ }, [mangoGroup])
+
+ useEffect(() => {
+ if (
+ form.perp &&
+ mangoGroup &&
+ mangoGroup!.perpMarketsMapByMarketIndex.get(form.perp.value)
+ ) {
+ const currentPerp = mangoGroup!.perpMarketsMapByMarketIndex.get(
+ form.perp.value
+ )!
+ const vals = {
+ oraclePk: currentPerp.oracle.toBase58(),
+ name: currentPerp.name,
+ oracleConfFilter: currentPerp.oracleConfig.confFilter.toNumber(),
+ maxStalenessSlots: currentPerp.oracleConfig.maxStalenessSlots.toNumber(),
+ baseDecimals: currentPerp.baseDecimals,
+ maintBaseAssetWeight: currentPerp.maintBaseAssetWeight.toNumber(),
+ initBaseAssetWeight: currentPerp.initBaseAssetWeight.toNumber(),
+ maintBaseLiabWeight: currentPerp.maintBaseLiabWeight.toNumber(),
+ initBaseLiabWeight: currentPerp.initBaseLiabWeight.toNumber(),
+ maintOverallAssetWeight: currentPerp.maintOverallAssetWeight.toNumber(),
+ initOverallAssetWeight: currentPerp.initOverallAssetWeight.toNumber(),
+ liquidationFee: currentPerp.baseLiquidationFee.toNumber(),
+ makerFee: currentPerp.makerFee.toNumber(),
+ takerFee: currentPerp.takerFee.toNumber(),
+ feePenalty: currentPerp.feePenalty,
+ minFunding: currentPerp.minFunding.toNumber(),
+ maxFunding: currentPerp.maxFunding.toNumber(),
+ impactQuantity: currentPerp.impactQuantity.toNumber(),
+ groupInsuranceFund: currentPerp.groupInsuranceFund,
+ settleFeeFlat: currentPerp.settleFeeFlat,
+ settleFeeAmountThreshold: currentPerp.settleFeeAmountThreshold,
+ settleFeeFractionLowHealth: currentPerp.settleFeeFractionLowHealth,
+ stablePriceDelayIntervalSeconds:
+ currentPerp.stablePriceModel.delayIntervalSeconds,
+ stablePriceDelayGrowthLimit:
+ currentPerp.stablePriceModel.delayGrowthLimit,
+ stablePriceGrowthLimit: currentPerp.stablePriceModel.stableGrowthLimit,
+ settlePnlLimitFactor: currentPerp.settlePnlLimitFactor,
+ settlePnlLimitWindowSize: currentPerp.settlePnlLimitWindowSizeTs.toNumber(),
+ reduceOnly: currentPerp.reduceOnly,
+ resetStablePrice: false,
+ forceClose: currentPerp.forceClose,
+ positivePnlLiquidationFee: currentPerp.positivePnlLiquidationFee.toNumber(),
+ }
+ setForm((prevForm) => ({
+ ...prevForm,
+ ...vals,
+ }))
+ setOriginalFormValues((prevForm) => ({ ...prevForm, ...vals }))
+ }
+ }, [form.perp, mangoGroup])
+
+ const inputs: InstructionInput[] = [
+ {
+ label: 'Governance',
+ initialValue: form.governedAccount,
+ name: 'governedAccount',
+ type: InstructionInputType.GOVERNED_ACCOUNT,
+ shouldBeGoverned: shouldBeGoverned as any,
+ governance: governance,
+ options: solAccounts,
+ },
+ {
+ label: 'Instruction hold up time (days)',
+ initialValue: form.holdupTime,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'holdupTime',
+ },
+ {
+ label: keyToLabel['perp'],
+ name: 'perp',
+ type: InstructionInputType.SELECT,
+ initialValue: form.perp,
+ options: perps,
+ },
+ {
+ label: keyToLabel['name'],
+ initialValue: form.name,
+ type: InstructionInputType.INPUT,
+ name: 'name',
+ },
+ {
+ label: keyToLabel['oraclePk'],
+ initialValue: form.oraclePk,
+ type: InstructionInputType.INPUT,
+ name: 'oraclePk',
+ },
+ {
+ label: keyToLabel['oracleConfFilter'],
+ subtitle: getAdditionalLabelInfo('confFilter'),
+ initialValue: form.oracleConfFilter,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'oracleConfFilter',
+ },
+ {
+ label: keyToLabel['maxStalenessSlots'],
+ subtitle: getAdditionalLabelInfo('maxStalenessSlots'),
+ initialValue: form.maxStalenessSlots,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'maxStalenessSlots',
+ },
+ {
+ label: keyToLabel['baseDecimals'],
+ initialValue: form.baseDecimals,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'baseDecimals',
+ },
+ {
+ label: keyToLabel['stablePriceDelayGrowthLimit'],
+ subtitle: getAdditionalLabelInfo('stablePriceDelayGrowthLimit'),
+ initialValue: form.stablePriceDelayGrowthLimit,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'stablePriceDelayGrowthLimit',
+ },
+ {
+ label: keyToLabel['stablePriceGrowthLimit'],
+ subtitle: getAdditionalLabelInfo('stablePriceGrowthLimit'),
+ initialValue: form.stablePriceGrowthLimit,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'stablePriceGrowthLimit',
+ },
+ {
+ label: keyToLabel['maintBaseAssetWeight'],
+ subtitle: getAdditionalLabelInfo('maintBaseAssetWeight'),
+ initialValue: form.maintBaseAssetWeight,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'maintBaseAssetWeight',
+ },
+ {
+ label: keyToLabel['initBaseAssetWeight'],
+ subtitle: getAdditionalLabelInfo('initBaseAssetWeight'),
+ initialValue: form.initBaseAssetWeight,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'initBaseAssetWeight',
+ },
+ {
+ label: keyToLabel['maintBaseLiabWeight'],
+ subtitle: getAdditionalLabelInfo('maintBaseLiabWeight'),
+ initialValue: form.maintBaseLiabWeight,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'maintBaseLiabWeight',
+ },
+ {
+ label: keyToLabel['initBaseLiabWeight'],
+ subtitle: getAdditionalLabelInfo('initBaseLiabWeight'),
+ initialValue: form.initBaseLiabWeight,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'initBaseLiabWeight',
+ },
+ {
+ label: keyToLabel['maintOverallAssetWeight'],
+ subtitle: getAdditionalLabelInfo('maintOverallAssetWeight'),
+ initialValue: form.maintOverallAssetWeight,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'maintOverallAssetWeight',
+ },
+ {
+ label: keyToLabel['initOverallAssetWeight'],
+ subtitle: getAdditionalLabelInfo('initOverallAssetWeight'),
+ initialValue: form.initOverallAssetWeight,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'initOverallAssetWeight',
+ },
+ {
+ label: keyToLabel['baseLiquidationFee'],
+ subtitle: getAdditionalLabelInfo('baseLiquidationFee'),
+ initialValue: form.baseLiquidationFee,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'baseLiquidationFee',
+ },
+ {
+ label: keyToLabel['makerFee'],
+ subtitle: getAdditionalLabelInfo('makerFee'),
+ initialValue: form.makerFee,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'makerFee',
+ },
+ {
+ label: keyToLabel['takerFee'],
+ subtitle: getAdditionalLabelInfo('takerFee'),
+ initialValue: form.takerFee,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'takerFee',
+ },
+ {
+ label: keyToLabel['feePenalty'],
+ subtitle: getAdditionalLabelInfo('feePenalty'),
+ initialValue: form.feePenalty,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'feePenalty',
+ },
+ {
+ label: keyToLabel['settleFeeFlat'],
+ subtitle: getAdditionalLabelInfo('settleFeeFlat'),
+ initialValue: form.settleFeeFlat,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'settleFeeFlat',
+ },
+ {
+ label: keyToLabel['settleFeeAmountThreshold'],
+ subtitle: getAdditionalLabelInfo('settleFeeAmountThreshold'),
+ initialValue: form.settleFeeAmountThreshold,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'settleFeeAmountThreshold',
+ },
+ {
+ label: keyToLabel['settleFeeFractionLowHealth'],
+ subtitle: getAdditionalLabelInfo('settleFeeFractionLowHealth'),
+ initialValue: form.settleFeeFractionLowHealth,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'settleFeeFractionLowHealth',
+ },
+ {
+ label: keyToLabel['stablePriceDelayIntervalSeconds'],
+ subtitle: getAdditionalLabelInfo('stablePriceDelayIntervalSeconds'),
+ initialValue: form.stablePriceDelayIntervalSeconds,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'stablePriceDelayIntervalSeconds',
+ },
+ {
+ label: keyToLabel['settlePnlLimitFactor'],
+ subtitle: getAdditionalLabelInfo('settlePnlLimitFactor'),
+ initialValue: form.settlePnlLimitFactor,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'settlePnlLimitFactor',
+ },
+ {
+ label: keyToLabel['settlePnlLimitWindowSize'],
+ subtitle: getAdditionalLabelInfo('settlePnlLimitWindowSize'),
+ initialValue: form.settlePnlLimitWindowSize,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'settlePnlLimitWindowSize',
+ },
+ {
+ label: keyToLabel['minFunding'],
+ subtitle: getAdditionalLabelInfo('minFunding'),
+ initialValue: form.minFunding,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'minFunding',
+ },
+ {
+ label: keyToLabel['maxFunding'],
+ subtitle: getAdditionalLabelInfo('maxFunding'),
+ initialValue: form.maxFunding,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'maxFunding',
+ },
+ {
+ label: keyToLabel['impactQuantity'],
+ subtitle: getAdditionalLabelInfo('impactQuantity'),
+ initialValue: form.impactQuantity,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'impactQuantity',
+ },
+ {
+ label: keyToLabel['positivePnlLiquidationFee'],
+ subtitle: getAdditionalLabelInfo('positivePnlLiquidationFee'),
+ initialValue: form.positivePnlLiquidationFee,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'positivePnlLiquidationFee',
+ },
+ {
+ label: keyToLabel['platformLiquidationFee'],
+ subtitle: getAdditionalLabelInfo('platformLiquidationFee'),
+ initialValue: form.platformLiquidationFee,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'platformLiquidationFee',
+ },
+ {
+ label: keyToLabel['groupInsuranceFund'],
+ subtitle: getAdditionalLabelInfo('groupInsuranceFund'),
+ initialValue: form.groupInsuranceFund,
+ type: InstructionInputType.SWITCH,
+ name: 'groupInsuranceFund',
+ },
+ {
+ label: keyToLabel['reduceOnly'],
+ subtitle: getAdditionalLabelInfo('reduceOnly'),
+ initialValue: form.reduceOnly,
+ type: InstructionInputType.SWITCH,
+ name: 'reduceOnly',
+ },
+ {
+ label: keyToLabel['resetStablePrice'],
+ subtitle: getAdditionalLabelInfo('resetStablePrice'),
+ initialValue: form.resetStablePrice,
+ type: InstructionInputType.SWITCH,
+ name: 'resetStablePrice',
+ },
+ {
+ label: keyToLabel['forceClose'],
+ subtitle: getAdditionalLabelInfo('forceClose'),
+ initialValue: form.forceClose,
+ type: InstructionInputType.SWITCH,
+ name: 'forceClose',
+ },
+ ]
+ return (
+ <>
+
+ {form && (
+ <>
+
+
+ Force values
+
+ {Object.keys(defaultFormValues)
+ .filter((x) => x !== 'governedAccount')
+ .filter((x) => x !== 'perp')
+ .filter((x) => x !== 'holdupTime')
+ .map((key) => (
+
+
{keyToLabel[key]}
+
+ x === key) ? true : false
+ }
+ onChange={(checked) => {
+ if (checked) {
+ setForcedValues([...forcedValues, key])
+ } else {
+ setForcedValues([
+ ...forcedValues.filter((x) => x !== key),
+ ])
+ }
+ }}
+ />
+
+
+ ))}
+
+
+
+ >
+ )}
+ >
+ )
+}
+
+export default PerpEdit
diff --git a/pages/dao/[symbol]/proposal/components/instructions/Mango/MangoV4/StubOracleCreate.tsx b/pages/dao/[symbol]/proposal/components/instructions/Mango/MangoV4/StubOracleCreate.tsx
index 87a757705e..dd779713c4 100644
--- a/pages/dao/[symbol]/proposal/components/instructions/Mango/MangoV4/StubOracleCreate.tsx
+++ b/pages/dao/[symbol]/proposal/components/instructions/Mango/MangoV4/StubOracleCreate.tsx
@@ -15,6 +15,8 @@ import { InstructionInputType } from '../../inputInstructionType'
import UseMangoV4 from '../../../../../../../../hooks/useMangoV4'
import { I80F48 } from '@blockworks-foundation/mango-v4'
import useWalletOnePointOh from '@hooks/useWalletOnePointOh'
+import ProgramSelector from '@components/Mango/ProgramSelector'
+import useProgramSelector from '@components/Mango/useProgramSelector'
interface StubOracleCreateForm {
governedAccount: AssetAccount | null
@@ -31,7 +33,11 @@ const StubOracleCreate = ({
governance: ProgramAccount | null
}) => {
const wallet = useWalletOnePointOh()
- const { mangoClient, mangoGroup } = UseMangoV4()
+ const programSelectorHook = useProgramSelector()
+ const { mangoClient, mangoGroup } = UseMangoV4(
+ programSelectorHook.program?.val,
+ programSelectorHook.program?.group
+ )
const { assetAccounts } = useGovernanceAssets()
const solAccounts = assetAccounts.filter(
(x) =>
@@ -139,6 +145,9 @@ const StubOracleCreate = ({
return (
<>
+
{form && (
| null
}) => {
const wallet = useWalletOnePointOh()
- const { mangoClient, mangoGroup } = UseMangoV4()
+ const programSelectorHook = useProgramSelector()
+ const { mangoClient, mangoGroup } = UseMangoV4(
+ programSelectorHook.program?.val,
+ programSelectorHook.program?.group
+ )
const { assetAccounts } = useGovernanceAssets()
const solAccounts = assetAccounts.filter(
(x) =>
@@ -136,6 +142,9 @@ const StubOracleSet = ({
return (
<>
+
{form && (
| null
}) => {
const wallet = useWalletOnePointOh()
- const { mangoGroup, mangoClient } = UseMangoV4()
+ const programSelectorHook = useProgramSelector()
+ const { mangoClient, mangoGroup } = UseMangoV4(
+ programSelectorHook.program?.val,
+ programSelectorHook.program?.group
+ )
const { assetAccounts } = useGovernanceAssets()
const solAccounts = assetAccounts.filter(
(x) =>
@@ -157,6 +163,9 @@ const TokenAddBank = ({
return (
<>
+
{form && (
| null
}) => {
const wallet = useWalletOnePointOh()
- const { mangoClient, mangoGroup, getAdditionalLabelInfo } = UseMangoV4()
+ const programSelectorHook = useProgramSelector()
+ const { mangoClient, mangoGroup, getAdditionalLabelInfo } = UseMangoV4(
+ programSelectorHook.program?.val,
+ programSelectorHook.program?.group
+ )
const { assetAccounts } = useGovernanceAssets()
- const connection = useLegacyConnectionContext()
const forwarderProgramHelpers = useForwarderProgramHelpers()
const solAccounts = assetAccounts.filter(
@@ -134,7 +136,6 @@ const TokenRegister = ({
async function getInstruction(): Promise {
const isValid = await validateInstruction()
let serializedInstruction = ''
- const additionalSerializedInstructions: string[] = []
if (
isValid &&
form.governedAccount?.governance?.account &&
@@ -193,27 +194,6 @@ const TokenRegister = ({
})
.instruction()
- const rp = new ReferralProvider(connection.current)
-
- const tx = await rp.initializeReferralTokenAccount({
- payerPubKey: form.governedAccount.extensions.transferAddress!,
- referralAccountPubKey: JUPITER_REFERRAL_PK,
- mint: new PublicKey(form.mintPk),
- })
- const isExistingAccount = await connection.current.getAccountInfo(
- tx.referralTokenAccountPubKey
- )
-
- if (!isExistingAccount) {
- additionalSerializedInstructions.push(
- ...tx.tx.instructions.map((x) =>
- serializeInstructionToBase64(
- forwarderProgramHelpers.withForwarderWrapper(x)
- )
- )
- )
- }
-
serializedInstruction = serializeInstructionToBase64(
forwarderProgramHelpers.withForwarderWrapper(ix)
)
@@ -563,6 +543,9 @@ const TokenRegister = ({
return (
<>
+
{form && (
| null
}) => {
const wallet = useWalletOnePointOh()
- const { mangoClient, mangoGroup } = UseMangoV4()
+ const programSelectorHook = useProgramSelector()
+ const { mangoClient, mangoGroup } = UseMangoV4(
+ programSelectorHook.program?.val,
+ programSelectorHook.program?.group
+ )
const { assetAccounts } = useGovernanceAssets()
const solAccounts = assetAccounts.filter(
(x) =>
@@ -49,7 +52,7 @@ const TokenRegisterTrustless = ({
x.extensions.transferAddress?.equals(mangoGroup?.admin)))
)
const forwarderProgramHelpers = useForwarderProgramHelpers()
- const connection = useLegacyConnectionContext()
+
const shouldBeGoverned = !!(index !== 0 && governance)
const [form, setForm] = useState({
governedAccount: null,
@@ -89,27 +92,6 @@ const TokenRegisterTrustless = ({
})
.instruction()
- const rp = new ReferralProvider(connection.current)
-
- const tx = await rp.initializeReferralTokenAccount({
- payerPubKey: form.governedAccount.extensions.transferAddress!,
- referralAccountPubKey: JUPITER_REFERRAL_PK,
- mint: new PublicKey(form.mintPk),
- })
- const isExistingAccount = await connection.current.getAccountInfo(
- tx.referralTokenAccountPubKey
- )
-
- if (!isExistingAccount) {
- additionalSerializedInstructions.push(
- ...tx.tx.instructions.map((x) =>
- serializeInstructionToBase64(
- forwarderProgramHelpers.withForwarderWrapper(x)
- )
- )
- )
- }
-
serializedInstruction = serializeInstructionToBase64(
forwarderProgramHelpers.withForwarderWrapper(ix)
)
@@ -213,6 +195,9 @@ const TokenRegisterTrustless = ({
return (
<>
+
{form && (
| null
+}) => {
+ const wallet = useWalletOnePointOh()
+ const programSelectorHook = useProgramSelector()
+ const { mangoClient, mangoGroup, getAdditionalLabelInfo } = UseMangoV4(
+ programSelectorHook.program?.val,
+ programSelectorHook.program?.group
+ )
+ const { assetAccounts } = useGovernanceAssets()
+ const forwarderProgramHelpers = useForwarderProgramHelpers()
+
+ const solAccounts = assetAccounts.filter(
+ (x) =>
+ x.type === AccountType.SOL &&
+ mangoGroup?.admin &&
+ x.extensions.transferAddress?.equals(mangoGroup?.admin)
+ )
+ const shouldBeGoverned = !!(index !== 0 && governance)
+ const [form, setForm] = useState({
+ governedAccount: null,
+ mintPk: '',
+ maxStalenessSlots: '',
+ oraclePk: '',
+ fallbackOracle: '',
+ oracleConfFilter: 0.1,
+ name: '',
+ adjustmentFactor: 0.004, // rate parameters are chosen to be the same for all high asset weight tokens,
+ util0: 0.7,
+ rate0: 0.1,
+ util1: 0.85,
+ rate1: 0.2,
+ maxRate: 2.0,
+ loanFeeRate: 0.005,
+ loanOriginationFeeRate: 0.0005,
+ maintAssetWeight: 1,
+ initAssetWeight: 1,
+ maintLiabWeight: 1,
+ initLiabWeight: 1,
+ liquidationFee: 0,
+ minVaultToDepositsRatio: 0.2,
+ netBorrowLimitWindowSizeTs: 24 * 60 * 60,
+ netBorrowLimitPerWindowQuote: toNative(1000000, 6).toNumber(),
+ tokenIndex: 0,
+ holdupTime: 0,
+ stablePriceDelayIntervalSeconds: 60 * 60,
+ stablePriceGrowthLimit: 0.0003,
+ stablePriceDelayGrowthLimit: 0.06,
+ tokenConditionalSwapTakerFeeRate: 0,
+ tokenConditionalSwapMakerFeeRate: 0,
+ flashLoanSwapFeeRate: 0,
+ reduceOnly: REDUCE_ONLY_OPTIONS[0],
+ borrowWeightScaleStartQuote: toNative(10000, 6).toNumber(),
+ depositWeightScaleStartQuote: toNative(10000, 6).toNumber(),
+ depositLimit: 0,
+ interestTargetUtilization: 0.5,
+ interestCurveScaling: 4,
+ insuranceFound: false,
+ zeroUtilRate: 0,
+ platformLiquidationFee: 0,
+ disableAssetLiquidation: false,
+ collateralFeePerDay: 0,
+ })
+ const [formErrors, setFormErrors] = useState({})
+ const { handleSetInstructions } = useContext(NewProposalContext)
+
+ const validateInstruction = async (): Promise => {
+ const { isValid, validationErrors } = await isFormValid(schema, form)
+ setFormErrors(validationErrors)
+ return isValid
+ }
+ async function getInstruction(): Promise {
+ const isValid = await validateInstruction()
+ let serializedInstruction = ''
+ if (
+ isValid &&
+ form.governedAccount?.governance?.account &&
+ wallet?.publicKey
+ ) {
+ const ix = await mangoClient!.program.methods
+ .tokenRegister(
+ Number(form.tokenIndex),
+ form.name,
+ {
+ confFilter: Number(form.oracleConfFilter),
+ maxStalenessSlots:
+ form.maxStalenessSlots !== ''
+ ? Number(form.maxStalenessSlots)
+ : null,
+ },
+ {
+ adjustmentFactor: Number(form.adjustmentFactor),
+ util0: Number(form.util0),
+ rate0: Number(form.rate0),
+ util1: Number(form.util1),
+ rate1: Number(form.rate1),
+ maxRate: Number(form.maxRate),
+ },
+ Number(form.loanFeeRate),
+ Number(form.loanOriginationFeeRate),
+ Number(form.maintAssetWeight),
+ Number(form.initAssetWeight),
+ Number(form.maintLiabWeight),
+ Number(form.initLiabWeight),
+ Number(form.liquidationFee),
+ Number(form.stablePriceDelayIntervalSeconds),
+ Number(form.stablePriceDelayGrowthLimit),
+ Number(form.stablePriceGrowthLimit),
+ Number(form.minVaultToDepositsRatio),
+ new BN(form.netBorrowLimitWindowSizeTs),
+ new BN(form.netBorrowLimitPerWindowQuote),
+ Number(form.borrowWeightScaleStartQuote),
+ Number(form.depositWeightScaleStartQuote),
+ Number(form.reduceOnly.value),
+ Number(form.tokenConditionalSwapTakerFeeRate),
+ Number(form.tokenConditionalSwapMakerFeeRate),
+ Number(form.flashLoanSwapFeeRate),
+ Number(form.interestCurveScaling),
+ Number(form.interestTargetUtilization),
+ form.insuranceFound,
+ new BN(form.depositLimit),
+ Number(form.zeroUtilRate),
+ Number(form.platformLiquidationFee),
+ form.disableAssetLiquidation,
+ Number(form.collateralFeePerDay)
+ )
+ .accounts({
+ group: mangoGroup!.publicKey,
+ admin: form.governedAccount.extensions.transferAddress,
+ mint: new PublicKey(form.mintPk),
+ oracle: new PublicKey(form.oraclePk),
+ payer: form.governedAccount.extensions.transferAddress,
+ rent: SYSVAR_RENT_PUBKEY,
+ fallbackOracle: new PublicKey(form.fallbackOracle),
+ })
+ .instruction()
+
+ serializedInstruction = serializeInstructionToBase64(
+ forwarderProgramHelpers.withForwarderWrapper(ix)
+ )
+ }
+ const obj: UiInstruction = {
+ serializedInstruction: serializedInstruction,
+ isValid,
+ chunkBy: 1,
+ governance: form.governedAccount?.governance,
+ customHoldUpTime: form.holdupTime,
+ }
+ return obj
+ }
+
+ useEffect(() => {
+ handleSetInstructions(
+ { governedAccount: form.governedAccount?.governance, getInstruction },
+ index
+ )
+ // 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
+ }, [
+ form,
+ forwarderProgramHelpers.form,
+ forwarderProgramHelpers.withForwarderWrapper,
+ ])
+ const schema = yup.object().shape({
+ governedAccount: yup
+ .object()
+ .nullable()
+ .required('Program governed account is required'),
+ oraclePk: yup
+ .string()
+ .required()
+ .test('is-valid-address', 'Please enter a valid PublicKey', (value) =>
+ value ? validatePubkey(value) : true
+ ),
+ mintPk: yup
+ .string()
+ .required()
+ .test('is-valid-address1', 'Please enter a valid PublicKey', (value) =>
+ value ? validatePubkey(value) : true
+ ),
+ name: yup.string().required(),
+ tokenIndex: yup.string().required(),
+ })
+ useEffect(() => {
+ const tokenIndex =
+ !mangoGroup || mangoGroup?.banksMapByTokenIndex.size === 0
+ ? 0
+ : Math.max(...[...mangoGroup!.banksMapByTokenIndex.keys()]) + 1
+ setForm({
+ ...form,
+ tokenIndex: tokenIndex,
+ })
+ }, [mangoGroup?.banksMapByTokenIndex.size])
+
+ const inputs: InstructionInput[] = [
+ {
+ label: 'Governance',
+ initialValue: form.governedAccount,
+ name: 'governedAccount',
+ type: InstructionInputType.GOVERNED_ACCOUNT,
+ shouldBeGoverned: shouldBeGoverned as any,
+ governance: governance,
+ options: solAccounts,
+ },
+ {
+ label: 'Instruction hold up time (days)',
+ initialValue: form.holdupTime,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'holdupTime',
+ },
+ {
+ label: 'Mint PublicKey',
+ initialValue: form.mintPk,
+ type: InstructionInputType.INPUT,
+ name: 'mintPk',
+ },
+ {
+ label: `Oracle PublicKey`,
+ initialValue: form.oraclePk,
+ type: InstructionInputType.INPUT,
+ name: 'oraclePk',
+ },
+ {
+ label: `Fallback oracle`,
+ initialValue: form.fallbackOracle,
+ type: InstructionInputType.INPUT,
+ name: 'fallbackOracle',
+ },
+ {
+ label: `Oracle Confidence Filter`,
+ subtitle: getAdditionalLabelInfo('confFilter'),
+ initialValue: form.oracleConfFilter,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'oracleConfFilter',
+ },
+ {
+ label: `Max Staleness Slots`,
+ subtitle: getAdditionalLabelInfo('maxStalenessSlots'),
+ initialValue: form.maxStalenessSlots,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'maxStalenessSlots',
+ },
+ {
+ label: 'Token Name',
+ initialValue: form.name,
+ type: InstructionInputType.INPUT,
+ name: 'name',
+ },
+ {
+ label: `Token Index`,
+ initialValue: form.tokenIndex,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'tokenIndex',
+ },
+ {
+ label: `Interest rate adjustment factor`,
+ subtitle: getAdditionalLabelInfo('adjustmentFactor'),
+ initialValue: form.adjustmentFactor,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'adjustmentFactor',
+ },
+ {
+ label: `Interest rate utilization point 0`,
+ subtitle: getAdditionalLabelInfo('util0'),
+ initialValue: form.util0,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'util0',
+ },
+ {
+ label: `Interest rate point 0`,
+ subtitle: getAdditionalLabelInfo('rate0'),
+ initialValue: form.rate0,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'rate0',
+ },
+ {
+ label: `Interest rate utilization point 1`,
+ subtitle: getAdditionalLabelInfo('util1'),
+ initialValue: form.util1,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'util1',
+ },
+ {
+ label: `Interest rate point 1`,
+ subtitle: getAdditionalLabelInfo('rate1'),
+ initialValue: form.rate1,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'rate1',
+ },
+ {
+ label: `Interest rate max rate`,
+ subtitle: getAdditionalLabelInfo('maxRate'),
+ initialValue: form.maxRate,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'maxRate',
+ },
+ {
+ label: `Loan Fee Rate`,
+ subtitle: getAdditionalLabelInfo('loanFeeRate'),
+ initialValue: form.loanFeeRate,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'loanFeeRate',
+ },
+ {
+ label: `Loan Origination Fee Rate`,
+ subtitle: getAdditionalLabelInfo('loanOriginationFeeRate'),
+ initialValue: form.loanOriginationFeeRate,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'loanOriginationFeeRate',
+ },
+ {
+ label: 'Maintenance Asset Weight',
+ subtitle: getAdditionalLabelInfo('maintAssetWeight'),
+ initialValue: form.maintAssetWeight,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'maintAssetWeight',
+ },
+ {
+ label: `Init Asset Weight`,
+ subtitle: getAdditionalLabelInfo('initAssetWeight'),
+ initialValue: form.initAssetWeight,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'initAssetWeight',
+ },
+ {
+ label: `Maintenance Liab Weight`,
+ subtitle: getAdditionalLabelInfo('maintLiabWeight'),
+ initialValue: form.maintLiabWeight,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'maintLiabWeight',
+ },
+ {
+ label: `Init Liab Weight`,
+ subtitle: getAdditionalLabelInfo('initLiabWeight'),
+ initialValue: form.initLiabWeight,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'initLiabWeight',
+ },
+ {
+ label: `Liquidation Fee`,
+ subtitle: getAdditionalLabelInfo('liquidationFee'),
+ initialValue: form.liquidationFee,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'liquidationFee',
+ },
+ {
+ label: `Min Vault To Deposits Ratio`,
+ subtitle: getAdditionalLabelInfo('minVaultToDepositsRatio'),
+ initialValue: form.minVaultToDepositsRatio,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'minVaultToDepositsRatio',
+ },
+ {
+ label: `Net Borrow Limit Window Size`,
+ subtitle: getAdditionalLabelInfo('netBorrowLimitWindowSizeTs'),
+ initialValue: form.netBorrowLimitWindowSizeTs,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'netBorrowLimitWindowSizeTs',
+ },
+ {
+ label: `Net Borrow Limit Per Window Quote`,
+ subtitle: getAdditionalLabelInfo('netBorrowLimitPerWindowQuote'),
+ initialValue: form.netBorrowLimitPerWindowQuote,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'netBorrowLimitPerWindowQuote',
+ },
+ {
+ label: 'Reduce only',
+ subtitle: getAdditionalLabelInfo('reduceOnly'),
+ initialValue: form.reduceOnly,
+ type: InstructionInputType.SELECT,
+ options: REDUCE_ONLY_OPTIONS,
+ name: 'reduceOnly',
+ },
+ {
+ label: `Stable Price Delay Interval Seconds`,
+ subtitle: getAdditionalLabelInfo('stablePriceDelayIntervalSeconds'),
+ initialValue: form.stablePriceDelayIntervalSeconds,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'stablePriceDelayIntervalSeconds',
+ },
+ {
+ label: `Stable Price Growth Limit`,
+ subtitle: getAdditionalLabelInfo('stablePriceGrowthLimit'),
+ initialValue: form.stablePriceGrowthLimit,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'stablePriceGrowthLimit',
+ },
+ {
+ label: `Stable Price Delay Growth Limit`,
+ subtitle: getAdditionalLabelInfo('stablePriceDelayGrowthLimit'),
+ initialValue: form.stablePriceDelayGrowthLimit,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'stablePriceDelayGrowthLimit',
+ },
+ {
+ label: `Token Conditional Swap Taker Fee Rate`,
+ subtitle: getAdditionalLabelInfo('tokenConditionalSwapTakerFeeRate'),
+ initialValue: form.tokenConditionalSwapTakerFeeRate,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'tokenConditionalSwapTakerFeeRate',
+ },
+ {
+ label: `Token Conditional Swap Maker Fee Rate`,
+ subtitle: getAdditionalLabelInfo('tokenConditionalSwapMakerFeeRate'),
+ initialValue: form.tokenConditionalSwapMakerFeeRate,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'tokenConditionalSwapMakerFeeRate',
+ },
+ {
+ label: `Flash Loan Deposit Fee Rate`,
+ subtitle: getAdditionalLabelInfo('flashLoanSwapFeeRate'),
+ initialValue: form.flashLoanSwapFeeRate,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'flashLoanSwapFeeRate',
+ },
+ {
+ label: `Borrow Weight Scale Start Quote`,
+ subtitle: getAdditionalLabelInfo('borrowWeightScaleStartQuote'),
+ initialValue: form.borrowWeightScaleStartQuote,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'borrowWeightScaleStartQuote',
+ },
+ {
+ label: `Deposit Weight Scale Start Quote`,
+ subtitle: getAdditionalLabelInfo('depositWeightScaleStartQuote'),
+ initialValue: form.depositWeightScaleStartQuote,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'depositWeightScaleStartQuote',
+ },
+ {
+ label: `Interest Curve Scaling`,
+ subtitle: getAdditionalLabelInfo('interestCurveScaling'),
+ initialValue: form.interestCurveScaling,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'interestCurveScaling',
+ },
+ {
+ label: `Interest Target Utilization`,
+ subtitle: getAdditionalLabelInfo('interestTargetUtilization'),
+ initialValue: form.interestTargetUtilization,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'interestTargetUtilization',
+ },
+ {
+ label: `Deposit Limit`,
+ subtitle: getAdditionalLabelInfo('depositLimit'),
+ initialValue: form.depositLimit,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'depositLimit',
+ },
+ {
+ label: `Insurance Found`,
+ subtitle: getAdditionalLabelInfo('insuranceFound'),
+ initialValue: form.insuranceFound,
+ type: InstructionInputType.SWITCH,
+ name: 'insuranceFound',
+ },
+ {
+ label: 'Zero Util Rate',
+ subtitle: getAdditionalLabelInfo('zeroUtilRate'),
+ initialValue: form.zeroUtilRate,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'zeroUtilRate',
+ },
+ {
+ label: 'Platform Liquidation Fee',
+ subtitle: getAdditionalLabelInfo('platformLiquidationFee'),
+ initialValue: form.platformLiquidationFee,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'platformLiquidationFee',
+ },
+ {
+ label: 'Disable Asset Liquidation',
+ subtitle: getAdditionalLabelInfo('disableAssetLiquidation'),
+ initialValue: form.disableAssetLiquidation,
+ type: InstructionInputType.SWITCH,
+ name: 'disableAssetLiquidation',
+ },
+ {
+ label: 'Collateral Fee Per Day',
+ subtitle: getAdditionalLabelInfo('collateralFeePerDay'),
+ initialValue: form.collateralFeePerDay,
+ type: InstructionInputType.INPUT,
+ inputType: 'number',
+ name: 'collateralFeePerDay',
+ },
+ ]
+
+ return (
+ <>
+
+ {form && (
+
+ )}
+
+ >
+ )
+}
+
+export default TokenRegister
diff --git a/pages/dao/[symbol]/proposal/components/instructions/Mango/MangoV4/WithdrawPerpFees.tsx b/pages/dao/[symbol]/proposal/components/instructions/Mango/MangoV4/WithdrawPerpFees.tsx
index c13bbd6572..bdf66ab0d4 100644
--- a/pages/dao/[symbol]/proposal/components/instructions/Mango/MangoV4/WithdrawPerpFees.tsx
+++ b/pages/dao/[symbol]/proposal/components/instructions/Mango/MangoV4/WithdrawPerpFees.tsx
@@ -21,6 +21,8 @@ import {
import { TransactionInstruction } from '@solana/web3.js'
import { useConnection } from '@solana/wallet-adapter-react'
import { PerpMarketIndex } from '@blockworks-foundation/mango-v4'
+import ProgramSelector from '@components/Mango/ProgramSelector'
+import useProgramSelector from '@components/Mango/useProgramSelector'
type NameMarketIndexVal = {
name: string
@@ -41,7 +43,11 @@ const WithdrawPerpFees = ({
governance: ProgramAccount | null
}) => {
const wallet = useWalletOnePointOh()
- const { mangoClient, mangoGroup } = UseMangoV4()
+ const programSelectorHook = useProgramSelector()
+ const { mangoClient, mangoGroup } = UseMangoV4(
+ programSelectorHook.program?.val,
+ programSelectorHook.program?.group
+ )
const { assetAccounts } = useGovernanceAssets()
const { connection } = useConnection()
const solAccounts = assetAccounts.filter(
@@ -185,6 +191,9 @@ const WithdrawPerpFees = ({
return (
<>
+
{form && (
| null
}) => {
const wallet = useWalletOnePointOh()
- const { mangoClient, mangoGroup } = UseMangoV4()
+ const programSelectorHook = useProgramSelector()
+ const { mangoClient, mangoGroup } = UseMangoV4(
+ programSelectorHook.program?.val,
+ programSelectorHook.program?.group
+ )
const { assetAccounts } = useGovernanceAssets()
const { connection } = useConnection()
const solAccounts = assetAccounts.filter(
@@ -56,6 +63,7 @@ const AdminTokenWithdrawTokenFees = ({
governedAccount: null,
token: null,
holdupTime: 0,
+ withdrawFromAllBanks: false,
})
const [formErrors, setFormErrors] = useState({})
const { handleSetInstructions } = useContext(NewProposalContext)
@@ -75,60 +83,64 @@ const AdminTokenWithdrawTokenFees = ({
form.governedAccount?.governance?.account &&
wallet?.publicKey
) {
- const bank = mangoGroup!.banksMapByMint.get(
- form.token!.value.toBase58()
- )![0]
- const ataAddress = await Token.getAssociatedTokenAddress(
- ASSOCIATED_TOKEN_PROGRAM_ID,
- TOKEN_PROGRAM_ID,
- bank.mint,
- form.governedAccount.extensions.transferAddress!,
- true
- )
+ const banks = form.withdrawFromAllBanks
+ ? [...mangoGroup!.banksMapByMint.values()].map((x) => x[0])
+ : [mangoGroup!.banksMapByMint.get(form.token!.value.toBase58())![0]]
- const depositAccountInfo = await connection.getAccountInfo(ataAddress)
- if (!depositAccountInfo) {
- // generate the instruction for creating the ATA
- prerequisiteInstructions.push(
- Token.createAssociatedTokenAccountInstruction(
- ASSOCIATED_TOKEN_PROGRAM_ID,
- TOKEN_PROGRAM_ID,
- bank.mint,
- ataAddress,
- form.governedAccount.extensions.transferAddress!,
- wallet.publicKey
- )
+ for (const bank of banks) {
+ const ataAddress = await Token.getAssociatedTokenAddress(
+ ASSOCIATED_TOKEN_PROGRAM_ID,
+ TOKEN_PROGRAM_ID,
+ bank.mint,
+ form.governedAccount.extensions.transferAddress!,
+ true
)
- }
- const ix = await mangoClient!.program.methods
- .adminTokenWithdrawFees()
- .accounts({
- group: mangoGroup!.publicKey,
- admin: form.governedAccount.extensions.transferAddress,
- tokenProgram: TOKEN_PROGRAM_ID,
- bank: bank.publicKey,
- vault: bank.vault,
- tokenAccount: ataAddress,
- })
- .instruction()
-
- additionalSerializedInstructions.push(serializeInstructionToBase64(ix))
-
- if (bank.mint.toBase58() === WSOL_MINT) {
- additionalSerializedInstructions.push(
- serializeInstructionToBase64(
- Token.createCloseAccountInstruction(
+ const depositAccountInfo = await connection.getAccountInfo(ataAddress)
+ if (!depositAccountInfo) {
+ // generate the instruction for creating the ATA
+ prerequisiteInstructions.push(
+ Token.createAssociatedTokenAccountInstruction(
+ ASSOCIATED_TOKEN_PROGRAM_ID,
TOKEN_PROGRAM_ID,
+ bank.mint,
ataAddress,
form.governedAccount.extensions.transferAddress!,
- form.governedAccount.extensions.transferAddress!,
- []
+ wallet.publicKey
)
)
- )
+ }
+
+ const ix = await mangoClient!.program.methods
+ .adminTokenWithdrawFees()
+ .accounts({
+ group: mangoGroup!.publicKey,
+ admin: form.governedAccount.extensions.transferAddress,
+ tokenProgram: TOKEN_PROGRAM_ID,
+ bank: bank.publicKey,
+ vault: bank.vault,
+ tokenAccount: ataAddress,
+ })
+ .instruction()
+
+ additionalSerializedInstructions.push(serializeInstructionToBase64(ix))
+
+ if (bank.mint.toBase58() === WSOL_MINT) {
+ additionalSerializedInstructions.push(
+ serializeInstructionToBase64(
+ Token.createCloseAccountInstruction(
+ TOKEN_PROGRAM_ID,
+ ataAddress,
+ form.governedAccount.extensions.transferAddress!,
+ form.governedAccount.extensions.transferAddress!,
+ []
+ )
+ )
+ )
+ }
}
}
+
const obj: UiInstruction = {
prerequisiteInstructions,
serializedInstruction: serializedInstruction,
@@ -136,6 +148,7 @@ const AdminTokenWithdrawTokenFees = ({
isValid,
governance: form.governedAccount?.governance,
customHoldUpTime: form.holdupTime,
+ chunkBy: 2,
}
return obj
}
@@ -192,10 +205,19 @@ const AdminTokenWithdrawTokenFees = ({
inputType: 'number',
name: 'holdupTime',
},
+ {
+ label: 'Withdraw from all banks',
+ initialValue: form.withdrawFromAllBanks,
+ type: InstructionInputType.SWITCH,
+ name: 'withdrawFromAllBanks',
+ },
]
return (
<>
+
{form && (
{
+ const { result: realm } = await fetchRealmByPubkey(connection, realmPk)
+ if (realm === undefined) {
+ throw new Error('Realm not found')
+ }
+
+} */
-const DualVote = ({
+const DaoVote = ({
index,
governance,
}: {
index: number
governance: ProgramAccount | null
}) => {
- const [form, setForm] = useState({
- realm: 'EGYbpow8V9gt8JFmadFYai4sjfwc7Vc9gazU735hE6u7',
- governanceProgram: 'GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw',
+ const [form, setForm] = useState({
proposal: '',
voteOption: 'Yes',
delegateToken: undefined,
@@ -61,9 +74,6 @@ const DualVote = ({
const wallet = useWalletOnePointOh()
const shouldBeGoverned = !!(index !== 0 && governance)
const { assetAccounts } = useGovernanceAssets()
- const [governedAccount, setGovernedAccount] = useState<
- ProgramAccount | undefined
- >(undefined)
const [formErrors, setFormErrors] = useState({})
const { handleSetInstructions } = useContext(NewProposalContext)
const handleSetForm = ({ propertyName, value }) => {
@@ -89,6 +99,15 @@ const DualVote = ({
return isValid
}, [form, schema])
+ /*
+ const parsedProposalPk = tryParsePublicKey(form.proposal)
+ const {
+ data: proposalData,
+ isLoading: proposalLoading,
+ } = useProposalByPubkeyQuery(parsedProposalPk)
+*/
+ // TODO preview proposal title!
+
useEffect(() => {
async function getInstruction(): Promise {
const isValid = await validateInstruction()
@@ -100,16 +119,39 @@ const DualVote = ({
form.delegateToken?.governance?.account &&
wallet?.publicKey
) {
- const DUAL_MINT = new PublicKey(
- 'DUALa4FC2yREwZ59PHeu1un4wis36vHRv5hWVBmzykCJ'
+ const proposalPk = new PublicKey(form.proposal)
+
+ const { result: proposal } = await fetchProposalByPubkeyQuery(
+ connection.current,
+ proposalPk
+ )
+ if (proposal === undefined) {
+ throw new Error('Proposal not found')
+ }
+ const { result: proposalGovernance } = await fetchGovernanceByPubkey(
+ connection.current,
+ proposal.account.governance
+ )
+ if (proposalGovernance === undefined) {
+ throw new Error('Governance not found')
+ }
+ const realmPk = proposalGovernance.account.realm
+ const { result: realm } = await fetchRealmByPubkey(
+ connection.current,
+ realmPk
)
- const programId = new PublicKey(form.governanceProgram)
+ if (realm === undefined) {
+ throw new Error('Realm not found')
+ }
+ const governingMint = proposal.account.governingTokenMint
+
+ const programId = proposal.owner
const walletPk = form.delegateToken.governance.nativeTreasuryAddress
const payer = form.delegateToken.governance.nativeTreasuryAddress
const tokenOwnerRecord = await getTokenOwnerRecordAddress(
programId,
- new PublicKey(form.realm),
- DUAL_MINT,
+ realmPk,
+ governingMint,
walletPk
)
@@ -119,41 +161,53 @@ const DualVote = ({
new EmptyWallet(Keypair.generate()),
options
)
- const proposal = await getProposal(
- connection.current,
- new PublicKey(form.proposal)
- )
- const vsrClient = await VsrClient.connect(provider, DEFAULT_VSR_ID)
- // Explicitly request the version before making RPC calls to work around race conditions in resolving
- // the version for RealmInfo
- const programVersion = await fetchProgramVersion(
+
+ const { result: realmConfig } = await fetchRealmConfigQuery(
connection.current,
- programId
+ realmPk
)
+ const votingPop =
+ governingMint.toString() === realm.account.communityMint.toString()
+ ? 'community'
+ : 'council'
+ const pluginPk =
+ votingPop === 'community'
+ ? realmConfig?.account.communityTokenConfig.voterWeightAddin
+ : realmConfig?.account.councilTokenConfig.voterWeightAddin
+ const pluginName = findPluginName(pluginPk)
- const { registrar } = await getRegistrarPDA(
- new PublicKey(form.realm),
- DUAL_MINT,
- DEFAULT_VSR_ID
- )
- const { voter } = await getVoterPDA(registrar, walletPk, DEFAULT_VSR_ID)
- const { voterWeightPk } = await getVoterWeightPDA(
- registrar,
- walletPk,
- DEFAULT_VSR_ID
- )
+ // TODO this needs to just make a VotingClient and use it, for any plugin.
+ // But that code doesn't exist because right now everything is done in stupid hook.
+ // So currently only [vanilla and] VSR is supported
+ let voterWeightPk: PublicKey | undefined = undefined
+ if (pluginName === 'VSR') {
+ if (pluginPk === undefined) throw new Error('should be impossible')
+ const vsrClient = await VsrClient.connect(provider, pluginPk)
+ // Explicitly request the version before making RPC calls to work around race conditions in resolving
+ // the version for RealmInfo
- const updateVoterWeightRecordIx = await vsrClient!.program.methods
- .updateVoterWeightRecord()
- .accounts({
- registrar,
- voter,
- voterWeightRecord: voterWeightPk,
- systemProgram: SYSTEM_PROGRAM_ID,
- })
- .instruction()
+ const { registrar } = await getRegistrarPDA(
+ realmPk,
+ governingMint,
+ pluginPk
+ )
+ const { voter } = await getVoterPDA(registrar, walletPk, pluginPk)
+ voterWeightPk = (
+ await getVoterWeightPDA(registrar, walletPk, pluginPk)
+ ).voterWeightPk
- instructions.push(updateVoterWeightRecordIx)
+ const updateVoterWeightRecordIx = await vsrClient.program.methods
+ .updateVoterWeightRecord()
+ .accounts({
+ registrar,
+ voter,
+ voterWeightRecord: voterWeightPk,
+ systemProgram: SYSTEM_PROGRAM_ID,
+ })
+ .instruction()
+
+ instructions.push(updateVoterWeightRecordIx)
+ }
const vote =
form.voteOption === 'Yes'
@@ -172,13 +226,18 @@ const DualVote = ({
veto: undefined,
})
- const tokenMint = DUAL_MINT
+ const tokenMint = governingMint
+
+ const programVersion = await fetchProgramVersion(
+ connection.current,
+ programId
+ )
await withCastVote(
instructions,
programId,
programVersion,
- new PublicKey(form.realm),
+ realmPk,
proposal.account.governance,
proposal.pubkey,
proposal.account.tokenOwnerRecord,
@@ -205,12 +264,11 @@ const DualVote = ({
return obj
}
handleSetInstructions(
- { governedAccount: governedAccount, getInstruction },
+ { governedAccount: form.delegateToken?.governance, getInstruction },
index
)
}, [
form,
- governedAccount,
handleSetInstructions,
index,
connection,
@@ -218,26 +276,10 @@ const DualVote = ({
validateInstruction,
])
- useEffect(() => {
- setGovernedAccount(form.delegateToken?.governance)
- }, [form.delegateToken])
-
// TODO: Include this in the config instruction which can optionally be done
// if the project doesnt need to change where the tokens get returned to.
return (
<>
-
- handleSetForm({
- value: evt.target.value,
- propertyName: 'realm',
- })
- }
- error={formErrors['realm']}
- />
{
[Instructions.Base64]: CustomBase64,
[Instructions.None]: Empty,
[Instructions.MangoV4TokenRegister]: TokenRegister,
+ [Instructions.MangoV4TokenRegisterV23]: TokenRegisterV23,
[Instructions.MangoV4TokenEdit]: EditToken,
+ [Instructions.MangoV4TokenEditV23]: EditTokenV23,
[Instructions.MangoV4GroupEdit]: GroupEdit,
+ [Instructions.MangoV4GroupEditV23]: GroupEditV23,
[Instructions.MangoV4AdminWithdrawTokenFees]: AdminTokenWithdrawFees,
[Instructions.MangoV4WithdrawPerpFees]: WithdrawPerpFees,
[Instructions.IdlSetBuffer]: IdlSetBuffer,
[Instructions.MangoV4OpenBookEditMarket]: OpenBookEditMarket,
[Instructions.MangoV4IxGateSet]: IxGateSet,
+ [Instructions.MangoV4IxGateSetV23]: IxGateSetV23,
[Instructions.MangoV4AltExtend]: AltExtend,
[Instructions.MangoV4AltSet]: AltSet,
[Instructions.MangoV4StubOracleCreate]: StubOracleCreate,
[Instructions.MangoV4StubOracleSet]: StubOracleSet,
[Instructions.MangoV4PerpEdit]: PerpEdit,
+ [Instructions.MangoV4PerpEditV23]: PerpEditV23,
[Instructions.MangoV4OpenBookRegisterMarket]: OpenBookRegisterMarket,
[Instructions.MangoV4PerpCreate]: PerpCreate,
+ [Instructions.MangoV4PerpCreateV23]: PerpCreateV23,
[Instructions.MangoV4TokenRegisterTrustless]: TokenRegisterTrustless,
[Instructions.MangoV4TokenAddBank]: TokenAddBank,
[Instructions.Grant]: Grant,
@@ -494,7 +506,7 @@ const New = () => {
[Instructions.DualFinanceDelegate]: DualDelegate,
[Instructions.DualFinanceDelegateWithdraw]: DualVoteDepositWithdraw,
[Instructions.DualFinanceVoteDeposit]: DualVoteDeposit,
- [Instructions.DualFinanceVote]: DualVote,
+ [Instructions.DaoVote]: DaoVote,
[Instructions.DistributionCloseVaults]: CloseVaults,
[Instructions.DistributionFillVaults]: FillVaults,
[Instructions.MeanCreateAccount]: MeanCreateAccount,
diff --git a/pages/realms/index.tsx b/pages/realms/index.tsx
index 5f51d6da93..246d513594 100644
--- a/pages/realms/index.tsx
+++ b/pages/realms/index.tsx
@@ -12,7 +12,6 @@ import Button from '@components/Button'
import { notify } from '@utils/notifications'
import { useRouter } from 'next/router'
import Input from '@components/inputs/Input'
-import dynamic from 'next/dynamic'
import { BsLayoutWtf, BsCheck } from 'react-icons/bs'
import useWalletOnePointOh from '@hooks/useWalletOnePointOh'
@@ -20,8 +19,7 @@ import { PublicKey } from '@solana/web3.js'
import { DEFAULT_GOVERNANCE_PROGRAM_ID } from '@components/instructions/tools'
import { useRealmsByProgramQuery } from '@hooks/queries/realm'
import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext'
-
-const RealmsDashboard = dynamic(() => import('./components/RealmsDashboard'))
+import RealmsDashboard from './components/RealmsDashboard'
const Realms = () => {
const [realms, setRealms] = useState>([])
diff --git a/pages/realms/new/community-token/index.tsx b/pages/realms/new/community-token/index.tsx
index fce23256e7..06b23dc2bb 100644
--- a/pages/realms/new/community-token/index.tsx
+++ b/pages/realms/new/community-token/index.tsx
@@ -72,7 +72,11 @@ const transformFormData2RealmCreation = (formData: CommunityTokenForm) => {
formData.transferCommunityMintAuthority ?? true,
// COUNCIL INFO
createCouncil: formData.addCouncil ?? false,
-
+ communityTokenConfig: new GoverningTokenConfigAccountArgs({
+ tokenType: GoverningTokenType.Liquid,
+ voterWeightAddin: undefined,
+ maxVoterWeightAddin: undefined,
+ }),
existingCouncilMintPk: formData.councilTokenMintAddress
? new PublicKey(formData.councilTokenMintAddress)
: undefined,
diff --git a/public/realms/BOHlogo.png b/public/realms/BOHlogo.png
new file mode 100644
index 0000000000..f8feb8f741
Binary files /dev/null and b/public/realms/BOHlogo.png differ
diff --git a/public/realms/Blockride/banner.png b/public/realms/Blockride/banner.png
new file mode 100644
index 0000000000..ec8b2ba0f0
Binary files /dev/null and b/public/realms/Blockride/banner.png differ
diff --git a/public/realms/Blockride/logo.png b/public/realms/Blockride/logo.png
new file mode 100644
index 0000000000..01e6e1e45c
Binary files /dev/null and b/public/realms/Blockride/logo.png differ
diff --git a/public/realms/BoH b/public/realms/BoH
new file mode 100644
index 0000000000..8b13789179
--- /dev/null
+++ b/public/realms/BoH
@@ -0,0 +1 @@
+
diff --git a/public/realms/ConkDao/conk.png b/public/realms/ConkDao/conk.png
new file mode 100644
index 0000000000..4c1826f43d
Binary files /dev/null and b/public/realms/ConkDao/conk.png differ
diff --git a/public/realms/ConkDao/conk_banner.png b/public/realms/ConkDao/conk_banner.png
new file mode 100644
index 0000000000..d619846d4d
Binary files /dev/null and b/public/realms/ConkDao/conk_banner.png differ
diff --git a/public/realms/Deans-List-Solarplex-State/img/banner-deanslist-solarplex.png b/public/realms/Deans-List-Solarplex-State/img/banner-deanslist-solarplex.png
new file mode 100644
index 0000000000..e5ed9605e6
Binary files /dev/null and b/public/realms/Deans-List-Solarplex-State/img/banner-deanslist-solarplex.png differ
diff --git a/public/realms/Deans-List-Solarplex-State/img/deans_list_solarplex_state.png b/public/realms/Deans-List-Solarplex-State/img/deans_list_solarplex_state.png
new file mode 100644
index 0000000000..077ad4c1a3
Binary files /dev/null and b/public/realms/Deans-List-Solarplex-State/img/deans_list_solarplex_state.png differ
diff --git a/public/realms/GARI Network DAO/Gari discord (1).png b/public/realms/GARI Network DAO/Gari discord (1).png
new file mode 100644
index 0000000000..4815d5da54
Binary files /dev/null and b/public/realms/GARI Network DAO/Gari discord (1).png differ
diff --git a/public/realms/GARI Network DAO/gari.png b/public/realms/GARI Network DAO/gari.png
new file mode 100644
index 0000000000..b6d30aa4e7
Binary files /dev/null and b/public/realms/GARI Network DAO/gari.png differ
diff --git a/public/realms/MOUTAI/MF.png b/public/realms/MOUTAI/MF.png
new file mode 100644
index 0000000000..ecf72c620c
Binary files /dev/null and b/public/realms/MOUTAI/MF.png differ
diff --git a/public/realms/MOUTAI/mdao.jpg b/public/realms/MOUTAI/mdao.jpg
new file mode 100644
index 0000000000..adc3c21104
Binary files /dev/null and b/public/realms/MOUTAI/mdao.jpg differ
diff --git a/public/realms/MOUTAI/t b/public/realms/MOUTAI/t
new file mode 100644
index 0000000000..8b13789179
--- /dev/null
+++ b/public/realms/MOUTAI/t
@@ -0,0 +1 @@
+
diff --git a/public/realms/MemeCoinDAOai/MemeCoinDAOBanner1_15.png b/public/realms/MemeCoinDAOai/MemeCoinDAOBanner1_15.png
new file mode 100644
index 0000000000..c269797d18
Binary files /dev/null and b/public/realms/MemeCoinDAOai/MemeCoinDAOBanner1_15.png differ
diff --git a/public/realms/MemeCoinDAOai/MemeCoinDAOFinalLogo.png b/public/realms/MemeCoinDAOai/MemeCoinDAOFinalLogo.png
new file mode 100644
index 0000000000..8e1ff1b54d
Binary files /dev/null and b/public/realms/MemeCoinDAOai/MemeCoinDAOFinalLogo.png differ
diff --git a/public/realms/PAWN/img/pawn.png b/public/realms/PAWN/img/pawn.png
new file mode 100644
index 0000000000..b3815c90f7
Binary files /dev/null and b/public/realms/PAWN/img/pawn.png differ
diff --git a/public/realms/PAWN/img/pawns-banner.png b/public/realms/PAWN/img/pawns-banner.png
new file mode 100644
index 0000000000..9a19f8ba8b
Binary files /dev/null and b/public/realms/PAWN/img/pawns-banner.png differ
diff --git a/public/realms/Solsaur/solsaur-realms-banner.png b/public/realms/Solsaur/solsaur-realms-banner.png
new file mode 100644
index 0000000000..a6f7b7f3e8
Binary files /dev/null and b/public/realms/Solsaur/solsaur-realms-banner.png differ
diff --git a/public/realms/Solsaur/solsaur.png b/public/realms/Solsaur/solsaur.png
new file mode 100644
index 0000000000..1b74053e51
Binary files /dev/null and b/public/realms/Solsaur/solsaur.png differ
diff --git a/public/realms/devnet.json b/public/realms/devnet.json
index cf00d616e5..98dde2e720 100644
--- a/public/realms/devnet.json
+++ b/public/realms/devnet.json
@@ -254,5 +254,20 @@
"website": "https://helium.com",
"twitter": "@Helium",
"ogImage": "/realms/Helium/img/mobilelogo.png"
+ },
+ {
+ "symbol": "$GARI",
+ "displayName": "GARI Network DAO",
+ "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw",
+ "realmId": "HvDndGYjZNMVQDsrdAJJR7DtnQSB5rXM9BJBdwuxiXDg",
+ "ogImage": "/realms/GARI Network DAO/Coin.png",
+ "website": "https://gari.network/",
+ "twitter": "@TheGariNetwork"
+ },
+ {
+ "symbol": "agrippa",
+ "displayName": "agrippa test dao",
+ "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw",
+ "realmId": "4tvK4JBdTcha81x5jL784sF1aECLbmLT3ScWDZRdz4cd"
}
-]
\ No newline at end of file
+]
diff --git a/public/realms/mainnet-beta.json b/public/realms/mainnet-beta.json
index 1925eefda2..3fd4db4fa2 100644
--- a/public/realms/mainnet-beta.json
+++ b/public/realms/mainnet-beta.json
@@ -25,6 +25,13 @@
"discord": "@grapedao",
"shortDescription": "Frictionless is revolutionizing governance participation, bridging the gap between web2 and web3"
},
+ {
+ "symbol": "DED",
+ "displayName": "DED DAO",
+ "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw",
+ "realmId": "735Kg6893iFH2KuGy6uJrVXYKwBi6ky3KLLNPmJ4TMCD",
+ "ogImage": "https://arweave.net/LzLM9GSor6FYeeFv5hv2a5oQuwcoyH3WFGbEq6_xGZk"
+ },
{
"symbol": "GrapeUX",
"displayName": "Grape UX",
@@ -60,6 +67,17 @@
"github": "https://github.com/Deans-List/",
"shortDescription": "A Service DAO turned Network State, consisting of Web3 power users providing feedback sessions. Join us in changing the future of work!"
},
+ {
+ "symbol": "Dean's List Solarplex State",
+ "displayName": "Dean's List Solarplex State",
+ "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw",
+ "realmId": "4U5tep3h2wFrLskrCJAemvFVyLwGvQ8Xbuc8dBEC6smF",
+ "bannerImage": "/realms/Deans-List-Solarplex-State/img/banner-deanslist-solarplex.png",
+ "twitter": "@deanslistDAO",
+ "ogImage": "/realms/Deans-List-Solarplex-State/img/deans_list_solarplex_state.png",
+ "github": "https://github.com/Deans-List/",
+ "shortDescription": "Dean's List Solarplex State oversees feedback incentives on Solarplex."
+ },
{
"symbol": "Ukraine",
"displayName": "Ukraine.SOL",
@@ -181,7 +199,7 @@
"sortRank": 3,
"website": "https://grapes.network/",
"twitter": "@grapeprotocol",
- "discord": "https://discord.com/invite/greatape",
+ "discord": "https://discord.com/invite/grapedao",
"github": "https://github.com/Grape-Labs"
},
{
@@ -1442,20 +1460,6 @@
"discord": "https://discord.gg/uniquevcs",
"github": "https://uniquevc.gitbook.io/unique-venture-clubs-docs/"
},
- {
- "symbol": "GARI Network",
- "category": "web3",
- "bannerImage": "https://i.imgur.com/VfFjhk5.jpeg",
- "displayName": "GARI Network",
- "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw",
- "realmId": "uWg5gaTsBnXc5qiVMB8XxBUPYqLAb5bzzgkkpxi6UAY",
- "ogImage": "https://i.imgur.com/t5hzoBV.jpg",
- "shortDescription": "GARI Network enables everyone to monetize their social media time and activities by leveraging web3 technologies.",
- "sortRank": 3,
- "website": "https://gari.network/",
- "twitter": "@GariToken",
- "discord": "https://discord.gg/garitoken"
- },
{
"symbol": "Dual DAO",
"category": "defi",
@@ -3227,6 +3231,19 @@
"twitter": "@hntdenver",
"ogImage": "/realms/LavaDAO/img/lavalogo.png"
},
+ {
+ "symbol": "PAWN",
+ "displayName": "Pawn DAO",
+ "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw",
+ "shortDescription": "A Pawn in someone's experiment.",
+ "discord": "https://discord.gg/Td7QFn2ePz",
+ "bannerImage": "/realms/PAWN/img/pawns-banner.png",
+ "category": "Memecoin",
+ "sortRank": 3,
+ "realmId": "7rvjS4CgRYUZkSLJAXitmeQCybvfZcYcMjpVRhJ9mFHK",
+ "twitter": "@pawnspl24",
+ "ogImage": "/realms/PAWN/img/pawn.png"
+ },
{
"symbol": "COMRADE",
"displayName": "ComradeDAO",
@@ -3343,5 +3360,100 @@
"bannerImage": "/realms/TrustBet/Bannerontransparent.png",
"ogImage": "realms/TrustBet/tickerlogo.svg",
"communityMint": "xpFbKJa92Ee1NSYEhc3b3BVk4im8YStXRaVW6EoW33w"
+ },
+ {
+ "symbol": "BLR",
+ "displayName": "Blockride",
+ "category": "web3",
+ "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw",
+ "realmId": "A6ZS5ZdkyAbncb55fKjaUhBcQcovp8XcYT5AEQayv96y",
+ "bannerImage": "/realms/Blockride/banner.png",
+ "ogImage": "/realms/Blockride/logo.png",
+ "twitter": "@blockridenft",
+ "website": "https://blockride.xyz/",
+ "sortRank": 3,
+ "shortDescription": "BLOCKRIDE DAO - Building a modern approach to vehicle financing",
+ "keywords": "Web3, REALM, Governance, vehicle financing, DAO, Africans, Nigeria, RWA, Solana",
+ "github": "https://github.com/BlockrideNFT-org"
+ },
+ {
+ "symbol": "RAAAWR",
+ "displayName": "Solsaur DAO",
+ "bannerImage": "/realms/Solsaur/solsaur-realms-banner.png",
+ "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw",
+ "realmId": "ANqmLV2hQNwFm3jyfqLEBa6KTksosr6uKzcdfg9X6ReR",
+ "ogImage": "/realms/Solsaur/solsaur.png",
+ "website": "https://www.solsaur.com",
+ "twitter": "@solsauras"
+ },
+ {
+ "symbol": "Conk",
+ "displayName": "Conk Dao",
+ "category": "web3",
+ "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw",
+ "realmId": "A3jzUmuVqbyzqLgHtmMA2igUeACScRiSk71Hy27ehieo",
+ "bannerImage": "/realms/ConkDao/conk_banner.png",
+ "ogImage": "/realms/ConkDao/conk.png",
+ "twitter": "@Conk_Coin",
+ "website": "https://conkcoin.club",
+ "sortRank": 3,
+ "shortDescription": "Conk DAO - The People's Cat Coin",
+ "keywords": "Web3, REALM, Governance, Meme, DAO, Solana"
+ },
+ {
+ "symbol": "MEMES",
+ "displayName": "MemeCoinDAOai",
+ "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw",
+ "realmId": "Ecar1VyamYnR2UzJzJbQMKR9Zq1U5p1xuUUsnzceDiaH",
+ "bannerImage": "/realms/MemeCoinDAOai/MemeCoinDAOBanner1_15.png",
+ "ogImage": "/realms/MemeCoinDAOai/MemeCoinDAOFinalLogo.png",
+ "website": "https://www.memecoindao.ai",
+ "twitter": "@MemeCoinDAOai"
+ },
+ {
+ "symbol": "$GARI",
+ "displayName": "GARI Network DAO",
+ "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw",
+ "realmId": "HvDndGYjZNMVQDsrdAJJR7DtnQSB5rXM9BJBdwuxiXDg",
+ "bannerImage": "https://media1.tenor.com/m/uKCFs6UJgCwAAAAC/gari-gari-token.gif",
+ "ogImage": "https://gari.network/wp-content/uploads/2023/12/gari-coin-1.png",
+ "website": "https://gari.network/",
+ "twitter": "@TheGariNetwork",
+ "category": "web3"
+ },
+ {
+ "symbol": "BOHDAO",
+ "displayName": "Brigade of Honor Dao",
+ "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw",
+ "realmId": "FSh5XBFUYFMEWP99y4j7W6zERtEnqFVuwfuHgHgJJYWq",
+ "ogImage": "https://www.brigadeofhonor.com/BOHlogo.png",
+ "website": "https://www.brigadeofhonor.com/",
+ "twitter": "@BoHgamingguild"
+ },
+ {
+ "symbol": "MF",
+ "displayName": "MOUTAI FUND",
+ "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw",
+ "realmId": "3JZmKT5xWKESXdC9aVpcv4so2DngpDHqzCm1pzwPU8Jc",
+ "ogImage": "/realms/MOUTAI/MF.png",
+ "website": "https://moutaifund.club/",
+ "twitter": "@MoutaiFund"
+ },
+ {
+ "symbol": "MOUTAI",
+ "displayName": "MOUTAI DAO",
+ "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw",
+ "realmId": "DgsXUhQbGuHxRNcSZJJdVXJcFCeMEFyDNeBYUDS9pHmC",
+ "ogImage": "/realms/MOUTAI/mdao.jpg",
+ "website": "https://www.moutaicoin.co/",
+ "twitter": "@Moutai_Sol"
+ },
+ {
+ "symbol": "GARBAGE",
+ "displayName": "GARBAGE DAO",
+ "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw",
+ "realmId": "GgF6fHb3iM3Um5DtvwbZvpGpYTzYnr1RmZr4NkwHveGp",
+ "website": "",
+ "twitter": ""
}
]
diff --git a/scripts/governance-notifier.ts b/scripts/governance-notifier.ts
index 0ce55880af..dbfac98d5c 100644
--- a/scripts/governance-notifier.ts
+++ b/scripts/governance-notifier.ts
@@ -96,7 +96,11 @@ async function runNotifier() {
votingTokenDecimals
)
- const minVotesNeeded = 100000000
+ const minVotesNeeded =
+ proposal.account.governance.toBase58() ===
+ '7D6tGmaMyC8i73Q8X2Fec2S1Zb5rkyai6pctdMqHpHWT'
+ ? 50000000
+ : 100000000
const quorumReached = yesVotes >= minVotesNeeded
const isSuccess = yesVotes > noVotes && quorumReached
diff --git a/stores/useVotePluginsClientStore.tsx b/stores/useVotePluginsClientStore.tsx
index d22261a98d..0ad00e6953 100644
--- a/stores/useVotePluginsClientStore.tsx
+++ b/stores/useVotePluginsClientStore.tsx
@@ -242,12 +242,14 @@ const useVotePluginsClientStore = create(
},
handleSetPythClient: async (wallet, connection) => {
if (wallet) {
- const pythClient = await PythClient.connect(connection.current, wallet as unknown as Wallet)
- set((s) => {
- s.state.pythClient = pythClient
- })
+ const pythClient = await PythClient.connect(connection.current, wallet as unknown as Wallet)
+ const maxVoterWeight = (await pythClient.program.methods.updateMaxVoterWeight().pubkeys()).maxVoterRecord
+ set((s) => {
+ s.state.pythClient = pythClient
+ s.state.maxVoterWeight = maxVoterWeight
+ })
}
- },
+ }
})
)
diff --git a/tools/feeEstimate.ts b/tools/feeEstimate.ts
new file mode 100644
index 0000000000..0c79d874f8
--- /dev/null
+++ b/tools/feeEstimate.ts
@@ -0,0 +1,55 @@
+import {
+ Connection,
+ PublicKey,
+ RecentPrioritizationFees,
+} from '@solana/web3.js'
+import { getClient, getGroupForClient } from '@utils/mangoV4Tools'
+import { groupBy, mapValues, maxBy, sampleSize } from 'lodash'
+
+export const getFeeEstimate = async (connection: Connection) => {
+ const defaultFee = 5000
+ try {
+ //Use mango client to find good fee
+ const MAINNET_MANGO_GROUP = new PublicKey(
+ '78b8f4cGCwmZ9ysPFMWLaLTkkaYnUjwMJYStWe5RTSSX'
+ )
+ const MAX_PRIORITY_FEE_KEYS = 128
+ const client = await getClient(connection)
+ const group = await getGroupForClient(client, MAINNET_MANGO_GROUP)
+ const feeMultiplier = 1.2
+ const altResponse = await connection.getAddressLookupTable(
+ group.addressLookupTables[0]
+ )
+ const altKeys = altResponse.value?.state.addresses
+ if (!altKeys) return defaultFee
+
+ const addresses = sampleSize(altKeys, MAX_PRIORITY_FEE_KEYS)
+ const fees = await connection.getRecentPrioritizationFees({
+ lockedWritableAccounts: addresses,
+ })
+
+ if (fees.length < 1) return defaultFee
+
+ // get max priority fee per slot (and sort by slot from old to new)
+ const maxFeeBySlot = mapValues(groupBy(fees, 'slot'), (items) =>
+ maxBy(items, 'prioritizationFee')
+ )
+ const maximumFees = Object.values(maxFeeBySlot).sort(
+ (a, b) => a!.slot - b!.slot
+ ) as RecentPrioritizationFees[]
+
+ // get median of last 20 fees
+ const recentFees = maximumFees.slice(Math.max(maximumFees.length - 20, 0))
+ const mid = Math.floor(recentFees.length / 2)
+ const medianFee =
+ recentFees.length % 2 !== 0
+ ? recentFees[mid].prioritizationFee
+ : (recentFees[mid - 1].prioritizationFee +
+ recentFees[mid].prioritizationFee) /
+ 2
+ const feeEstimate = Math.ceil(medianFee * feeMultiplier)
+ return feeEstimate
+ } catch (e) {
+ return defaultFee
+ }
+}
diff --git a/tools/governance/prepareRealmCreation.ts b/tools/governance/prepareRealmCreation.ts
index 0f4951d71b..806e31319b 100644
--- a/tools/governance/prepareRealmCreation.ts
+++ b/tools/governance/prepareRealmCreation.ts
@@ -68,7 +68,7 @@ interface RealmCreationV2 {
transferCouncilMintAuthority: boolean
councilWalletPks: PublicKey[]
- communityTokenConfig?: GoverningTokenConfigAccountArgs
+ communityTokenConfig: GoverningTokenConfigAccountArgs
skipRealmAuthority?: boolean
}
type RealmCreationV3 = {
@@ -234,6 +234,7 @@ export async function prepareRealmCreation({
// there are incoming council members
incomingCouncilMembers > 0)
+ console.log('Prepare realm - can community govern?', communityCanGovern)
if (
!communityCanGovern &&
nftCollectionCount === 0 && // note this is not the most thorough check possible for nft realms
diff --git a/utils/Mango/listingTools.ts b/utils/Mango/listingTools.ts
index d623eff2f8..1762f12cae 100644
--- a/utils/Mango/listingTools.ts
+++ b/utils/Mango/listingTools.ts
@@ -9,11 +9,13 @@ import {
toUiDecimalsForQuote,
} from '@blockworks-foundation/mango-v4'
import {
+ LISTING_PRESET,
LISTING_PRESETS,
- LISTING_PRESETS_KEYS,
- LISTING_PRESETS_PYTH,
- ListingPreset,
- getTierWithAdjustedNetBorrows,
+ LISTING_PRESETS_KEY,
+ getPresetWithAdjustedNetBorrows,
+ getPresetWithAdjustedDepositLimit,
+ getPythPresets,
+ getSwitchBoardPresets,
} from '@blockworks-foundation/mango-v4-settings/lib/helpers/listingTools'
import { AnchorProvider, BN, Program, Wallet } from '@coral-xyz/anchor'
import { MAINNET_USDC_MINT } from '@foresight-tmp/foresight-sdk/dist/consts'
@@ -28,6 +30,7 @@ import {
VersionedTransaction,
} from '@solana/web3.js'
import SwitchboardProgram from '@switchboard-xyz/sbv2-lite'
+import { notify } from '@utils/notifications'
import Big from 'big.js'
import { secondsToHours } from 'date-fns'
@@ -45,7 +48,7 @@ export type FlatListingArgs = {
name: string
tokenIndex: number
'oracleConfig.confFilter': number
- 'oracleConfig.maxStalenessSlots': number
+ 'oracleConfig.maxStalenessSlots': number | null
'interestRateParams.util0': number
'interestRateParams.rate0': number
'interestRateParams.util1': number
@@ -127,7 +130,7 @@ export type ListingArgsFormatted = {
tokenIndex: number
tokenName: string
oracleConfidenceFilter: string
- oracleMaxStalenessSlots: number
+ oracleMaxStalenessSlots: number | null
interestRateUtilizationPoint1: string
interestRateUtilizationPoint0: string
interestRatePoint0: string
@@ -151,7 +154,7 @@ export type ListingArgsFormatted = {
stablePriceGrowthLimit: string
tokenConditionalSwapMakerFeeRate: number
tokenConditionalSwapTakerFeeRate: number
- flashLoanSwapFeeRate: number
+ flashLoanSwapFeeRate: string
reduceOnly: string
oracle: string
depositLimit: string
@@ -169,10 +172,13 @@ export type EditTokenArgsFormatted = ListingArgsFormatted & {
setFallbackOracle: boolean
}
-const transformPresetToProposed = (listingPreset: ListingPreset) => {
+const transformPresetToProposed = (listingPreset: LISTING_PRESET) => {
const proposedPreset: FormattedListingPreset = {
...listingPreset,
- 'oracleConfig.maxStalenessSlots': listingPreset.maxStalenessSlots!,
+ 'oracleConfig.maxStalenessSlots':
+ listingPreset.maxStalenessSlots === -1
+ ? null
+ : listingPreset.maxStalenessSlots!,
'oracleConfig.confFilter': listingPreset.oracleConfFilter,
'interestRateParams.adjustmentFactor': listingPreset.adjustmentFactor,
'interestRateParams.util0': listingPreset.util0,
@@ -194,26 +200,40 @@ type FormattedListingPreset = Omit<
>
type ProposedListingPresets = {
- [key in LISTING_PRESETS_KEYS]: FormattedListingPreset
+ [key in LISTING_PRESETS_KEY]: FormattedListingPreset
}
export const getFormattedListingPresets = (
isPythOracle: boolean,
- currentTotalDepositsInUsdc?: number
+ uiDeposits?: number,
+ decimals?: number,
+ tokenPrice?: number
) => {
- const PRESETS = isPythOracle ? LISTING_PRESETS_PYTH : LISTING_PRESETS
+ const PRESETS = !isPythOracle
+ ? getSwitchBoardPresets(LISTING_PRESETS)
+ : getPythPresets(LISTING_PRESETS)
const PROPOSED_LISTING_PRESETS: ProposedListingPresets = Object.keys(
PRESETS
).reduce((accumulator, key) => {
- accumulator[key] = transformPresetToProposed(
- !currentTotalDepositsInUsdc
- ? PRESETS[key]
- : getTierWithAdjustedNetBorrows(
- PRESETS[key],
- currentTotalDepositsInUsdc
- )
- )
+ let adjustedPreset = PRESETS[key]
+ if (uiDeposits && tokenPrice) {
+ adjustedPreset = getPresetWithAdjustedNetBorrows(
+ PRESETS[key],
+ uiDeposits,
+ tokenPrice,
+ toUiDecimals(PRESETS[key].netBorrowLimitPerWindowQuote, 6)
+ )
+ }
+
+ if (decimals && tokenPrice) {
+ adjustedPreset = getPresetWithAdjustedDepositLimit(
+ adjustedPreset,
+ tokenPrice,
+ decimals
+ )
+ }
+ accumulator[key] = transformPresetToProposed(adjustedPreset)
return accumulator
}, {} as ProposedListingPresets)
return PROPOSED_LISTING_PRESETS
@@ -228,41 +248,41 @@ const fetchJupiterRoutes = async (
feeBps = 0
) => {
{
- const paramsString = new URLSearchParams({
- inputMint: inputMint.toString(),
- outputMint: outputMint.toString(),
- amount: amount.toString(),
- slippageBps: Math.ceil(slippage * 100).toString(),
- feeBps: feeBps.toString(),
- swapMode,
- }).toString()
-
- const response = await fetch(
- `https://quote-api.jup.ag/v4/quote?${paramsString}`
- )
-
- const res = await response.json()
- const data = res.data
-
- return {
- routes: res.data as RouteInfo[],
- bestRoute: (data.length ? data[0] : null) as RouteInfo | null,
+ try {
+ const paramsString = new URLSearchParams({
+ inputMint: inputMint.toString(),
+ outputMint: outputMint.toString(),
+ amount: amount.toString(),
+ slippageBps: Math.ceil(slippage * 100).toString(),
+ feeBps: feeBps.toString(),
+ swapMode,
+ }).toString()
+
+ const response = await fetch(
+ `https://quote-api.jup.ag/v6/quote?${paramsString}`
+ )
+
+ const res = await response.json()
+ return {
+ bestRoute: (res ? res : null) as RouteInfo | null,
+ }
+ } catch (e) {
+ console.log(e)
+ return {
+ bestRoute: null,
+ }
}
}
}
-export const getSuggestedCoinTier = async (
+export const getSuggestedCoinPresetInfo = async (
outputMint: string,
hasPythOracle: boolean
) => {
try {
- const TIERS: LISTING_PRESETS_KEYS[] = [
- 'ULTRA_PREMIUM',
- 'PREMIUM',
- 'MID',
- 'MEME',
- 'SHIT',
- ]
+ const PRESETS = !hasPythOracle
+ ? getSwitchBoardPresets(LISTING_PRESETS)
+ : getPythPresets(LISTING_PRESETS)
const swaps = await Promise.all([
fetchJupiterRoutes(
@@ -280,6 +300,11 @@ export const getSuggestedCoinTier = async (
outputMint,
toNative(20000, 6).toNumber()
),
+ fetchJupiterRoutes(
+ MAINNET_USDC_MINT.toBase58(),
+ outputMint,
+ toNative(10000, 6).toNumber()
+ ),
fetchJupiterRoutes(
MAINNET_USDC_MINT.toBase58(),
outputMint,
@@ -308,6 +333,12 @@ export const getSuggestedCoinTier = async (
toNative(20000, 6).toNumber(),
'ExactOut'
),
+ fetchJupiterRoutes(
+ MAINNET_USDC_MINT.toBase58(),
+ outputMint,
+ toNative(20000, 6).toNumber(),
+ 'ExactOut'
+ ),
fetchJupiterRoutes(
MAINNET_USDC_MINT.toBase58(),
outputMint,
@@ -329,13 +360,16 @@ export const getSuggestedCoinTier = async (
(acc: { amount: string; priceImpactPct: number }[], val) => {
if (val.swapMode === 'ExactIn') {
const exactOutRoute = bestRoutesSwaps.find(
- (x) => x.amount === val.amount && x.swapMode === 'ExactOut'
+ (x) => x.outAmount === val.inAmount && x.swapMode === 'ExactOut'
)
+
acc.push({
- amount: val.amount.toString(),
+ amount: val.inAmount.toString(),
priceImpactPct: exactOutRoute?.priceImpactPct
- ? (val.priceImpactPct + exactOutRoute.priceImpactPct) / 2
- : val.priceImpactPct,
+ ? (Number(val.priceImpactPct) +
+ Number(exactOutRoute.priceImpactPct)) /
+ 2
+ : Number(val.priceImpactPct),
})
}
return acc
@@ -343,35 +377,32 @@ export const getSuggestedCoinTier = async (
[]
)
- const indexForTierFromSwaps = averageSwaps.findIndex(
+ const indexForTargetAmount = averageSwaps.findIndex(
(x) => x?.priceImpactPct && x?.priceImpactPct * 100 < 1
)
- const tier =
- indexForTierFromSwaps > -1 ? TIERS[indexForTierFromSwaps] : 'SHIT'
+ const targetAmount =
+ indexForTargetAmount > -1
+ ? toUiDecimals(new BN(averageSwaps[indexForTargetAmount].amount), 6)
+ : 0
- const tierLowerThenCurrent =
- tier === 'ULTRA_PREMIUM' || tier === 'PREMIUM'
- ? 'MID'
- : tier === 'MID'
- ? 'MEME'
- : tier
- const isPythRecommendedTier =
- tier === 'MID' || tier === 'PREMIUM' || tier === 'ULTRA_PREMIUM'
- const listingTier =
- isPythRecommendedTier && !hasPythOracle ? tierLowerThenCurrent : tier
+ const preset: LISTING_PRESET =
+ Object.values(PRESETS).find(
+ (x) => x.preset_target_amount === targetAmount
+ ) || PRESETS.UNTRUSTED
return {
- tier: listingTier,
- priceImpact: (indexForTierFromSwaps > -1
- ? averageSwaps[indexForTierFromSwaps]!.priceImpactPct
+ presetKey: preset.preset_key,
+ priceImpact: (indexForTargetAmount > -1
+ ? averageSwaps[indexForTargetAmount]!.priceImpactPct
: 100
).toFixed(2),
}
} catch (e) {
+ console.log(e)
return {
- tier: 'SHIT',
- priceImpact: 100,
+ presetKey: 'UNTRUSTED',
+ priceImpact: '100',
}
}
}
@@ -510,9 +541,6 @@ export const getBestMarket = async ({
if (!markets.length) {
return undefined
}
- if (markets.length === 1) {
- return markets[0].publicKey
- }
const marketsDataJsons = await Promise.all([
...markets.map((x) =>
fetch(`/openSerumApi/market/${x.publicKey.toBase58()}`)
@@ -521,12 +549,26 @@ export const getBestMarket = async ({
const marketsData = await Promise.all([
...marketsDataJsons.map((x) => x.json()),
])
- const bestMarket = marketsData.sort((a, b) => b.volume24h - a.volume24h)
- return bestMarket.length
- ? new PublicKey(bestMarket[0].id)
- : markets[0].publicKey
+ let error = ''
+ let sortedMarkets = marketsData.sort((a, b) => b.volume24h - a.volume24h)
+ let firstBestMarket = sortedMarkets[0]
+
+ if (firstBestMarket.volume24h === 0) {
+ error = 'Openbook market had 0 volume in last 24h check it carefully'
+ }
+ sortedMarkets = sortedMarkets.sort(
+ (a, b) => b.quoteDepositsTotal - a.quoteDepositsTotal
+ )
+ firstBestMarket = sortedMarkets[0]
+
+ return sortedMarkets.length
+ ? { pubKey: new PublicKey(firstBestMarket.id), error: error }
+ : undefined
} catch (e) {
- return null
+ notify({
+ message: 'Openbook market not found',
+ type: 'error',
+ })
}
}
@@ -678,7 +720,7 @@ export const getFormattedBankValues = (group: Group, bank: Bank) => {
netBorrowLimitWindowSizeTs: secondsToHours(
bank.netBorrowLimitWindowSizeTs.toNumber()
),
- depositLimit: bank.depositLimit.toNumber(),
+ depositLimit: bank.depositLimit.toString(),
interestTargetUtilization: bank.interestTargetUtilization,
interestCurveScaling: bank.interestCurveScaling,
reduceOnly: REDUCE_ONLY_OPTIONS[bank.reduceOnly].name,
diff --git a/utils/instructions/Dual/delegate.ts b/utils/instructions/Dual/delegate.ts
index f6555c4286..6c9d52e94b 100644
--- a/utils/instructions/Dual/delegate.ts
+++ b/utils/instructions/Dual/delegate.ts
@@ -40,6 +40,8 @@ import {
import { getMintCfgIdx, tryGetVoter } from 'VoteStakeRegistry/sdk/api'
import { getPeriod } from 'VoteStakeRegistry/tools/deposits'
import { fetchProgramVersion } from '@hooks/queries/useProgramVersionQuery'
+import { fetchRealmByPubkey } from '@hooks/queries/realm'
+import { determineVotingPowerType } from '@hooks/queries/governancePower'
const govProgramId = new PublicKey(
'GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw'
@@ -66,6 +68,7 @@ interface VoteDepositArgs {
setFormErrors: any
schema: any
wallet: WalletAdapter | undefined
+ realmPk: PublicKey | undefined
}
export async function getDelegateInstruction({
@@ -123,8 +126,14 @@ export async function getVoteDepositInstruction({
form,
schema,
setFormErrors,
+ realmPk,
}: VoteDepositArgs): Promise {
- const isValid = await validateInstruction({ schema, form, setFormErrors })
+ const isValid =
+ (await validateInstruction({ schema, form, setFormErrors })) &&
+ realmPk !== undefined
+ if (!realmPk) {
+ setFormErrors({ realm: 'Realm not found' })
+ }
const serializedInstruction = ''
const additionalSerializedInstructions: string[] = []
@@ -136,9 +145,25 @@ export async function getVoteDepositInstruction({
wallet?.publicKey &&
form.realm &&
form.delegateToken &&
- form.delegateToken.extensions.mint?.publicKey
+ form.delegateToken.extensions.mint?.publicKey &&
+ realmPk
) {
- const realmPk = new PublicKey(form.realm)
+ const { result: realm } = await fetchRealmByPubkey(
+ connection.current,
+ realmPk
+ )
+ if (!realm) {
+ throw new Error('Realm not found')
+ }
+ const plugin = await determineVotingPowerType(
+ connection.current,
+ realmPk,
+ 'community'
+ )
+ if (plugin !== 'VSR') {
+ throw new Error('this form currently only supports VSR')
+ }
+
const communityMintPk = form.delegateToken.extensions.mint?.publicKey
const daoWallet = form.delegateToken.governance.nativeTreasuryAddress
const amount = getMintNaturalAmountFromDecimalAsBN(
@@ -148,10 +173,10 @@ export async function getVoteDepositInstruction({
const programVersion = await fetchProgramVersion(
connection.current,
- govProgramId // governance program public key
+ realm.owner // governance program public key
)
const tokenOwnerRecordAddress = await getTokenOwnerRecordAddress(
- govProgramId,
+ realm.owner,
realmPk,
form.delegateToken.extensions.mint.publicKey,
daoWallet
@@ -204,7 +229,7 @@ export async function getVoteDepositInstruction({
if (!isExisintgTokenOwnerRecord) {
await withCreateTokenOwnerRecord(
prerequisiteInstructions,
- govProgramId,
+ realm.owner,
programVersion,
realmPk,
daoWallet,
diff --git a/utils/instructions/Dual/index.ts b/utils/instructions/Dual/index.ts
index 1d46f5a42d..e23e641f57 100644
--- a/utils/instructions/Dual/index.ts
+++ b/utils/instructions/Dual/index.ts
@@ -141,7 +141,8 @@ export async function getConfigInstruction({
//owner is sol wallet or governance same as baseTokenAccount
form.baseTreasury.extensions!.token!.account.owner,
[],
- form.numTokens
+ // @ts-ignore
+ form.numTokens as unknown as bigint
)
)
)
@@ -332,7 +333,8 @@ export async function getConfigGsoInstruction({
//owner is sol wallet or governance same as baseTreasury
form.baseTreasury.extensions!.token!.account.owner,
[],
- form.numTokens
+ // @ts-ignore
+ form.numTokens as unknown as bigint
)
)
)
@@ -362,6 +364,7 @@ export async function getConfigGsoInstruction({
// Set all GSOs to have the same expiration and lockup period. This means
// that users will be able to unstake at the same time as option expiration.
const lockupPeriodEnd = form.optionExpirationUnixSeconds
+ const lockupMint = new PublicKey(form.lockupMint);
const configInstruction = await gso.createConfigInstruction(
optionsPerMillion,
lockupPeriodEnd,
@@ -371,6 +374,7 @@ export async function getConfigGsoInstruction({
form.soName,
strikeAtomsPerLot,
form.payer.extensions.transferAddress!,
+ lockupMint,
baseMint,
quoteMint,
baseAccount,
diff --git a/utils/instructions/NftVoter/castNftVote.ts b/utils/instructions/NftVoter/castNftVote.ts
index 340a7e6dfe..178aa090af 100644
--- a/utils/instructions/NftVoter/castNftVote.ts
+++ b/utils/instructions/NftVoter/castNftVote.ts
@@ -12,7 +12,7 @@ import { PROGRAM_ID as ACCOUNT_COMPACTION_PROGRAM_ID } from '@solana/spl-account
import { SYSTEM_PROGRAM_ID } from '@solana/spl-governance'
import { NftVoter } from 'idls/nft_voter'
import { NftVoterV2 } from 'idls/nft_voter_v2'
-import { Program } from '@project-serum/anchor'
+import { Program } from '@coral-xyz/anchor'
import {
AccountData,
UpdateVoterWeightRecordTypes,
@@ -201,8 +201,15 @@ export const getCastNftVoteInstructionV2 = async (
cnft
)
+ // CreateCnftActionTicket requires a non-null collection,
+ // but getCnftParamAndProof returns a nullable one
+ if (!param.collection.key) throw new Error("Collection key not found");
+ // Typescript doesn't infer this in its current version, but this is basically
+ // casting the collection key to non-null.
+ const typesafeParams = [param as typeof param & { collection: typeof param.collection & { key : PublicKey }}]
+
const instruction = await program.methods
- .createCnftActionTicket({ [type]: {} }, [param])
+ .createCnftActionTicket({ [type]: {} }, typesafeParams)
.accounts({
registrar,
voterWeightRecord: voterWeightPk,
diff --git a/utils/instructions/NftVoter/updateVoterWeight.ts b/utils/instructions/NftVoter/updateVoterWeight.ts
index 9a11626b47..9e6958bd48 100644
--- a/utils/instructions/NftVoter/updateVoterWeight.ts
+++ b/utils/instructions/NftVoter/updateVoterWeight.ts
@@ -8,7 +8,7 @@ import { PROGRAM_ID as ACCOUNT_COMPACTION_PROGRAM_ID } from '@solana/spl-account
import { SYSTEM_PROGRAM_ID } from '@solana/spl-governance'
import { NftVoter } from 'idls/nft_voter'
import { NftVoterV2 } from 'idls/nft_voter_v2'
-import { Program } from '@project-serum/anchor'
+import { Program } from '@coral-xyz/anchor'
import {
AccountData,
UpdateVoterWeightRecordTypes,
@@ -130,8 +130,16 @@ export const getUpdateVoterWeightRecordInstructionV2 = async (
program.provider.connection,
cnft
)
+
+ // CreateCnftActionTicket requires a non-null collection,
+ // but getCnftParamAndProof returns a nullable one
+ if (!param.collection.key) throw new Error("Collection key not found");
+ // Typescript doesn't infer this in its current version, but this is basically
+ // casting the collection key to non-null.
+ const typesafeParams = [param as typeof param & { collection: typeof param.collection & { key : PublicKey }}]
+
const instruction = await program.methods
- .createCnftActionTicket({ [type]: {} }, [param])
+ .createCnftActionTicket({ [type]: {} }, typesafeParams)
.accounts({
registrar,
voterWeightRecord: voterWeightPk,
diff --git a/utils/mangoV4Tools.ts b/utils/mangoV4Tools.ts
index 60e30be0f6..295865a4d8 100644
--- a/utils/mangoV4Tools.ts
+++ b/utils/mangoV4Tools.ts
@@ -1,3 +1,9 @@
+import { MANGO_V4_ID, MangoClient } from '@blockworks-foundation/mango-v4'
+import { AnchorProvider } from '@coral-xyz/anchor'
+import queryClient from '@hooks/queries/queryClient'
+import { Connection, Keypair, PublicKey } from '@solana/web3.js'
+import EmptyWallet from './Mango/listingTools'
+
export function getChangedValues>(
originalValues: T,
newValues: T,
@@ -38,3 +44,38 @@ export function getNullOrTransform(
}
return null
}
+
+export const getClient = async (connection: Connection) => {
+ const client = await queryClient.fetchQuery({
+ queryKey: ['mangoClient', connection.rpcEndpoint],
+ queryFn: async () => {
+ const options = AnchorProvider.defaultOptions()
+ const adminProvider = new AnchorProvider(
+ connection,
+ new EmptyWallet(Keypair.generate()),
+ options
+ )
+ const client = MangoClient.connect(
+ adminProvider,
+ 'mainnet-beta',
+ MANGO_V4_ID['mainnet-beta']
+ )
+
+ return client
+ },
+ })
+ return client
+}
+export const getGroupForClient = async (
+ client: MangoClient,
+ groupPk: PublicKey
+) => {
+ const group = await queryClient.fetchQuery({
+ queryKey: ['mangoGroup', groupPk.toBase58(), client.connection.rpcEndpoint],
+ queryFn: async () => {
+ const response = await client.getGroup(groupPk)
+ return response
+ },
+ })
+ return group
+}
diff --git a/utils/modifiedMangolana.ts b/utils/modifiedMangolana.ts
index f39b89bbec..87761fb884 100644
--- a/utils/modifiedMangolana.ts
+++ b/utils/modifiedMangolana.ts
@@ -27,6 +27,8 @@ import {
TransactionInstructionWithSigners,
} from '@blockworks-foundation/mangolana/lib/globalTypes'
import { WalletSigner } from '@solana/spl-governance'
+import { getFeeEstimate } from '@tools/feeEstimate'
+import { createComputeBudgetIx } from '@blockworks-foundation/mango-v4'
interface TransactionInstructionWithType {
instructionsSet: TransactionInstructionWithSigners[]
@@ -407,7 +409,7 @@ export const sendSignAndConfirmTransactions = async ({
const logger = new Logger({ ...config })
const block =
timeoutStrategy?.block ?? (await connection.getLatestBlockhash('confirmed'))
-
+ const fee = await getFeeEstimate(connection)
const walletPk = wallet.publicKey
if (!walletPk) throw new Error('Wallet not connected!')
@@ -438,6 +440,7 @@ export const sendSignAndConfirmTransactions = async ({
}
const transaction = new Transaction()
+ transaction.add(createComputeBudgetIx(fee))
transactionInstruction.instructionsSet.forEach((instruction) => {
transaction.add(instruction.transactionInstruction)
if (instruction.signers?.length) {
diff --git a/utils/plugin/gateway.ts b/utils/plugin/gateway.ts
new file mode 100644
index 0000000000..ab9184b325
--- /dev/null
+++ b/utils/plugin/gateway.ts
@@ -0,0 +1,84 @@
+import {getRegistrarPDA} from "@utils/plugin/accounts";
+import {ProgramAccount, Realm, SYSTEM_PROGRAM_ID} from "@solana/spl-governance";
+import {GatewayClient} from "@solana/governance-program-library";
+import {PublicKey} from "@solana/web3.js";
+
+// Get the registrar account for a given realm
+export const tryGetRegistar = async (
+ realm: ProgramAccount,
+ gatewayClient: GatewayClient,
+) => {
+ const {registrar} = await getRegistrarPDA(
+ realm.pubkey,
+ realm.account.communityMint,
+ gatewayClient.program.programId
+ )
+ try {
+ return await gatewayClient.program.account.registrar.fetch(
+ registrar
+ )
+ } catch (e) {
+ return null
+ }
+};
+
+// Create an instruction to create a registrar account for a given realm
+export const createCivicRegistrarIx = async (
+ realm: ProgramAccount,
+ payer: PublicKey,
+ gatewayClient: GatewayClient,
+ gatekeeperNetwork: PublicKey,
+ predecessor?: PublicKey
+) => {
+ const { registrar } = await getRegistrarPDA(
+ realm.pubkey,
+ realm.account.communityMint,
+ gatewayClient.program.programId
+ )
+
+ const remainingAccounts = predecessor
+ ? [{ pubkey: predecessor, isSigner: false, isWritable: false }]
+ : []
+
+ return gatewayClient!.program.methods
+ .createRegistrar(false)
+ .accounts({
+ registrar,
+ realm: realm.pubkey,
+ governanceProgramId: realm.owner,
+ realmAuthority: realm.account.authority!,
+ governingTokenMint: realm.account.communityMint!,
+ gatekeeperNetwork,
+ payer,
+ systemProgram: SYSTEM_PROGRAM_ID,
+ })
+ .remainingAccounts(remainingAccounts)
+ .instruction()
+}
+
+// Create an instruction to configure a registrar account for a given realm
+export const configureCivicRegistrarIx = async (
+ realm: ProgramAccount,
+ gatewayClient: GatewayClient,
+ gatekeeperNetwork: PublicKey,
+ predecessor?: PublicKey
+) => {
+ const { registrar } = await getRegistrarPDA(
+ realm.pubkey,
+ realm.account.communityMint,
+ gatewayClient.program.programId
+ )
+ const remainingAccounts = predecessor
+ ? [{ pubkey: predecessor, isSigner: false, isWritable: false }]
+ : []
+ return gatewayClient.program.methods
+ .configureRegistrar(false)
+ .accounts({
+ registrar,
+ realm: realm.pubkey,
+ realmAuthority: realm.account.authority!,
+ gatekeeperNetwork: gatekeeperNetwork,
+ })
+ .remainingAccounts(remainingAccounts)
+ .instruction()
+}
\ No newline at end of file
diff --git a/utils/send.tsx b/utils/send.tsx
index 93c10f875b..7eca40b04a 100644
--- a/utils/send.tsx
+++ b/utils/send.tsx
@@ -10,6 +10,8 @@ import Wallet from '@project-serum/sol-wallet-adapter'
import { sleep } from '@project-serum/common'
import { WalletSigner } from '@solana/spl-governance'
import { invalidateInstructionAccounts } from '@hooks/queries/queryClient'
+import { createComputeBudgetIx } from '@blockworks-foundation/mango-v4'
+import { getFeeEstimate } from '@tools/feeEstimate'
class TransactionError extends Error {
public txid: string
@@ -69,9 +71,12 @@ export async function signTransaction({
signers?: Array
connection: Connection
}) {
- transaction.recentBlockhash = (
- await connection.getLatestBlockhash('max')
- ).blockhash
+ const [{ blockhash: recentBlockhash }, fee] = await Promise.all([
+ connection.getLatestBlockhash('max'),
+ getFeeEstimate(connection),
+ ])
+ transaction.add(createComputeBudgetIx(fee))
+ transaction.recentBlockhash = recentBlockhash
transaction.setSigners(wallet!.publicKey!, ...signers.map((s) => s.publicKey))
if (signers.length > 0) {
transaction.partialSign(...signers)
@@ -91,9 +96,14 @@ export async function signTransactions({
wallet: Wallet
connection: Connection
}) {
- const blockhash = (await connection.getLatestBlockhash('max')).blockhash
+ const [{ blockhash: recentBlockhash }, fee] = await Promise.all([
+ connection.getLatestBlockhash('max'),
+ getFeeEstimate(connection),
+ ])
+
transactionsAndSigners.forEach(({ transaction, signers = [] }) => {
- transaction.recentBlockhash = blockhash
+ transaction.add(createComputeBudgetIx(fee))
+ transaction.recentBlockhash = recentBlockhash
transaction.setSigners(
wallet!.publicKey!,
...signers.map((s) => s.publicKey)
diff --git a/utils/sendTransactions.tsx b/utils/sendTransactions.tsx
index f740fa144d..1ddd9d8d16 100644
--- a/utils/sendTransactions.tsx
+++ b/utils/sendTransactions.tsx
@@ -11,7 +11,11 @@ import { invalidateInstructionAccounts } from '@hooks/queries/queryClient'
import {
sendSignAndConfirmTransactionsProps,
sendSignAndConfirmTransactions,
+ TransactionInstructionWithType,
} from '@blockworks-foundation/mangolana/lib/transactions'
+import { getFeeEstimate } from '@tools/feeEstimate'
+import { TransactionInstructionWithSigners } from '@blockworks-foundation/mangolana/lib/globalTypes'
+import { createComputeBudgetIx } from '@blockworks-foundation/mango-v4'
export type WalletSigner = Pick<
SignerWalletAdapter,
@@ -32,7 +36,7 @@ export enum SequenceType {
StopOnFailure,
}
-export const sendTransactionsV3 = ({
+export const sendTransactionsV3 = async ({
connection,
wallet,
transactionInstructions,
@@ -42,6 +46,19 @@ export const sendTransactionsV3 = ({
// eslint-disable-next-line @typescript-eslint/no-unused-vars
lookupTableAccounts,
}: sendSignAndConfirmTransactionsProps & { lookupTableAccounts?: any }) => {
+ const transactionInstructionsWithFee: TransactionInstructionWithType[] = []
+ const fee = await getFeeEstimate(connection)
+ for (const tx of transactionInstructions) {
+ const txObjWithFee = {
+ ...tx,
+ instructionSet: [
+ new TransactionInstructionWithSigners(createComputeBudgetIx(fee)),
+ ...tx.instructionsSet,
+ ],
+ }
+ transactionInstructionsWithFee.push(txObjWithFee)
+ }
+
const callbacksWithUiComponent = {
afterBatchSign: (signedTxnsCount) => {
if (callbacks?.afterBatchSign) {
@@ -54,7 +71,7 @@ export const sendTransactionsV3 = ({
callbacks?.afterAllTxConfirmed()
}
closeTransactionProcessUi()
- transactionInstructions.forEach((x) =>
+ transactionInstructionsWithFee.forEach((x) =>
x.instructionsSet.forEach((x) =>
invalidateInstructionAccounts(x.transactionInstruction)
)
@@ -79,7 +96,7 @@ export const sendTransactionsV3 = ({
getErrorMsg(e),
e.txid
)
- transactionInstructions.forEach((x) =>
+ transactionInstructionsWithFee.forEach((x) =>
x.instructionsSet.forEach((x) =>
invalidateInstructionAccounts(x.transactionInstruction)
)
@@ -89,7 +106,7 @@ export const sendTransactionsV3 = ({
const cfg = {
maxTxesInBatch:
- transactionInstructions.filter(
+ transactionInstructionsWithFee.filter(
(x) => x.sequenceType === SequenceType.Sequential
).length > 0
? 20
@@ -103,7 +120,7 @@ export const sendTransactionsV3 = ({
return sendSignAndConfirmTransactions({
connection,
wallet,
- transactionInstructions,
+ transactionInstructions: transactionInstructionsWithFee,
timeoutStrategy,
callbacks: callbacksWithUiComponent,
config: cfg,
@@ -137,17 +154,21 @@ export const txBatchesToInstructionSetWithSigners = (
txBatch: TransactionInstruction[],
signerBatches: Keypair[][],
batchIdx?: number
-) => {
+): { transactionInstruction: TransactionInstruction; signers: Keypair[] }[] => {
return txBatch.map((tx, txIdx) => {
+ let signers: Keypair[] = []
+
+ if (
+ typeof batchIdx !== 'undefined' &&
+ signerBatches?.length &&
+ signerBatches?.[batchIdx]?.[txIdx]
+ ) {
+ signers = [signerBatches[batchIdx][txIdx]]
+ }
+
return {
transactionInstruction: tx,
- signers:
- typeof batchIdx !== 'undefined' &&
- signerBatches.length &&
- signerBatches[batchIdx] &&
- signerBatches[batchIdx][txIdx]
- ? [signerBatches[batchIdx][txIdx]]
- : [],
+ signers,
}
})
}
diff --git a/utils/services/tokenPrice.tsx b/utils/services/tokenPrice.tsx
index f5eca91a93..0f0200c3a8 100644
--- a/utils/services/tokenPrice.tsx
+++ b/utils/services/tokenPrice.tsx
@@ -85,6 +85,17 @@ class TokenPriceService {
vsTokenSymbol: 'USDC',
}
}
+
+ //override chai price if its broken
+ const chaiMint = '3jsFX1tx2Z8ewmamiwSU851GzyzM2DJMq7KWW5DM8Py3'
+ const chaiData = this._tokenPriceToUSDlist[chaiMint]
+
+ if (chaiData?.price && (chaiData.price > 1.3 || chaiData.price < 0.9)) {
+ this._tokenPriceToUSDlist[chaiMint] = {
+ ...chaiData,
+ price: 1,
+ }
+ }
}
}
/**
diff --git a/utils/uiTypes/NftVoterClient.ts b/utils/uiTypes/NftVoterClient.ts
index c9b5369e88..6a2bd59d54 100644
--- a/utils/uiTypes/NftVoterClient.ts
+++ b/utils/uiTypes/NftVoterClient.ts
@@ -1,4 +1,4 @@
-import { Program, Provider } from '@project-serum/anchor'
+import { Program, Provider } from '@coral-xyz/anchor'
import { PublicKey } from '@solana/web3.js'
import { NftVoter, IDL } from '../../idls/nft_voter'
import { NftVoterV2, IDLV2 } from '../../idls/nft_voter_v2'
diff --git a/utils/uiTypes/VotePlugin.ts b/utils/uiTypes/VotePlugin.ts
index 22da4901e2..1a9f185eec 100644
--- a/utils/uiTypes/VotePlugin.ts
+++ b/utils/uiTypes/VotePlugin.ts
@@ -50,7 +50,7 @@ import {
} from '@utils/instructions/NftVoter/castNftVote'
import { NftVoter } from 'idls/nft_voter'
import { NftVoterV2 } from 'idls/nft_voter_v2'
-import { Program } from '@project-serum/anchor'
+import { Program } from '@coral-xyz/anchor'
import { fetchTokenOwnerRecordByPubkey } from '@hooks/queries/tokenOwnerRecord'
import { StakeConnection as PythClient } from '@pythnetwork/staking'
import { getVotingNfts } from '@hooks/queries/plugins/nftVoter'
@@ -341,7 +341,7 @@ export class VotingClient {
} = await this.client.withUpdateVoterWeight(
instructions,
stakeAccount!,
- { [type]: {} },
+ { [type]: {} } as any,
pythVoterWeightTarget
)
diff --git a/utils/uiTypes/proposalCreationTypes.ts b/utils/uiTypes/proposalCreationTypes.ts
index 3880d37716..4de7c00e00 100644
--- a/utils/uiTypes/proposalCreationTypes.ts
+++ b/utils/uiTypes/proposalCreationTypes.ts
@@ -342,7 +342,7 @@ export enum Instructions {
DualFinanceDelegate,
DualFinanceDelegateWithdraw,
DualFinanceVoteDeposit,
- DualFinanceVote,
+ DaoVote,
DistributionCloseVaults,
DistributionFillVaults,
DelegateStake,
@@ -356,15 +356,21 @@ export enum Instructions {
InitSolendObligationAccount,
JoinDAO,
MangoV4PerpCreate,
+ MangoV4PerpCreateV23,
MangoV4PerpEdit,
+ MangoV4PerpEditV23,
MangoV4OpenBookRegisterMarket,
MangoV4OpenBookEditMarket,
MangoV4TokenEdit,
+ MangoV4TokenEditV23,
MangoV4TokenRegister,
+ MangoV4TokenRegisterV23,
MangoV4TokenRegisterTrustless,
MangoV4GroupEdit,
+ MangoV4GroupEditV23,
IdlSetBuffer,
MangoV4IxGateSet,
+ MangoV4IxGateSetV23,
MangoV4AltSet,
MangoV4AltExtend,
MangoV4StubOracleCreate,
@@ -488,7 +494,7 @@ export interface DualFinanceStakingOptionForm {
strike: number
soName: string | undefined
optionExpirationUnixSeconds: number
- numTokens: number
+ numTokens: string
lotSize: number
baseTreasury: AssetAccount | undefined
quoteTreasury: AssetAccount | undefined
@@ -504,6 +510,7 @@ export interface DualFinanceGsoForm {
lotSize: number
subscriptionPeriodEnd: number
lockupRatio: number
+ lockupMint: string
baseTreasury: AssetAccount | undefined
quoteTreasury: AssetAccount | undefined
payer: AssetAccount | undefined
diff --git a/utils/validations.tsx b/utils/validations.tsx
index 4a8bb1f2af..c6a5324220 100644
--- a/utils/validations.tsx
+++ b/utils/validations.tsx
@@ -510,9 +510,9 @@ export const getDualFinanceGovernanceAirdropSchema = ({
),
treasury: yup.object().typeError('Treasury is required'),
amount: yup
- .number()
+ .string()
.typeError('Amount is required')
- .test('amount', 'amount', async function (val: number) {
+ .test('amount', 'amount', async function (val: string) {
if (!form.treasury) {
return this.createError({
message: `Please select a treasury`,
@@ -520,8 +520,8 @@ export const getDualFinanceGovernanceAirdropSchema = ({
}
const numAtomsInTreasury = new BN(
form.treasury.extensions.token.account.amount
- ).toNumber()
- if (numAtomsInTreasury < val) {
+ )
+ if (numAtomsInTreasury.lt(new BN(val))) {
return this.createError({
message: `Not enough tokens`,
})
@@ -584,9 +584,9 @@ export const getDualFinanceMerkleAirdropSchema = ({ form }: { form: any }) => {
),
treasury: yup.object().typeError('Treasury is required'),
amount: yup
- .number()
+ .string()
.typeError('Amount is required')
- .test('amount', 'amount', async function (val: number) {
+ .test('amount', 'amount', async function (val: string) {
if (!form.treasury) {
return this.createError({
message: `Please select a treasury`,
@@ -594,8 +594,8 @@ export const getDualFinanceMerkleAirdropSchema = ({ form }: { form: any }) => {
}
const numAtomsInTreasury = new BN(
form.treasury.extensions.token.account.amount
- ).toNumber()
- if (numAtomsInTreasury < val) {
+ )
+ if (numAtomsInTreasury.lt(new BN(val))) {
return this.createError({
message: `Not enough tokens`,
})
@@ -634,9 +634,9 @@ export const getDualFinanceLiquidityStakingOptionSchema = ({
}
),
numTokens: yup
- .number()
+ .string()
.typeError('Num tokens is required')
- .test('amount', 'amount', async function (val: number) {
+ .test('amount', 'amount', async function (val: string) {
if (!form.baseTreasury) {
return this.createError({
message: `Please select a treasury`,
@@ -644,8 +644,8 @@ export const getDualFinanceLiquidityStakingOptionSchema = ({
}
const numAtomsInTreasury = new BN(
form.baseTreasury.extensions.token.account.amount
- ).toNumber()
- if (numAtomsInTreasury < val) {
+ )
+ if (numAtomsInTreasury.lt(new BN(val))) {
return this.createError({
message: `Not enough tokens`,
})
@@ -716,9 +716,9 @@ export const getDualFinanceStakingOptionSchema = ({
}
),
numTokens: yup
- .number()
+ .string()
.typeError('Num tokens is required')
- .test('amount', 'amount', async function (val: number) {
+ .test('amount', 'amount', async function (val: string) {
if (!form.baseTreasury) {
return this.createError({
message: `Please select a treasury`,
@@ -726,8 +726,8 @@ export const getDualFinanceStakingOptionSchema = ({
}
const numAtomsInTreasury = new BN(
form.baseTreasury.extensions.token.account.amount
- ).toNumber()
- if (numAtomsInTreasury < val) {
+ )
+ if (numAtomsInTreasury.lt(new BN(val))) {
return this.createError({
message: `Not enough tokens`,
})
@@ -775,9 +775,9 @@ export const getDualFinanceGsoSchema = ({ form }: { form: any }) => {
}
),
numTokens: yup
- .number()
+ .string()
.typeError('Num tokens is required')
- .test('amount', 'amount', async function (val: number) {
+ .test('amount', 'amount', async function (val: string) {
if (!form.baseTreasury) {
return this.createError({
message: `Please select a treasury`,
@@ -785,8 +785,8 @@ export const getDualFinanceGsoSchema = ({ form }: { form: any }) => {
}
const numAtomsInTreasury = new BN(
form.baseTreasury.extensions.token.account.amount
- ).toNumber()
- if (numAtomsInTreasury < val) {
+ )
+ if (numAtomsInTreasury.lt(new BN(val))) {
return this.createError({
message: `Not enough tokens`,
})
@@ -874,11 +874,7 @@ export const getDualFinanceDelegateWithdrawSchema = () => {
export const getDualFinanceVoteDepositSchema = () => {
return yup.object().shape({
numTokens: yup.number().typeError('Num tokens is required'),
- realm: yup
- .string()
- .test('is-valid-address1', 'Please enter a valid PublicKey', (value) =>
- value ? validatePubkey(value) : true
- ),
+ realm: yup.string(),
token: yup.object().typeError('Delegate Token is required'),
})
}
diff --git a/yarn.lock b/yarn.lock
index 0150df6a32..00711f2417 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -280,10 +280,10 @@
core-js-pure "^3.25.1"
regenerator-runtime "^0.13.11"
-"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.1", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.5", "@babel/runtime@^7.11.1", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.15.4", "@babel/runtime@^7.17.2", "@babel/runtime@^7.17.8", "@babel/runtime@^7.18.3", "@babel/runtime@^7.19.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.2", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
- version "7.22.10"
- resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.10.tgz#ae3e9631fd947cb7e3610d3e9d8fef5f76696682"
- integrity sha512-21t/fkKLMZI4pqP2wlmsQAWnYW1PDyKyyUV4vCi+B25ydmdaYTKXPwCj0BzSUnZf4seIiYvSA3jcZ3gdsMFkLQ==
+"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.1", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.5", "@babel/runtime@^7.11.1", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.15.4", "@babel/runtime@^7.17.2", "@babel/runtime@^7.17.8", "@babel/runtime@^7.18.3", "@babel/runtime@^7.19.4", "@babel/runtime@^7.22.6", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.2", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
+ version "7.23.6"
+ resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.6.tgz#c05e610dc228855dc92ef1b53d07389ed8ab521d"
+ integrity sha512-zHd0eUrf5GZoOWVCXp6koAKQTfZV07eit6bGPmJgnZdnSAvvZee6zniW2XMF7Cmc4ISOOnPy3QaSiIJGJkVEDQ==
dependencies:
regenerator-runtime "^0.14.0"
@@ -337,10 +337,32 @@
keccak256 "^1.0.6"
merkletreejs "^0.3.11"
-"@blockworks-foundation/mango-v4-settings@0.3.1":
- version "0.3.1"
- resolved "https://registry.yarnpkg.com/@blockworks-foundation/mango-v4-settings/-/mango-v4-settings-0.3.1.tgz#0c1c0458a384346da18d55b1051c910e4cf6bd91"
- integrity sha512-dADriziRtDliXOUFs6PdmUOu2trT4KrRHJsmlGw1BolfM5CafoFT85pDutZNHK5Vy1jn1TKqewyATREgTToH+w==
+"@blockworks-foundation/mango-v4-rc@npm:@blockworks-foundation/mango-v4@0.23.0-rc1":
+ version "0.23.0-rc1"
+ resolved "https://registry.yarnpkg.com/@blockworks-foundation/mango-v4/-/mango-v4-0.23.0-rc1.tgz#a4eed291c7ac1e6d02bbad228d917e34ad2149c0"
+ integrity sha512-U+F1SAr35TVsKz48W5iYanEIFxttfEVYV0uwDUhXz9HWbHctKYuZH0RyUb9y7xyI6vDBn/z/87FmFiV8meVlyQ==
+ dependencies:
+ "@blockworks-foundation/mango-v4-settings" "0.14.15"
+ "@blockworks-foundation/mangolana" "0.0.14"
+ "@coral-xyz/anchor" "^0.28.1-beta.2"
+ "@project-serum/serum" "0.13.65"
+ "@pythnetwork/client" "~2.14.0"
+ "@solana/spl-token" "0.3.7"
+ "@solana/web3.js" "^1.78.2"
+ "@switchboard-xyz/sbv2-lite" "^0.1.6"
+ big.js "^6.1.1"
+ binance-api-node "^0.12.0"
+ bs58 "^5.0.0"
+ cross-fetch "^3.1.5"
+ dotenv "^16.0.3"
+ fast-copy "^3.0.1"
+ lodash "^4.17.21"
+ node-kraken-api "^2.2.2"
+
+"@blockworks-foundation/mango-v4-settings@0.14.15":
+ version "0.14.15"
+ resolved "https://registry.yarnpkg.com/@blockworks-foundation/mango-v4-settings/-/mango-v4-settings-0.14.15.tgz#0ac04f2cffbd27a4129bc2086ec1418e29393880"
+ integrity sha512-GBo43KCosdaohbtS3Rtz8e2zsLsiN3JqTfLKVtStRYO3f2tQLzeo/D2Khz07psw2egq6TCNZJH7+v32iGrPq0w==
dependencies:
bn.js "^5.2.1"
eslint-config-prettier "^9.0.0"
@@ -353,12 +375,13 @@
bn.js "^5.2.1"
eslint-config-prettier "^9.0.0"
-"@blockworks-foundation/mango-v4@0.21.0":
- version "0.21.0"
- resolved "https://registry.yarnpkg.com/@blockworks-foundation/mango-v4/-/mango-v4-0.21.0.tgz#b3959e201817222da60e8a6d3ba84147242e1439"
- integrity sha512-UIF+hQGSsLFKoRAPWolZgPef/r5WB1s9wBdTqLHlU1oUAWXcOw1ZzpSvPzyF2RosGm5k/NdYsL1ONwENSWxl6A==
+"@blockworks-foundation/mango-v4@0.21.22":
+ version "0.21.22"
+ resolved "https://registry.yarnpkg.com/@blockworks-foundation/mango-v4/-/mango-v4-0.21.22.tgz#cf399225b995f3d82edc523f5af03c004c9369ec"
+ integrity sha512-n+aSuqlmv6lofmpkLCs4mNF5E7jBGD4UTKE3XfJNUVeV0Vh6E3dihraT26ZkrHCW+woNPWa+26vmd3X3bk4t+w==
dependencies:
"@blockworks-foundation/mango-v4-settings" "^0.2.16"
+ "@blockworks-foundation/mangolana" "0.0.13"
"@coral-xyz/anchor" "^0.28.1-beta.2"
"@project-serum/serum" "0.13.65"
"@pythnetwork/client" "~2.14.0"
@@ -370,17 +393,31 @@
bs58 "^5.0.0"
cross-fetch "^3.1.5"
dotenv "^16.0.3"
+ fast-copy "^3.0.1"
lodash "^4.17.21"
node-kraken-api "^2.2.2"
-"@blockworks-foundation/mangolana@0.0.1-beta.15":
- version "0.0.1-beta.15"
- resolved "https://registry.yarnpkg.com/@blockworks-foundation/mangolana/-/mangolana-0.0.1-beta.15.tgz#5442044ecb54c2f57128155665c0b1d9ecbdda39"
- integrity sha512-VDSRGHhrtR4nyjGEqQGLBLWbQLFn1Kh1SoaqwwV3De0Ls0WDhe8C5aTDQ8k028XKrlHRC5O1QkJrwWskqKvqNw==
+"@blockworks-foundation/mangolana@0.0.13":
+ version "0.0.13"
+ resolved "https://registry.yarnpkg.com/@blockworks-foundation/mangolana/-/mangolana-0.0.13.tgz#82a9b0846e69068de6216d20fcdcd60375d14e1e"
+ integrity sha512-/QPMHjtPpAYaDPbQVLolp5Lq4cCd77b8gBumws97L3J0DfvsKpZVYeAA0fNmSX6qq+pKqCgCywDjJeYhJ01PsQ==
dependencies:
- "@solana/web3.js" "^1.63.1"
+ "@solana/web3.js" "^1.88.0"
bs58 "^5.0.0"
- node-fetch "^3.2.10"
+ isomorphic-ws "^5.0.0"
+ node-fetch "2.6.11"
+ ws "^8.16.0"
+
+"@blockworks-foundation/mangolana@0.0.14":
+ version "0.0.14"
+ resolved "https://registry.yarnpkg.com/@blockworks-foundation/mangolana/-/mangolana-0.0.14.tgz#f2a0e164f2cbe6e0a0db4fc10267e81ef5d2f7ec"
+ integrity sha512-KuA2+GdeKoHCBmx2HZnVb8IPomUP1w0ZiwQ1F10SLIypYfrylvPa+HSK2ak/+nzZCb8erS9Oub45UPV7cOh5ng==
+ dependencies:
+ "@solana/web3.js" "^1.88.0"
+ bs58 "^5.0.0"
+ isomorphic-ws "^5.0.0"
+ node-fetch "2.6.11"
+ ws "^8.16.0"
"@blocto/sdk@^0.2.22":
version "0.2.22"
@@ -765,7 +802,27 @@
superstruct "^0.15.4"
toml "^3.0.0"
-"@coral-xyz/borsh@0.27.0", "@coral-xyz/borsh@^0.26.0", "@coral-xyz/borsh@^0.27.0", "@coral-xyz/borsh@^0.28.0":
+"@coral-xyz/anchor@^0.29.0":
+ version "0.29.0"
+ resolved "https://registry.yarnpkg.com/@coral-xyz/anchor/-/anchor-0.29.0.tgz#bd0be95bedfb30a381c3e676e5926124c310ff12"
+ integrity sha512-eny6QNG0WOwqV0zQ7cs/b1tIuzZGmP7U7EcH+ogt4Gdbl8HDmIYVMh/9aTmYZPaFWjtUaI8qSn73uYEXWfATdA==
+ dependencies:
+ "@coral-xyz/borsh" "^0.29.0"
+ "@noble/hashes" "^1.3.1"
+ "@solana/web3.js" "^1.68.0"
+ bn.js "^5.1.2"
+ bs58 "^4.0.1"
+ buffer-layout "^1.2.2"
+ camelcase "^6.3.0"
+ cross-fetch "^3.1.5"
+ crypto-hash "^1.3.0"
+ eventemitter3 "^4.0.7"
+ pako "^2.0.3"
+ snake-case "^3.0.4"
+ superstruct "^0.15.4"
+ toml "^3.0.0"
+
+"@coral-xyz/borsh@0.27.0", "@coral-xyz/borsh@^0.26.0", "@coral-xyz/borsh@^0.27.0", "@coral-xyz/borsh@^0.28.0", "@coral-xyz/borsh@^0.29.0":
version "0.27.0"
resolved "https://registry.yarnpkg.com/@coral-xyz/borsh/-/borsh-0.27.0.tgz#700c647ea5262b1488957ac7fb4e8acf72c72b63"
integrity sha512-tJKzhLukghTWPLy+n8K8iJKgBq1yLT/AxaNd10yJrX8mI56ao5+OFAKAqW/h0i79KCvb4BK0VGO5ECmmolFz9A==
@@ -862,10 +919,10 @@
"@solana/web3.js" "^1.73.2"
js-sha3 "^0.8.0"
-"@dual-finance/gso@0.0.14":
- version "0.0.14"
- resolved "https://registry.yarnpkg.com/@dual-finance/gso/-/gso-0.0.14.tgz#48990ae01295453d4428f6dbea2b83e73d0d9232"
- integrity sha512-DjnP/VkT64oNaiyyHrtzwuCe4jEiFkt+9XTfJeLs88TmyUPULel/xmt4PQP2gzjCFrKcj160C+Sb7Q3SjaQB4w==
+"@dual-finance/gso@0.0.17":
+ version "0.0.17"
+ resolved "https://registry.yarnpkg.com/@dual-finance/gso/-/gso-0.0.17.tgz#b547bc722c7e924be20dd424acb048739ccb3bdb"
+ integrity sha512-SatlyKfQq185FVWfzOu62IDorCiS/5+JMbnNybgZuI9f2/Sz/WU7ybY4Z7MZz4u8fK6ZWkLQEU3Mfmki/opBzA==
dependencies:
"@dual-finance/staking-options" "^0.0.17"
"@project-serum/anchor" "^0.25.0"
@@ -1627,6 +1684,11 @@
bs58 "^5.0.0"
ramda "^0.27.1"
+"@ioredis/commands@^1.1.1":
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/@ioredis/commands/-/commands-1.2.0.tgz#6d61b3097470af1fdbbe622795b8921d42018e11"
+ integrity sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==
+
"@istanbuljs/load-nyc-config@^1.0.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced"
@@ -1846,13 +1908,13 @@
"@types/yargs" "^17.0.8"
chalk "^4.0.0"
-"@jnwng/walletconnect-solana@^0.1.5":
- version "0.1.5"
- resolved "https://registry.yarnpkg.com/@jnwng/walletconnect-solana/-/walletconnect-solana-0.1.5.tgz#54d71c0667fe317376490c337c36d0d19da95e5a"
- integrity sha512-n8YLfF6NIVOqn+YeJEFRaZbbeNTGXL+VPBl+hqMpxLH+Fp+qgdm4CYH+ULH/OSszL2DBO1j+hB/XFDPiswCNeA==
+"@jnwng/walletconnect-solana@^0.2.0":
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/@jnwng/walletconnect-solana/-/walletconnect-solana-0.2.0.tgz#aebea64beaa47273b9b9a71c62d88d543900ab96"
+ integrity sha512-nyRq0xLEj9i2J4UXQ0Mr4KzsooTMbLu0ewHOqdQV7iZE0PfbtKa8poTSF4ZBAQD8hoMHEx+I7zGFCNMI9BTrTA==
dependencies:
"@walletconnect/qrcode-modal" "^1.8.0"
- "@walletconnect/sign-client" "^2.4.5"
+ "@walletconnect/sign-client" "^2.7.2"
"@walletconnect/utils" "^2.4.5"
bs58 "^5.0.0"
@@ -1873,22 +1935,27 @@
"@jridgewell/sourcemap-codec" "^1.4.10"
"@jridgewell/trace-mapping" "^0.3.9"
-"@jridgewell/resolve-uri@3.1.0", "@jridgewell/resolve-uri@^3.0.3":
+"@jridgewell/resolve-uri@3.1.0":
version "3.1.0"
resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78"
integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==
+"@jridgewell/resolve-uri@^3.0.3":
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721"
+ integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==
+
"@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72"
integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==
-"@jridgewell/sourcemap-codec@1.4.14", "@jridgewell/sourcemap-codec@^1.4.10":
+"@jridgewell/sourcemap-codec@1.4.14":
version "1.4.14"
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24"
integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==
-"@jridgewell/sourcemap-codec@^1.4.13":
+"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.13":
version "1.4.15"
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32"
integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==
@@ -2543,20 +2610,22 @@
dependencies:
"@react-spring/web" "9.3.1"
-"@noble/ed25519@^1.6.1", "@noble/ed25519@^1.7.0", "@noble/ed25519@^1.7.1":
+"@noble/curves@^1.0.0":
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.3.0.tgz#01be46da4fd195822dab821e72f71bf4aeec635e"
+ integrity sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA==
+ dependencies:
+ "@noble/hashes" "1.3.3"
+
+"@noble/ed25519@^1.6.1", "@noble/ed25519@^1.7.1":
version "1.7.3"
resolved "https://registry.yarnpkg.com/@noble/ed25519/-/ed25519-1.7.3.tgz#57e1677bf6885354b466c38e2b620c62f45a7123"
integrity sha512-iR8GBkDt0Q3GyaVcIu7mSsVIqnFbkbRzGLWlvhwunacoLwt4J3swfKhfaM6rN6WY+TBGoYT1GtT1mIh2/jGbRQ==
-"@noble/hashes@^1.1.2", "@noble/hashes@^1.1.3", "@noble/hashes@^1.3.1":
- version "1.3.2"
- resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.2.tgz#6f26dbc8fbc7205873ce3cee2f690eba0d421b39"
- integrity sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==
-
-"@noble/secp256k1@^1.6.3":
- version "1.7.1"
- resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-1.7.1.tgz#b251c70f824ce3ca7f8dc3df08d58f005cc0507c"
- integrity sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==
+"@noble/hashes@1.3.3", "@noble/hashes@^1.1.3", "@noble/hashes@^1.3.0", "@noble/hashes@^1.3.1":
+ version "1.3.3"
+ resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.3.tgz#39908da56a4adc270147bb07968bf3b16cfe1699"
+ integrity sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==
"@nodelib/fs.scandir@2.1.5":
version "2.1.5"
@@ -2630,6 +2699,98 @@
node-gyp "^7.1.0"
read-package-json-fast "^2.0.1"
+"@parcel/watcher-android-arm64@2.4.0":
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.4.0.tgz#9c93763794153e4f76920994a423b6ea3257059d"
+ integrity sha512-+fPtO/GsbYX1LJnCYCaDVT3EOBjvSFdQN9Mrzh9zWAOOfvidPWyScTrHIZHHfJBvlHzNA0Gy0U3NXFA/M7PHUA==
+
+"@parcel/watcher-darwin-arm64@2.4.0":
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.4.0.tgz#2c79c2abde16aa24cac67e555b60802fd13fe210"
+ integrity sha512-T/At5pansFuQ8VJLRx0C6C87cgfqIYhW2N/kBfLCUvDhCah0EnLLwaD/6MW3ux+rpgkpQAnMELOCTKlbwncwiA==
+
+"@parcel/watcher-darwin-x64@2.4.0":
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.4.0.tgz#23d82f198c5d033f047467c68d7c335f3df49b46"
+ integrity sha512-vZMv9jl+szz5YLsSqEGCMSllBl1gU1snfbRL5ysJU03MEa6gkVy9OMcvXV1j4g0++jHEcvzhs3Z3LpeEbVmY6Q==
+
+"@parcel/watcher-freebsd-x64@2.4.0":
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.4.0.tgz#7310cc86abc27dacd57624bcdba1f0ba092e76df"
+ integrity sha512-dHTRMIplPDT1M0+BkXjtMN+qLtqq24sLDUhmU+UxxLP2TEY2k8GIoqIJiVrGWGomdWsy5IO27aDV1vWyQ6gfHA==
+
+"@parcel/watcher-linux-arm-glibc@2.4.0":
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.4.0.tgz#c31b76e695027eeb1078d3d6f1d641d0b900c335"
+ integrity sha512-9NQXD+qk46RwATNC3/UB7HWurscY18CnAPMTFcI9Y8CTbtm63/eex1SNt+BHFinEQuLBjaZwR2Lp+n7pmEJPpQ==
+
+"@parcel/watcher-linux-arm64-glibc@2.4.0":
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.4.0.tgz#56e09b86e9d8a4096f606be118b588da6e965080"
+ integrity sha512-QuJTAQdsd7PFW9jNGaV9Pw+ZMWV9wKThEzzlY3Lhnnwy7iW23qtQFPql8iEaSFMCVI5StNNmONUopk+MFKpiKg==
+
+"@parcel/watcher-linux-arm64-musl@2.4.0":
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.4.0.tgz#27ffd5ca5f510ecd638f9ad22e2e813049db54e7"
+ integrity sha512-oyN+uA9xcTDo/45bwsd6TFHa7Lc7hKujyMlvwrCLvSckvWogndCEoVYFNfZ6JJ2KNL/6fFiGPcbjp8jJmEh5Ng==
+
+"@parcel/watcher-linux-x64-glibc@2.4.0":
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.4.0.tgz#44cbbb1e5884a1ca900655f47a0775218318f934"
+ integrity sha512-KphV8awJmxU3q52JQvJot0QMu07CIyEjV+2Tb2ZtbucEgqyRcxOBDMsqp1JNq5nuDXtcCC0uHQICeiEz38dPBQ==
+
+"@parcel/watcher-linux-x64-musl@2.4.0":
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.4.0.tgz#4c33993618c8d5113722852806239cb80360494b"
+ integrity sha512-7jzcOonpXNWcSijPpKD5IbC6xC7yTibjJw9jviVzZostYLGxbz8LDJLUnLzLzhASPlPGgpeKLtFUMjAAzM+gSA==
+
+"@parcel/watcher-wasm@2.4.0":
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/@parcel/watcher-wasm/-/watcher-wasm-2.4.0.tgz#84a3959c8ef1cd67b36b9fec487edbc8f27719f6"
+ integrity sha512-MNgQ4WCbBybqQ97KwR/hqJGYTg3+s8qHpgIyFWB2qJOBvoJWbXuJGmm4ZkPLq2bMaANqCZqrXwmKYagZTkMKZA==
+ dependencies:
+ is-glob "^4.0.3"
+ micromatch "^4.0.5"
+ napi-wasm "^1.1.0"
+
+"@parcel/watcher-win32-arm64@2.4.0":
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.4.0.tgz#2a172fd2fda95fe5389298ca3e70b5a96316162a"
+ integrity sha512-NOej2lqlq8bQNYhUMnOD0nwvNql8ToQF+1Zhi9ULZoG+XTtJ9hNnCFfyICxoZLXor4bBPTOnzs/aVVoefYnjIg==
+
+"@parcel/watcher-win32-ia32@2.4.0":
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.4.0.tgz#279225b2ebe1fadd3c5137c9b2365ad422656904"
+ integrity sha512-IO/nM+K2YD/iwjWAfHFMBPz4Zqn6qBDqZxY4j2n9s+4+OuTSRM/y/irksnuqcspom5DjkSeF9d0YbO+qpys+JA==
+
+"@parcel/watcher-win32-x64@2.4.0":
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.4.0.tgz#93e0bd0ad1bda2c9a688764b9b30b71dc5b72a71"
+ integrity sha512-pAUyUVjfFjWaf/pShmJpJmNxZhbMvJASUpdes9jL6bTEJ+gDxPRSpXTIemNyNsb9AtbiGXs9XduP1reThmd+dA==
+
+"@parcel/watcher@^2.4.0":
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/@parcel/watcher/-/watcher-2.4.0.tgz#2d3c4ef8832a5cdfdbb76b914f022489933e664f"
+ integrity sha512-XJLGVL0DEclX5pcWa2N9SX1jCGTDd8l972biNooLFtjneuGqodupPQh6XseXIBBeVIMaaJ7bTcs3qGvXwsp4vg==
+ dependencies:
+ detect-libc "^1.0.3"
+ is-glob "^4.0.3"
+ micromatch "^4.0.5"
+ node-addon-api "^7.0.0"
+ optionalDependencies:
+ "@parcel/watcher-android-arm64" "2.4.0"
+ "@parcel/watcher-darwin-arm64" "2.4.0"
+ "@parcel/watcher-darwin-x64" "2.4.0"
+ "@parcel/watcher-freebsd-x64" "2.4.0"
+ "@parcel/watcher-linux-arm-glibc" "2.4.0"
+ "@parcel/watcher-linux-arm64-glibc" "2.4.0"
+ "@parcel/watcher-linux-arm64-musl" "2.4.0"
+ "@parcel/watcher-linux-x64-glibc" "2.4.0"
+ "@parcel/watcher-linux-x64-musl" "2.4.0"
+ "@parcel/watcher-win32-arm64" "2.4.0"
+ "@parcel/watcher-win32-ia32" "2.4.0"
+ "@parcel/watcher-win32-x64" "2.4.0"
+
"@particle-network/auth@^0.5.5":
version "0.5.6"
resolved "https://registry.yarnpkg.com/@particle-network/auth/-/auth-0.5.6.tgz#058e00980511fdf72189b6d4a7576e67934a008a"
@@ -2722,26 +2883,6 @@
snake-case "^3.0.4"
toml "^3.0.0"
-"@project-serum/anchor@0.24.2", "@project-serum/anchor@^0.24.2":
- version "0.24.2"
- resolved "https://registry.yarnpkg.com/@project-serum/anchor/-/anchor-0.24.2.tgz#a3c52a99605c80735f446ca9b3a4885034731004"
- integrity sha512-0/718g8/DnEuwAidUwh5wLYphUYXhUbiClkuRNhvNoa+1Y8a4g2tJyxoae+emV+PG/Gikd/QUBNMkIcimiIRTA==
- dependencies:
- "@project-serum/borsh" "^0.2.5"
- "@solana/web3.js" "^1.36.0"
- base64-js "^1.5.1"
- bn.js "^5.1.2"
- bs58 "^4.0.1"
- buffer-layout "^1.2.2"
- camelcase "^5.3.1"
- cross-fetch "^3.1.5"
- crypto-hash "^1.3.0"
- eventemitter3 "^4.0.7"
- js-sha256 "^0.9.0"
- pako "^2.0.3"
- snake-case "^3.0.4"
- toml "^3.0.0"
-
"@project-serum/anchor@0.26.0":
version "0.26.0"
resolved "https://registry.yarnpkg.com/@project-serum/anchor/-/anchor-0.26.0.tgz#99e15a3923a5d10514f8185b2d3909e5699d60d5"
@@ -2824,6 +2965,26 @@
snake-case "^3.0.4"
toml "^3.0.0"
+"@project-serum/anchor@^0.24.2":
+ version "0.24.2"
+ resolved "https://registry.yarnpkg.com/@project-serum/anchor/-/anchor-0.24.2.tgz#a3c52a99605c80735f446ca9b3a4885034731004"
+ integrity sha512-0/718g8/DnEuwAidUwh5wLYphUYXhUbiClkuRNhvNoa+1Y8a4g2tJyxoae+emV+PG/Gikd/QUBNMkIcimiIRTA==
+ dependencies:
+ "@project-serum/borsh" "^0.2.5"
+ "@solana/web3.js" "^1.36.0"
+ base64-js "^1.5.1"
+ bn.js "^5.1.2"
+ bs58 "^4.0.1"
+ buffer-layout "^1.2.2"
+ camelcase "^5.3.1"
+ cross-fetch "^3.1.5"
+ crypto-hash "^1.3.0"
+ eventemitter3 "^4.0.7"
+ js-sha256 "^0.9.0"
+ pako "^2.0.3"
+ snake-case "^3.0.4"
+ toml "^3.0.0"
+
"@project-serum/anchor@^0.25.0":
version "0.25.0"
resolved "https://registry.yarnpkg.com/@project-serum/anchor/-/anchor-0.25.0.tgz#88ee4843336005cf5a64c80636ce626f0996f503"
@@ -2961,16 +3122,16 @@
resolved "https://registry.yarnpkg.com/@pythnetwork/staking-wasm/-/staking-wasm-0.3.4.tgz#29c0f47467249a4c66814a8aab9eadf2cc008add"
integrity sha512-0ZdaWmueVO5hucdVH4UDfHyBuxtW6UDcrpEFtD/3pq4naQjcgu1u6rK8iL2pgKi8W2UlsB4vwJqay2Sf1sA4mw==
-"@pythnetwork/staking@^2.0.0":
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/@pythnetwork/staking/-/staking-2.0.0.tgz#41edcb000a3c2d1db938a3017dae46f54aac061e"
- integrity sha512-7RPcsYfEJxGZ12P+OyQ1lfXxgcoe69N0Zftj525GaxUDMBvCXtNSQM+FuskF8y/GKHifZ+CDI8eP3w26gv0ZzQ==
+"@pythnetwork/staking@^2.1.0":
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/@pythnetwork/staking/-/staking-2.1.0.tgz#7c38357cf539f7c044f18507971eb9547d955917"
+ integrity sha512-hw+FJ7TrpJ0X1ixCmKnCUsFitSYgQ3xf9OxFJM5gKp6eHxv5oC/6Thc6dOkCCsw67xTfHC6fOm2WxfwoA6bTVw==
dependencies:
- "@project-serum/anchor" "0.24.2"
+ "@coral-xyz/anchor" "^0.29.0"
"@pythnetwork/staking-wasm" "*"
"@solana/spl-governance" "0.3.26"
"@solana/spl-token" "^0.1.8"
- "@solana/web3.js" "^1.36.0"
+ "@solana/web3.js" "^1.87.5"
encoding "^0.1.13"
ts-node "^10.7.0"
typescript "^4.3.5"
@@ -4161,6 +4322,18 @@
js-sha3 "^0.8.0"
typescript-collections "^1.3.3"
+"@solana/spl-account-compression@~0.2.0":
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/@solana/spl-account-compression/-/spl-account-compression-0.2.0.tgz#a8a28a3985b50d0391bfd6374345e9d36eb8f792"
+ integrity sha512-nHpa+hTUpjLdV9x4LXlp7k0WIkr8kUGjY/SPh+vuTUy4SEIIDjrGJ6/B0hUdd8+mFfrq2x4j/tgJvPsm4K5AJw==
+ dependencies:
+ "@metaplex-foundation/beet" "^0.7.1"
+ "@metaplex-foundation/beet-solana" "^0.4.0"
+ bn.js "^5.2.1"
+ borsh "^0.7.0"
+ js-sha3 "^0.8.0"
+ typescript-collections "^1.3.3"
+
"@solana/spl-governance@0.3.26":
version "0.3.26"
resolved "https://registry.yarnpkg.com/@solana/spl-governance/-/spl-governance-0.3.26.tgz#1a6c56037063654d243cc3ee9503b5b3140bbd6f"
@@ -4245,7 +4418,7 @@
dependencies:
"@solana/wallet-adapter-base" "^0.9.22"
-"@solana/wallet-adapter-base@0.9.22", "@solana/wallet-adapter-base@^0.9.17", "@solana/wallet-adapter-base@^0.9.2", "@solana/wallet-adapter-base@^0.9.21", "@solana/wallet-adapter-base@^0.9.22":
+"@solana/wallet-adapter-base@0.9.22":
version "0.9.22"
resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-base/-/wallet-adapter-base-0.9.22.tgz#97812eaf6aebe01e5fe714326b3c9a0614ae6112"
integrity sha512-xbLEZPGSJFvgTeldG9D55evhl7QK/3e/F7vhvcA97mEt1eieTgeKMnGlmmjs3yivI3/gtZNZeSk1XZLnhKcQvw==
@@ -4255,6 +4428,16 @@
"@wallet-standard/features" "^1.0.3"
eventemitter3 "^4.0.7"
+"@solana/wallet-adapter-base@^0.9.17", "@solana/wallet-adapter-base@^0.9.2", "@solana/wallet-adapter-base@^0.9.21", "@solana/wallet-adapter-base@^0.9.22", "@solana/wallet-adapter-base@^0.9.23":
+ version "0.9.23"
+ resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-base/-/wallet-adapter-base-0.9.23.tgz#3b17c28afd44e173f44f658bf9700fd637e12a11"
+ integrity sha512-apqMuYwFp1jFi55NxDfvXUX2x1T0Zh07MxhZ/nCCTGys5raSfYUh82zen2BLv8BSDj/JxZ2P/s7jrQZGrX8uAw==
+ dependencies:
+ "@solana/wallet-standard-features" "^1.1.0"
+ "@wallet-standard/base" "^1.0.1"
+ "@wallet-standard/features" "^1.0.3"
+ eventemitter3 "^4.0.7"
+
"@solana/wallet-adapter-bitkeep@^0.3.18":
version "0.3.18"
resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-bitkeep/-/wallet-adapter-bitkeep-0.3.18.tgz#00e500d216b9d363bdb024aeb7eb8d7e33f584af"
@@ -4571,13 +4754,13 @@
dependencies:
"@solana/wallet-adapter-base" "^0.9.22"
-"@solana/wallet-adapter-walletconnect@0.1.14", "@solana/wallet-adapter-walletconnect@^0.1.14", "@solana/wallet-adapter-walletconnect@^0.1.6":
- version "0.1.14"
- resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-walletconnect/-/wallet-adapter-walletconnect-0.1.14.tgz#6994077781880b1a86fda27e000e947ed7764609"
- integrity sha512-nz8BB1Gs9s2yLuAf1+wDyZoGxCAVi1XWpzVlXMRBD7oL7Bn3kx3SOohzgoOKQltTrye4PF4cl+KCStzY3zQfkg==
+"@solana/wallet-adapter-walletconnect@0.1.16", "@solana/wallet-adapter-walletconnect@^0.1.14", "@solana/wallet-adapter-walletconnect@^0.1.6":
+ version "0.1.16"
+ resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-walletconnect/-/wallet-adapter-walletconnect-0.1.16.tgz#c335970ddec1247e546a4811fceb4f5edf9487de"
+ integrity sha512-jNaQwSho8hT7gF1ifePE8TJc1FULx8jCF16KX3fZPtzXDxKrj0R4VUpHMGcw4MlDknrnZNLOJAVvyiawAkPCRQ==
dependencies:
- "@jnwng/walletconnect-solana" "^0.1.5"
- "@solana/wallet-adapter-base" "^0.9.22"
+ "@jnwng/walletconnect-solana" "^0.2.0"
+ "@solana/wallet-adapter-base" "^0.9.23"
"@solana/wallet-adapter-wallets@0.19.15":
version "0.19.15"
@@ -4644,10 +4827,10 @@
dependencies:
"@wallet-standard/base" "^1.0.0"
-"@solana/wallet-standard-features@^1.0.0", "@solana/wallet-standard-features@^1.0.1":
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/@solana/wallet-standard-features/-/wallet-standard-features-1.0.1.tgz#36270a646f74a80e51b9e21fb360edb64f840c68"
- integrity sha512-SUfx7KtBJ55XIj0qAhhVcC1I6MklAXqWFEz9hDHW+6YcJIyvfix/EilBhaBik1FJ2JT0zukpOfFv8zpuAbFRbw==
+"@solana/wallet-standard-features@^1.0.0", "@solana/wallet-standard-features@^1.0.1", "@solana/wallet-standard-features@^1.1.0":
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/@solana/wallet-standard-features/-/wallet-standard-features-1.2.0.tgz#be8b3824abf5ebcfeaa7298445bf53f76a27c935"
+ integrity sha512-tUd9srDLkRpe1BYg7we+c4UhRQkq+XQWswsr/L1xfGmoRDF47BPSXf4zE7ZU2GRBGvxtGt7lwJVAufQyQYhxTQ==
dependencies:
"@wallet-standard/base" "^1.0.1"
"@wallet-standard/features" "^1.0.3"
@@ -4683,25 +4866,24 @@
"@wallet-standard/app" "^1.0.1"
"@wallet-standard/base" "^1.0.1"
-"@solana/web3.js@1.56.0", "@solana/web3.js@1.73.3", "@solana/web3.js@^1.17.0", "@solana/web3.js@^1.21.0", "@solana/web3.js@^1.22.0", "@solana/web3.js@^1.30.2", "@solana/web3.js@^1.31.0", "@solana/web3.js@^1.32.0", "@solana/web3.js@^1.35.1", "@solana/web3.js@^1.36.0", "@solana/web3.js@^1.37.1", "@solana/web3.js@^1.43.4", "@solana/web3.js@^1.44.3", "@solana/web3.js@^1.50.1", "@solana/web3.js@^1.56.2", "@solana/web3.js@^1.59.1", "@solana/web3.js@^1.63.0", "@solana/web3.js@^1.63.1", "@solana/web3.js@^1.66.2", "@solana/web3.js@^1.68.0", "@solana/web3.js@^1.73.0", "@solana/web3.js@^1.73.2", "@solana/web3.js@^1.77.3", "@solana/web3.js@^1.78.2", "@solana/web3.js@^1.78.3", "@solana/web3.js@^1.87.6":
- version "1.73.3"
- resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.73.3.tgz#60e6bd68f6f364d4be360b1e0a03a0a68468a029"
- integrity sha512-vHRMo589XEIpoujpE2sZZ1aMZvfA1ImKfNxobzEFyMb+H5j6mRRUXfdgWD0qJ0sm11e5BcBC7HPeRXJB+7f3Lg==
+"@solana/web3.js@1.56.0", "@solana/web3.js@1.78.2", "@solana/web3.js@^1.17.0", "@solana/web3.js@^1.21.0", "@solana/web3.js@^1.22.0", "@solana/web3.js@^1.30.2", "@solana/web3.js@^1.31.0", "@solana/web3.js@^1.32.0", "@solana/web3.js@^1.35.1", "@solana/web3.js@^1.36.0", "@solana/web3.js@^1.37.1", "@solana/web3.js@^1.43.4", "@solana/web3.js@^1.44.3", "@solana/web3.js@^1.50.1", "@solana/web3.js@^1.56.2", "@solana/web3.js@^1.59.1", "@solana/web3.js@^1.63.0", "@solana/web3.js@^1.63.1", "@solana/web3.js@^1.66.2", "@solana/web3.js@^1.68.0", "@solana/web3.js@^1.73.0", "@solana/web3.js@^1.73.2", "@solana/web3.js@^1.77.3", "@solana/web3.js@^1.78.2", "@solana/web3.js@^1.78.3", "@solana/web3.js@^1.87.5", "@solana/web3.js@^1.87.6", "@solana/web3.js@^1.88.0":
+ version "1.78.2"
+ resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.78.2.tgz#ae976ce2f793077aa104ab455f9f75be86a3e2a4"
+ integrity sha512-oF+TmBZCt3eAEl4Meu3GO2p6G8wdyoKgXgTKzQpIUIhpMGA/dVQzyMFpKjCgoTU1Kx+/UF3gXUdsZOxQukGbvQ==
dependencies:
- "@babel/runtime" "^7.12.5"
- "@noble/ed25519" "^1.7.0"
- "@noble/hashes" "^1.1.2"
- "@noble/secp256k1" "^1.6.3"
+ "@babel/runtime" "^7.22.6"
+ "@noble/curves" "^1.0.0"
+ "@noble/hashes" "^1.3.0"
"@solana/buffer-layout" "^4.0.0"
agentkeepalive "^4.2.1"
bigint-buffer "^1.1.5"
- bn.js "^5.0.0"
+ bn.js "^5.2.1"
borsh "^0.7.0"
bs58 "^4.0.1"
- buffer "6.0.1"
+ buffer "6.0.3"
fast-stable-stringify "^1.0.0"
- jayson "^3.4.4"
- node-fetch "^2.6.7"
+ jayson "^4.1.0"
+ node-fetch "^2.6.12"
rpc-websockets "^7.5.1"
superstruct "^0.14.2"
@@ -5140,9 +5322,9 @@
integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==
"@tsconfig/node16@^1.0.2":
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.3.tgz#472eaab5f15c1ffdd7f8628bd4c4f753995ec79e"
- integrity sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9"
+ integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==
"@types/aria-query@^4.2.0":
version "4.2.2"
@@ -5869,26 +6051,27 @@
"@walletconnect/window-metadata" "1.0.0"
detect-browser "5.2.0"
-"@walletconnect/core@2.4.7":
- version "2.4.7"
- resolved "https://registry.yarnpkg.com/@walletconnect/core/-/core-2.4.7.tgz#f1e2935eded3b882128a7fa6b56eff25221e6f2c"
- integrity sha512-w92NrtziqrWs070HJICGh80Vp60PaXu06OjNvOnVZEorbTipCWx4xxgcC2NhsT4TCQ8r1FOut6ahLe1PILuRsg==
- dependencies:
- "@walletconnect/heartbeat" "1.2.0"
- "@walletconnect/jsonrpc-provider" "^1.0.6"
- "@walletconnect/jsonrpc-utils" "^1.0.4"
- "@walletconnect/jsonrpc-ws-connection" "^1.0.7"
- "@walletconnect/keyvaluestorage" "^1.0.2"
+"@walletconnect/core@2.11.0":
+ version "2.11.0"
+ resolved "https://registry.yarnpkg.com/@walletconnect/core/-/core-2.11.0.tgz#3a4e301077b2f858fd916b7a20b5b984d1afce63"
+ integrity sha512-2Tjp5BCevI7dbmqo/OrCjX4tqgMqwJNQLlQAlphqPfvwlF9+tIu6pGcVbSN3U9zyXzWIZCeleqEaWUeSeET4Ew==
+ dependencies:
+ "@walletconnect/heartbeat" "1.2.1"
+ "@walletconnect/jsonrpc-provider" "1.0.13"
+ "@walletconnect/jsonrpc-types" "1.0.3"
+ "@walletconnect/jsonrpc-utils" "1.0.8"
+ "@walletconnect/jsonrpc-ws-connection" "1.0.14"
+ "@walletconnect/keyvaluestorage" "^1.1.1"
"@walletconnect/logger" "^2.0.1"
"@walletconnect/relay-api" "^1.0.9"
"@walletconnect/relay-auth" "^1.0.4"
- "@walletconnect/safe-json" "^1.0.1"
+ "@walletconnect/safe-json" "^1.0.2"
"@walletconnect/time" "^1.0.2"
- "@walletconnect/types" "2.4.7"
- "@walletconnect/utils" "2.4.7"
+ "@walletconnect/types" "2.11.0"
+ "@walletconnect/utils" "2.11.0"
events "^3.3.0"
+ isomorphic-unfetch "3.1.0"
lodash.isequal "4.5.0"
- pino "7.11.0"
uint8arrays "^3.1.0"
"@walletconnect/environment@^1.0.1":
@@ -5906,62 +6089,59 @@
keyvaluestorage-interface "^1.0.0"
tslib "1.14.1"
-"@walletconnect/heartbeat@1.2.0":
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/@walletconnect/heartbeat/-/heartbeat-1.2.0.tgz#1e87dd234cb72b0587b84f95c4f942f2b4bd0c79"
- integrity sha512-0vbzTa/ARrpmMmOD+bQMxPvFYKtOLQZObgZakrYr0aODiMOO71CmPVNV2eAqXnw9rMmcP+z91OybLeIFlwTjjA==
+"@walletconnect/heartbeat@1.2.1":
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/@walletconnect/heartbeat/-/heartbeat-1.2.1.tgz#afaa3a53232ae182d7c9cff41c1084472d8f32e9"
+ integrity sha512-yVzws616xsDLJxuG/28FqtZ5rzrTA4gUjdEMTbWB5Y8V1XHRmqq4efAxCw5ie7WjbXFSUyBHaWlMR+2/CpQC5Q==
dependencies:
"@walletconnect/events" "^1.0.1"
"@walletconnect/time" "^1.0.2"
- chai "^4.3.7"
- mocha "^10.2.0"
- ts-node "^10.9.1"
tslib "1.14.1"
-"@walletconnect/jsonrpc-provider@^1.0.6":
- version "1.0.8"
- resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-provider/-/jsonrpc-provider-1.0.8.tgz#d56e5bc95c1ec264748a6911389a3ac80f4bd831"
- integrity sha512-M44vzTrF0TeDcxQorm2lJ5klmfqchYOZqmIHb5T9lIPA/rj22643P83j44flZLyzycPqy5UUlIH6foeBPwjxMg==
+"@walletconnect/jsonrpc-provider@1.0.13":
+ version "1.0.13"
+ resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-provider/-/jsonrpc-provider-1.0.13.tgz#9a74da648d015e1fffc745f0c7d629457f53648b"
+ integrity sha512-K73EpThqHnSR26gOyNEL+acEex3P7VWZe6KE12ZwKzAt2H4e5gldZHbjsu2QR9cLeJ8AXuO7kEMOIcRv1QEc7g==
dependencies:
- "@walletconnect/jsonrpc-utils" "^1.0.6"
- "@walletconnect/safe-json" "^1.0.1"
+ "@walletconnect/jsonrpc-utils" "^1.0.8"
+ "@walletconnect/safe-json" "^1.0.2"
tslib "1.14.1"
-"@walletconnect/jsonrpc-types@^1.0.2":
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-types/-/jsonrpc-types-1.0.2.tgz#b79519f679cd6a5fa4a1bea888f27c1916689a20"
- integrity sha512-CZe8tjJX73OWdHjrBHy7HtAapJ2tT0Q3TYhPBhRxi3643lwPIQWC9En45ldY14TZwgSewkbZ0FtGBZK0G7Bbyg==
+"@walletconnect/jsonrpc-types@1.0.3", "@walletconnect/jsonrpc-types@^1.0.2", "@walletconnect/jsonrpc-types@^1.0.3":
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-types/-/jsonrpc-types-1.0.3.tgz#65e3b77046f1a7fa8347ae02bc1b841abe6f290c"
+ integrity sha512-iIQ8hboBl3o5ufmJ8cuduGad0CQm3ZlsHtujv9Eu16xq89q+BG7Nh5VLxxUgmtpnrePgFkTwXirCTkwJH1v+Yw==
dependencies:
keyvaluestorage-interface "^1.0.0"
tslib "1.14.1"
-"@walletconnect/jsonrpc-utils@^1.0.4", "@walletconnect/jsonrpc-utils@^1.0.6":
- version "1.0.6"
- resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-utils/-/jsonrpc-utils-1.0.6.tgz#7fa58e6671247e64e189828103282e6258f5330f"
- integrity sha512-snp0tfkjPiDLQp/jrBewI+9SM33GPV4+Gjgldod6XQ7rFyQ5FZjnBxUkY4xWH0+arNxzQSi6v5iDXjCjSaorpg==
+"@walletconnect/jsonrpc-utils@1.0.8", "@walletconnect/jsonrpc-utils@^1.0.6", "@walletconnect/jsonrpc-utils@^1.0.8":
+ version "1.0.8"
+ resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-utils/-/jsonrpc-utils-1.0.8.tgz#82d0cc6a5d6ff0ecc277cb35f71402c91ad48d72"
+ integrity sha512-vdeb03bD8VzJUL6ZtzRYsFMq1eZQcM3EAzT0a3st59dyLfJ0wq+tKMpmGH7HlB7waD858UWgfIcudbPFsbzVdw==
dependencies:
"@walletconnect/environment" "^1.0.1"
- "@walletconnect/jsonrpc-types" "^1.0.2"
+ "@walletconnect/jsonrpc-types" "^1.0.3"
tslib "1.14.1"
-"@walletconnect/jsonrpc-ws-connection@^1.0.7":
- version "1.0.9"
- resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-ws-connection/-/jsonrpc-ws-connection-1.0.9.tgz#38e089818e490cf52cfad9f98300949a74de9fdd"
- integrity sha512-x1COaW6hhMLEo+ND5zF/siBGg5SEwC/gHjeRbJtK1CRiq9atkg/XR7JwtSNfMvYX/O3PRCVmuc5SP0RQio9JUw==
+"@walletconnect/jsonrpc-ws-connection@1.0.14":
+ version "1.0.14"
+ resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-ws-connection/-/jsonrpc-ws-connection-1.0.14.tgz#eec700e74766c7887de2bd76c91a0206628732aa"
+ integrity sha512-Jsl6fC55AYcbkNVkwNM6Jo+ufsuCQRqViOQ8ZBPH9pRREHH9welbBiszuTLqEJiQcO/6XfFDl6bzCJIkrEi8XA==
dependencies:
"@walletconnect/jsonrpc-utils" "^1.0.6"
- "@walletconnect/safe-json" "^1.0.1"
+ "@walletconnect/safe-json" "^1.0.2"
events "^3.3.0"
- tslib "1.14.1"
ws "^7.5.1"
-"@walletconnect/keyvaluestorage@^1.0.2":
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/@walletconnect/keyvaluestorage/-/keyvaluestorage-1.0.2.tgz#92f5ca0f54c1a88a093778842ce0c874d86369c8"
- integrity sha512-U/nNG+VLWoPFdwwKx0oliT4ziKQCEoQ27L5Hhw8YOFGA2Po9A9pULUYNWhDgHkrb0gYDNt//X7wABcEWWBd3FQ==
+"@walletconnect/keyvaluestorage@^1.1.1":
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/@walletconnect/keyvaluestorage/-/keyvaluestorage-1.1.1.tgz#dd2caddabfbaf80f6b8993a0704d8b83115a1842"
+ integrity sha512-V7ZQq2+mSxAq7MrRqDxanTzu2RcElfK1PfNYiaVnJgJ7Q7G7hTVwF8voIBx92qsRyGHZihrwNPHuZd1aKkd0rA==
dependencies:
- safe-json-utils "^1.1.1"
- tslib "1.14.1"
+ "@walletconnect/safe-json" "^1.0.1"
+ idb-keyval "^6.2.1"
+ unstorage "^1.9.0"
"@walletconnect/logger@^2.0.1":
version "2.0.1"
@@ -6013,29 +6193,27 @@
resolved "https://registry.yarnpkg.com/@walletconnect/safe-json/-/safe-json-1.0.0.tgz#12eeb11d43795199c045fafde97e3c91646683b2"
integrity sha512-QJzp/S/86sUAgWY6eh5MKYmSfZaRpIlmCJdi5uG4DJlKkZrHEF7ye7gA+VtbVzvTtpM/gRwO2plQuiooIeXjfg==
-"@walletconnect/safe-json@^1.0.1":
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/@walletconnect/safe-json/-/safe-json-1.0.1.tgz#9813fa0a7a544b16468730c2d7bed046ed160957"
- integrity sha512-Fm7e31oSYY15NQr8SsLJheKAy5L744udZf2lJKcz6wFmPJEzf7hOF0866o/rrldRzJnjZ4H2GJ45pFudsnLW5A==
+"@walletconnect/safe-json@^1.0.1", "@walletconnect/safe-json@^1.0.2":
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/@walletconnect/safe-json/-/safe-json-1.0.2.tgz#7237e5ca48046e4476154e503c6d3c914126fa77"
+ integrity sha512-Ogb7I27kZ3LPC3ibn8ldyUr5544t3/STow9+lzz7Sfo808YD7SBWk7SAsdBFlYgP2zDRy2hS3sKRcuSRM0OTmA==
dependencies:
tslib "1.14.1"
-"@walletconnect/sign-client@^2.4.5":
- version "2.4.7"
- resolved "https://registry.yarnpkg.com/@walletconnect/sign-client/-/sign-client-2.4.7.tgz#d01e645f189726d5f919724a4145cdd16e4c4044"
- integrity sha512-x5uxnHQkNSn0QNXUdPEfwy4o1Vyi2QIWkDGUh+pfSP4s2vN0+IJAcwqBqkPn+zJ1X7eKYLs+v0ih1eieciYMPA==
+"@walletconnect/sign-client@^2.7.2":
+ version "2.11.0"
+ resolved "https://registry.yarnpkg.com/@walletconnect/sign-client/-/sign-client-2.11.0.tgz#de10f976cc1b8ab04b7f7c27f6a298e4e083ab25"
+ integrity sha512-H2ukscibBS+6WrzQWh+WyVBqO5z4F5et12JcwobdwgHnJSlqIoZxqnUYYWNCI5rUR5UKsKWaUyto4AE9N5dw4Q==
dependencies:
- "@walletconnect/core" "2.4.7"
+ "@walletconnect/core" "2.11.0"
"@walletconnect/events" "^1.0.1"
- "@walletconnect/heartbeat" "1.2.0"
- "@walletconnect/jsonrpc-provider" "^1.0.6"
- "@walletconnect/jsonrpc-utils" "^1.0.4"
+ "@walletconnect/heartbeat" "1.2.1"
+ "@walletconnect/jsonrpc-utils" "1.0.8"
"@walletconnect/logger" "^2.0.1"
"@walletconnect/time" "^1.0.2"
- "@walletconnect/types" "2.4.7"
- "@walletconnect/utils" "2.4.7"
+ "@walletconnect/types" "2.11.0"
+ "@walletconnect/utils" "2.11.0"
events "^3.3.0"
- pino "7.11.0"
"@walletconnect/time@^1.0.2":
version "1.0.2"
@@ -6044,15 +6222,15 @@
dependencies:
tslib "1.14.1"
-"@walletconnect/types@2.4.7":
- version "2.4.7"
- resolved "https://registry.yarnpkg.com/@walletconnect/types/-/types-2.4.7.tgz#9f102b444631149b2cb0d264830860dc5e211dc0"
- integrity sha512-1VaPdPJrE+UrEjAhK5bdxq2+MTo3DvUMmQeNUsp3vUGhocQXB9hJQQ1rYBknYYSyDu2rTksGCQ4nv3ZOqfxvHw==
+"@walletconnect/types@2.11.0":
+ version "2.11.0"
+ resolved "https://registry.yarnpkg.com/@walletconnect/types/-/types-2.11.0.tgz#474a009c56faa9ef4063b76ed84415c801dc9f1e"
+ integrity sha512-AB5b1lrEbCGHxqS2vqfCkIoODieH+ZAUp9rA1O2ftrhnqDJiJK983Df87JhYhECsQUBHHfALphA8ydER0q+9sw==
dependencies:
"@walletconnect/events" "^1.0.1"
- "@walletconnect/heartbeat" "1.2.0"
- "@walletconnect/jsonrpc-types" "^1.0.2"
- "@walletconnect/keyvaluestorage" "^1.0.2"
+ "@walletconnect/heartbeat" "1.2.1"
+ "@walletconnect/jsonrpc-types" "1.0.3"
+ "@walletconnect/keyvaluestorage" "^1.1.1"
"@walletconnect/logger" "^2.0.1"
events "^3.3.0"
@@ -6061,25 +6239,24 @@
resolved "https://registry.yarnpkg.com/@walletconnect/types/-/types-1.8.0.tgz#3f5e85b2d6b149337f727ab8a71b8471d8d9a195"
integrity sha512-Cn+3I0V0vT9ghMuzh1KzZvCkiAxTq+1TR2eSqw5E5AVWfmCtECFkVZBP6uUJZ8YjwLqXheI+rnjqPy7sVM4Fyg==
-"@walletconnect/utils@2.4.7", "@walletconnect/utils@^2.4.5":
- version "2.4.7"
- resolved "https://registry.yarnpkg.com/@walletconnect/utils/-/utils-2.4.7.tgz#f9589f3181f5dc3fd3d4e2cb4c41a08af42e2aae"
- integrity sha512-t3kW0qLClnejTTKg3y/o/MmJb5ZDGfD13YT9Nw56Up3qq/pwVfTtWjt8vJOQWMIm0hZgjgESivcf6/wuu3/Oqw==
+"@walletconnect/utils@2.11.0", "@walletconnect/utils@^2.4.5":
+ version "2.11.0"
+ resolved "https://registry.yarnpkg.com/@walletconnect/utils/-/utils-2.11.0.tgz#31c95151c823022077883dda61800cdea71879b7"
+ integrity sha512-hxkHPlTlDQILHfIKXlmzgNJau/YcSBC3XHUSuZuKZbNEw3duFT6h6pm3HT/1+j1a22IG05WDsNBuTCRkwss+BQ==
dependencies:
"@stablelib/chacha20poly1305" "1.0.1"
"@stablelib/hkdf" "1.0.1"
"@stablelib/random" "^1.0.2"
"@stablelib/sha256" "1.0.1"
"@stablelib/x25519" "^1.0.3"
- "@walletconnect/jsonrpc-utils" "^1.0.4"
"@walletconnect/relay-api" "^1.0.9"
- "@walletconnect/safe-json" "^1.0.1"
+ "@walletconnect/safe-json" "^1.0.2"
"@walletconnect/time" "^1.0.2"
- "@walletconnect/types" "2.4.7"
+ "@walletconnect/types" "2.11.0"
"@walletconnect/window-getters" "^1.0.1"
"@walletconnect/window-metadata" "^1.0.1"
detect-browser "5.3.0"
- query-string "7.1.1"
+ query-string "7.1.3"
uint8arrays "^3.1.0"
"@walletconnect/window-getters@1.0.0":
@@ -6160,19 +6337,19 @@ acorn-walk@^7.0.0:
integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==
acorn-walk@^8.0.0, acorn-walk@^8.0.2, acorn-walk@^8.1.1:
- version "8.2.0"
- resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1"
- integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==
+ version "8.3.2"
+ resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.2.tgz#7703af9415f1b6db9315d6895503862e231d34aa"
+ integrity sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==
acorn@^7.0.0:
version "7.4.1"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
-acorn@^8.0.4, acorn@^8.1.0, acorn@^8.4.1, acorn@^8.8.0, acorn@^8.8.1:
- version "8.8.1"
- resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.1.tgz#0a3f9cbecc4ec3bea6f0a80b66ae8dd2da250b73"
- integrity sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==
+acorn@^8.0.4, acorn@^8.1.0, acorn@^8.11.3, acorn@^8.4.1, acorn@^8.8.0, acorn@^8.8.1:
+ version "8.11.3"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a"
+ integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==
aes-js@3.0.0:
version "3.0.0"
@@ -6295,7 +6472,7 @@ any-observable@^0.3.0:
resolved "https://registry.yarnpkg.com/any-observable/-/any-observable-0.3.0.tgz#af933475e5806a67d0d7df090dd5e8bef65d119b"
integrity sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==
-anymatch@^3.0.3, anymatch@~3.1.2:
+anymatch@^3.0.3, anymatch@^3.1.3, anymatch@~3.1.2:
version "3.1.3"
resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e"
integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==
@@ -6622,16 +6799,7 @@ axios@^0.27.2:
follow-redirects "^1.14.9"
form-data "^4.0.0"
-axios@^1.1.3, axios@^1.4.0:
- version "1.5.1"
- resolved "https://registry.yarnpkg.com/axios/-/axios-1.5.1.tgz#11fbaa11fc35f431193a9564109c88c1f27b585f"
- integrity sha512-Q28iYCWzNHjAm+yEAot5QaAMxhMghWLFVf7rRdwhUI+c2jix2DUXjAHXVi+s1ibs3mjPO/cCgbA++3BjD0vP/A==
- dependencies:
- follow-redirects "^1.15.0"
- form-data "^4.0.0"
- proxy-from-env "^1.1.0"
-
-axios@^1.3.6:
+axios@^1.1.3, axios@^1.3.6, axios@^1.4.0:
version "1.6.2"
resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.2.tgz#de67d42c755b571d3e698df1b6504cde9b0ee9f2"
integrity sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==
@@ -7083,14 +7251,6 @@ buffer-xor@^1.0.3:
resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9"
integrity sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==
-buffer@6.0.1:
- version "6.0.1"
- resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.1.tgz#3cbea8c1463e5a0779e30b66d4c88c6ffa182ac2"
- integrity sha512-rVAXBwEcEoYtxnHSO5iWyhzV/O1WMtkUYWlfdLS7FjU4PnSJJHEfHXi/uHPI5EwltmOA794gN3bm3/pzuctWjQ==
- dependencies:
- base64-js "^1.3.1"
- ieee754 "^1.2.1"
-
buffer@6.0.3, buffer@^6.0.1, buffer@^6.0.2, buffer@^6.0.3, buffer@~6.0.3:
version "6.0.3"
resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6"
@@ -7213,19 +7373,6 @@ chai@=4.3.4:
pathval "^1.1.1"
type-detect "^4.0.5"
-chai@^4.3.7:
- version "4.3.7"
- resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.7.tgz#ec63f6df01829088e8bf55fca839bcd464a8ec51"
- integrity sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==
- dependencies:
- assertion-error "^1.1.0"
- check-error "^1.0.2"
- deep-eql "^4.1.2"
- get-func-name "^2.0.0"
- loupe "^2.3.1"
- pathval "^1.1.1"
- type-detect "^4.0.5"
-
chalk@3.0.0, chalk@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4"
@@ -7278,9 +7425,11 @@ chardet@^0.7.0:
integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==
check-error@^1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82"
- integrity sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.3.tgz#a6502e4312a7ee969f646e83bb3ddd56281bd694"
+ integrity sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==
+ dependencies:
+ get-func-name "^2.0.2"
chokidar@3.5.3, chokidar@^3.5.2, chokidar@^3.5.3:
version "3.5.3"
@@ -7315,6 +7464,13 @@ cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3:
inherits "^2.0.1"
safe-buffer "^5.0.1"
+citty@^0.1.5:
+ version "0.1.5"
+ resolved "https://registry.yarnpkg.com/citty/-/citty-0.1.5.tgz#fe37ceae5dc764af75eb2fece99d2bf527ea4e50"
+ integrity sha512-AS7n5NSc0OQVMV9v6wt3ByujNIrne0/cTjiC2MYqhvao57VNfiuVksTSr2p17nVOhEr2KtqiAkGwHcgMC/qUuQ==
+ dependencies:
+ consola "^3.2.3"
+
cjs-module-lexer@^1.0.0:
version "1.2.2"
resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz#9f84ba3244a512f3a54e5277e8eef4c489864e40"
@@ -7372,6 +7528,15 @@ client-only@^0.0.1:
resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1"
integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==
+clipboardy@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/clipboardy/-/clipboardy-4.0.0.tgz#e73ced93a76d19dd379ebf1f297565426dffdca1"
+ integrity sha512-5mOlNS0mhX0707P2I0aZ2V/cmHUEO/fL7VFLqszkhUsxt7RwnmrInf/eEQKlf5GzvYeHIjT+Ov1HRfNmymlG0w==
+ dependencies:
+ execa "^8.0.1"
+ is-wsl "^3.1.0"
+ is64bit "^2.0.0"
+
cliui@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5"
@@ -7409,6 +7574,11 @@ clsx@1.2.1, clsx@^1.2.1:
resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12"
integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==
+cluster-key-slot@^1.1.0:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz#88ddaa46906e303b5de30d3153b7d9fe0a0c19ac"
+ integrity sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==
+
cmd-shim@^6.0.0:
version "6.0.1"
resolved "https://registry.yarnpkg.com/cmd-shim/-/cmd-shim-6.0.1.tgz#a65878080548e1dca760b3aea1e21ed05194da9d"
@@ -7534,6 +7704,11 @@ concat-map@0.0.1:
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
+consola@^3.2.3:
+ version "3.2.3"
+ resolved "https://registry.yarnpkg.com/consola/-/consola-3.2.3.tgz#0741857aa88cfa0d6fd53f1cff0375136e98502f"
+ integrity sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==
+
console-control-strings@^1.0.0, console-control-strings@~1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e"
@@ -7549,6 +7724,11 @@ convert-source-map@^2.0.0:
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a"
integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==
+cookie-es@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/cookie-es/-/cookie-es-1.0.0.tgz#4759684af168dfc54365b2c2dda0a8d7ee1e4865"
+ integrity sha512-mWYvfOLrfEc996hlKcdABeIiPHUPC6DM2QYZdGGOvhOTbA3tjm2eBwqlJpoFdjC89NI4Qt6h0Pu06Mp+1Pj5OQ==
+
copy-to-clipboard@^3.3.1:
version "3.3.3"
resolved "https://registry.yarnpkg.com/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz#55ac43a1db8ae639a4bd99511c148cdd1b83a1b0"
@@ -7681,6 +7861,11 @@ cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3:
shebang-command "^2.0.0"
which "^2.0.1"
+crossws@^0.1.0:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/crossws/-/crossws-0.1.1.tgz#3a85a8140568e4828d9747a884171ea7e6a8bbe2"
+ integrity sha512-c9c/o7bS3OjsdpSkvexpka0JNlesBF2JU9B2V1yNsYGwRbAafxhJQ7VI9b48D5bpONz/oxbPGMzBojy9sXoQIQ==
+
crypto-browserify@^3.12.0:
version "3.12.0"
resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec"
@@ -8160,11 +8345,6 @@ dashdash@^1.12.0:
dependencies:
assert-plus "^1.0.0"
-data-uri-to-buffer@^4.0.0:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz#d8feb2b2881e6a4f58c2e08acfd0e2834e26222e"
- integrity sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==
-
data-urls@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-3.0.2.tgz#9cf24a477ae22bcef5cd5f6f0bfbc1d2d3be9143"
@@ -8237,7 +8417,7 @@ decode-named-character-reference@^1.0.0:
dependencies:
character-entities "^2.0.0"
-decode-uri-component@^0.2.0:
+decode-uri-component@^0.2.0, decode-uri-component@^0.2.2:
version "0.2.2"
resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9"
integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==
@@ -8254,13 +8434,6 @@ deep-eql@^3.0.1:
dependencies:
type-detect "^4.0.0"
-deep-eql@^4.1.2:
- version "4.1.3"
- resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.3.tgz#7c7775513092f7df98d8df9996dd085eb668cc6d"
- integrity sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==
- dependencies:
- type-detect "^4.0.0"
-
deep-equal@^2.0.5:
version "2.1.0"
resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-2.1.0.tgz#5ba60402cf44ab92c2c07f3f3312c3d857a0e1dd"
@@ -8312,6 +8485,11 @@ defined@^1.0.0:
resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.1.tgz#c0b9db27bfaffd95d6f61399419b893df0f91ebf"
integrity sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q==
+defu@^6.1.3, defu@^6.1.4:
+ version "6.1.4"
+ resolved "https://registry.yarnpkg.com/defu/-/defu-6.1.4.tgz#4e0c9cf9ff68fe5f3d7f2765cc1a012dfdcb0479"
+ integrity sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==
+
delaunator@5:
version "5.0.0"
resolved "https://registry.yarnpkg.com/delaunator/-/delaunator-5.0.0.tgz#60f052b28bd91c9b4566850ebf7756efe821d81b"
@@ -8334,6 +8512,11 @@ delegates@^1.0.0:
resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==
+denque@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/denque/-/denque-2.1.0.tgz#e93e1a6569fb5e66f16a3c2a2964617d349d6ab1"
+ integrity sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==
+
depd@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df"
@@ -8357,6 +8540,11 @@ des.js@^1.0.0:
inherits "^2.0.1"
minimalistic-assert "^1.0.0"
+destr@^2.0.1, destr@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/destr/-/destr-2.0.2.tgz#8d3c0ee4ec0a76df54bc8b819bca215592a8c218"
+ integrity sha512-65AlobnZMiCET00KaFFjUefxDX0khFA/E4myqZ7a6Sq1yZtR8+FVIvilVX66vF2uobSumxooYZChiRPCKNqhmg==
+
detect-browser@5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/detect-browser/-/detect-browser-5.2.0.tgz#c9cd5afa96a6a19fda0bbe9e9be48a6b6e1e9c97"
@@ -8367,6 +8555,11 @@ detect-browser@5.3.0:
resolved "https://registry.yarnpkg.com/detect-browser/-/detect-browser-5.3.0.tgz#9705ef2bddf46072d0f7265a1fe300e36fe7ceca"
integrity sha512-53rsFbGdwMwlF7qvCt0ypLM5V5/Mbl0szB7GPN8y9NCcbknYOeVVXdrXEq+90IwAfrrzt6Hd+u2E2ntakICU8w==
+detect-libc@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b"
+ integrity sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==
+
detect-newline@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651"
@@ -8436,9 +8629,9 @@ diffie-hellman@^5.0.0:
randombytes "^2.0.0"
dijkstrajs@^1.0.1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/dijkstrajs/-/dijkstrajs-1.0.2.tgz#2e48c0d3b825462afe75ab4ad5e829c8ece36257"
- integrity sha512-QV6PMaHTCNmKSeP6QoXhVTw9snc9VD8MulTT0Bd99Pacp4SS1cjcrYPgBPmibqKVtMJJfqC6XvOXgPMEEPH/fg==
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/dijkstrajs/-/dijkstrajs-1.0.3.tgz#4c8dbdea1f0f6478bff94d9c49c784d623e4fc23"
+ integrity sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==
dir-glob@^3.0.1:
version "3.0.1"
@@ -9147,6 +9340,21 @@ execa@^5.0.0:
signal-exit "^3.0.3"
strip-final-newline "^2.0.0"
+execa@^8.0.1:
+ version "8.0.1"
+ resolved "https://registry.yarnpkg.com/execa/-/execa-8.0.1.tgz#51f6a5943b580f963c3ca9c6321796db8cc39b8c"
+ integrity sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==
+ dependencies:
+ cross-spawn "^7.0.3"
+ get-stream "^8.0.1"
+ human-signals "^5.0.0"
+ is-stream "^3.0.0"
+ merge-stream "^2.0.0"
+ npm-run-path "^5.1.0"
+ onetime "^6.0.0"
+ signal-exit "^4.1.0"
+ strip-final-newline "^3.0.0"
+
exenv@^1.2.0:
version "1.2.2"
resolved "https://registry.yarnpkg.com/exenv/-/exenv-1.2.2.tgz#2ae78e85d9894158670b03d47bec1f03bd91bb9d"
@@ -9207,6 +9415,11 @@ eyes@^0.1.8:
resolved "https://registry.yarnpkg.com/eyes/-/eyes-0.1.8.tgz#62cf120234c683785d902348a800ef3e0cc20bc0"
integrity sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ==
+fast-copy@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/fast-copy/-/fast-copy-3.0.1.tgz#9e89ef498b8c04c1cd76b33b8e14271658a732aa"
+ integrity sha512-Knr7NOtK3HWRYGtHoJrjkaWepqT8thIVGAwt0p0aUs1zqkAzXZV4vo9fFNwyb5fcqK1GKYFYxldQdIDVKhUAfA==
+
fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
version "3.1.3"
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
@@ -9244,9 +9457,9 @@ fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6:
integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==
fast-redact@^3.0.0:
- version "3.1.2"
- resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-3.1.2.tgz#d58e69e9084ce9fa4c1a6fa98a3e1ecf5d7839aa"
- integrity sha512-+0em+Iya9fKGfEQGcd62Yv6onjBmmhV1uh86XVfOU8VwAe6kaFdQCWI9s0/Nnugx5Vd9tdbZ7e6gE2tR9dzXdw==
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-3.3.0.tgz#7c83ce3a7be4898241a46560d51de10f653f7634"
+ integrity sha512-6T5V1QK1u4oF+ATxs1lWUmlEk6P2T9HqJG3e2DnHOdVgZy2rFJBoEnrIedcTXlkAHU/zKC+7KETJ+KGGKwxgMQ==
fast-safe-stringify@^2.0.6, fast-safe-stringify@^2.1.1:
version "2.1.1"
@@ -9291,14 +9504,6 @@ fbjs@^2.0.0:
setimmediate "^1.0.5"
ua-parser-js "^0.7.18"
-fetch-blob@^3.1.2, fetch-blob@^3.1.4:
- version "3.2.0"
- resolved "https://registry.yarnpkg.com/fetch-blob/-/fetch-blob-3.2.0.tgz#f09b8d4bbd45adc6f0c20b7e787e793e309dcce9"
- integrity sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==
- dependencies:
- node-domexception "^1.0.0"
- web-streams-polyfill "^3.0.3"
-
fetch-retry@^5.0.6:
version "5.0.6"
resolved "https://registry.yarnpkg.com/fetch-retry/-/fetch-retry-5.0.6.tgz#17d0bc90423405b7a88b74355bf364acd2a7fa56"
@@ -9467,13 +9672,6 @@ form-data@~2.3.2:
combined-stream "^1.0.6"
mime-types "^2.1.12"
-formdata-polyfill@^4.0.10:
- version "4.0.10"
- resolved "https://registry.yarnpkg.com/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz#24807c31c9d402e002ab3d8c720144ceb8848423"
- integrity sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==
- dependencies:
- fetch-blob "^3.1.2"
-
fp-ts@2.12.2:
version "2.12.2"
resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-2.12.2.tgz#a191db2dbbb04f48a0e75050b94f57cc876c7b40"
@@ -9506,16 +9704,11 @@ fs.realpath@^1.0.0:
integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
fsevents@^2.3.2, fsevents@~2.3.2:
- version "2.3.2"
- resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
- integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
-
-function-bind@^1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
- integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
+ version "2.3.3"
+ resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
+ integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
-function-bind@^1.1.2:
+function-bind@^1.1.1, function-bind@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c"
integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==
@@ -9564,10 +9757,10 @@ get-caller-file@^2.0.1, get-caller-file@^2.0.5:
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
-get-func-name@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41"
- integrity sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==
+get-func-name@^2.0.0, get-func-name@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.2.tgz#0d7cf20cd13fda808669ffa88f4ffc7a3943fc41"
+ integrity sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==
get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3:
version "1.1.3"
@@ -9593,6 +9786,11 @@ get-package-type@^0.1.0:
resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a"
integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==
+get-port-please@^3.1.2:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/get-port-please/-/get-port-please-3.1.2.tgz#502795e56217128e4183025c89a48c71652f4e49"
+ integrity sha512-Gxc29eLs1fbn6LQ4jSU4vXjlwyZhF5HsGuMAa7gqBP4Rw4yxxltyDUuF5MBclFzDTXO+ACchGQoeela4DSfzdQ==
+
get-stream@^5.0.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3"
@@ -9605,6 +9803,11 @@ get-stream@^6.0.0:
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7"
integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==
+get-stream@^8.0.1:
+ version "8.0.1"
+ resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-8.0.1.tgz#def9dfd71742cd7754a7761ed43749a27d02eca2"
+ integrity sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==
+
get-symbol-description@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6"
@@ -9717,6 +9920,21 @@ gzip-size@^6.0.0:
dependencies:
duplexer "^0.1.2"
+h3@^1.10.1, h3@^1.8.2:
+ version "1.10.1"
+ resolved "https://registry.yarnpkg.com/h3/-/h3-1.10.1.tgz#221634ca9bdb216a6b359bd2915be466a179b8a1"
+ integrity sha512-UBAUp47hmm4BB5/njB4LrEa9gpuvZj4/Qf/ynSMzO6Ku2RXaouxEfiG2E2IFnv6fxbhAkzjasDxmo6DFdEeXRg==
+ dependencies:
+ cookie-es "^1.0.0"
+ defu "^6.1.4"
+ destr "^2.0.2"
+ iron-webcrypto "^1.0.0"
+ ohash "^1.1.3"
+ radix3 "^1.1.0"
+ ufo "^1.3.2"
+ uncrypto "^0.1.3"
+ unenv "^1.9.0"
+
har-schema@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
@@ -9885,6 +10103,11 @@ http-proxy-agent@^5.0.0:
agent-base "6"
debug "4"
+http-shutdown@^1.2.2:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/http-shutdown/-/http-shutdown-1.2.2.tgz#41bc78fc767637c4c95179bc492f312c0ae64c5f"
+ integrity sha512-S9wWkJ/VSY9/k4qcjG318bqJNruzE4HySUhFYknwmu6LBP97KLLfwNf+n4V1BHurvFNkSKLFnK/RsuUnRTf9Vw==
+
http-signature@~1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1"
@@ -9912,6 +10135,11 @@ human-signals@^2.1.0:
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0"
integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==
+human-signals@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-5.0.0.tgz#42665a284f9ae0dade3ba41ebc37eb4b852f3a28"
+ integrity sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==
+
humanize-ms@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed"
@@ -9943,6 +10171,11 @@ iconv-lite@^0.4.24:
dependencies:
safer-buffer ">= 2.1.2 < 3"
+idb-keyval@^6.2.1:
+ version "6.2.1"
+ resolved "https://registry.yarnpkg.com/idb-keyval/-/idb-keyval-6.2.1.tgz#94516d625346d16f56f3b33855da11bfded2db33"
+ integrity sha512-8Sb3veuYCyrZL+VBt9LJfZjLUPWVvqn8tG28VqYNFCo43KHcKuq+b4EiXGeuaLAQWL2YmyDgMp2aSpH9JHsEQg==
+
ieee754@^1.1.13, ieee754@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
@@ -10097,6 +10330,26 @@ io-ts@2.2.18:
resolved "https://registry.yarnpkg.com/io-ts/-/io-ts-2.2.18.tgz#dfb41aded5f0e598ccf2a25a483c205444210173"
integrity sha512-3JxUUzRtPQPs5sOwB7pW0+Xb54nOzqA6M1sRB1hwgsRmkWMeGTjtOrCynGTJhIj+mBLUj2S37DAq2+BrPh9kTQ==
+ioredis@^5.3.2:
+ version "5.3.2"
+ resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-5.3.2.tgz#9139f596f62fc9c72d873353ac5395bcf05709f7"
+ integrity sha512-1DKMMzlIHM02eBBVOFQ1+AolGjs6+xEcM4PDL7NqOS6szq7H9jSaEkIUH6/a5Hl241LzW6JLSiAbNvTQjUupUA==
+ dependencies:
+ "@ioredis/commands" "^1.1.1"
+ cluster-key-slot "^1.1.0"
+ debug "^4.3.4"
+ denque "^2.1.0"
+ lodash.defaults "^4.2.0"
+ lodash.isarguments "^3.1.0"
+ redis-errors "^1.2.0"
+ redis-parser "^3.0.0"
+ standard-as-callback "^2.1.0"
+
+iron-webcrypto@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/iron-webcrypto/-/iron-webcrypto-1.0.0.tgz#e3b689c0c61b434a0a4cb82d0aeabbc8b672a867"
+ integrity sha512-anOK1Mktt8U1Xi7fCM3RELTuYbnFikQY5VtrDj7kPgpejV7d43tWKhzgioO0zpkazLEL/j/iayRqnJhrGfqUsg==
+
is-arguments@^1.0.4, is-arguments@^1.1.0, is-arguments@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b"
@@ -10159,20 +10412,13 @@ is-color-stop@^1.1.0:
rgb-regex "^1.0.1"
rgba-regex "^1.0.0"
-is-core-module@^2.13.0:
+is-core-module@^2.13.0, is-core-module@^2.8.1, is-core-module@^2.9.0:
version "2.13.1"
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384"
integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==
dependencies:
hasown "^2.0.0"
-is-core-module@^2.8.1, is-core-module@^2.9.0:
- version "2.11.0"
- resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144"
- integrity sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==
- dependencies:
- has "^1.0.3"
-
is-date-object@^1.0.1, is-date-object@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f"
@@ -10180,6 +10426,11 @@ is-date-object@^1.0.1, is-date-object@^1.0.5:
dependencies:
has-tostringtag "^1.0.0"
+is-docker@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-3.0.0.tgz#90093aa3106277d8a77a5910dbae71747e15a200"
+ integrity sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==
+
is-extglob@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
@@ -10226,6 +10477,13 @@ is-hex-prefixed@1.0.0:
resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554"
integrity sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA==
+is-inside-container@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-inside-container/-/is-inside-container-1.0.0.tgz#e81fba699662eb31dbdaf26766a61d4814717ea4"
+ integrity sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==
+ dependencies:
+ is-docker "^3.0.0"
+
is-interactive@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e"
@@ -10335,6 +10593,11 @@ is-stream@^2.0.0, is-stream@^2.0.1:
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077"
integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==
+is-stream@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-3.0.0.tgz#e6bfd7aa6bef69f4f472ce9bb681e3e57b4319ac"
+ integrity sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==
+
is-string@^1.0.5, is-string@^1.0.7:
version "1.0.7"
resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd"
@@ -10390,6 +10653,20 @@ is-weakset@^2.0.1:
call-bind "^1.0.2"
get-intrinsic "^1.1.1"
+is-wsl@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-3.1.0.tgz#e1c657e39c10090afcbedec61720f6b924c3cbd2"
+ integrity sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==
+ dependencies:
+ is-inside-container "^1.0.0"
+
+is64bit@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/is64bit/-/is64bit-2.0.0.tgz#198c627cbcb198bbec402251f88e5e1a51236c07"
+ integrity sha512-jv+8jaWCl0g2lSBkNSVXdzfBA0npK1HGC2KtWM9FumFRoGS94g3NbCCLVnCYHLjp4GrW2KZeeSTMo5ddtznmGw==
+ dependencies:
+ system-architecture "^0.1.0"
+
isarray@^2.0.1, isarray@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723"
@@ -10413,11 +10690,24 @@ isomorphic-fetch@^3.0.0:
node-fetch "^2.6.1"
whatwg-fetch "^3.4.1"
+isomorphic-unfetch@3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/isomorphic-unfetch/-/isomorphic-unfetch-3.1.0.tgz#87341d5f4f7b63843d468438128cb087b7c3e98f"
+ integrity sha512-geDJjpoZ8N0kWexiwkX8F9NkTsXhetLPVbZFQ+JTW239QNOwvB0gniuR1Wc6f0AMTn7/mFGyXvHTifrCp/GH8Q==
+ dependencies:
+ node-fetch "^2.6.1"
+ unfetch "^4.2.0"
+
isomorphic-ws@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz#55fd4cd6c5e6491e76dc125938dd863f5cd4f2dc"
integrity sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==
+isomorphic-ws@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz#e5529148912ecb9b451b46ed44d53dae1ce04bbf"
+ integrity sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==
+
isstream@~0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
@@ -10465,10 +10755,10 @@ istanbul-reports@^3.1.3:
html-escaper "^2.0.0"
istanbul-lib-report "^3.0.0"
-jayson@^3.4.4:
- version "3.7.0"
- resolved "https://registry.yarnpkg.com/jayson/-/jayson-3.7.0.tgz#b735b12d06d348639ae8230d7a1e2916cb078f25"
- integrity sha512-tfy39KJMrrXJ+mFcMpxwBvFDetS8LAID93+rycFglIQM4kl3uNR3W4lBLE/FFhsoUCEox5Dt2adVpDm/XtebbQ==
+jayson@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/jayson/-/jayson-4.1.0.tgz#60dc946a85197317f2b1439d672a8b0a99cea2f9"
+ integrity sha512-R6JlbyLN53Mjku329XoRT2zJAE6ZgOQ8f91ucYdMCD4nkGCF9kZSrcGXpHIU4jeKj58zUZke2p+cdQchU7Ly7A==
dependencies:
"@types/connect" "^3.4.33"
"@types/node" "^12.12.54"
@@ -10480,7 +10770,6 @@ jayson@^3.4.4:
eyes "^0.1.8"
isomorphic-ws "^4.0.1"
json-stringify-safe "^5.0.1"
- lodash "^4.17.20"
uuid "^8.3.2"
ws "^7.4.5"
@@ -10859,6 +11148,11 @@ jest@29.2.0:
import-local "^3.0.2"
jest-cli "^29.2.0"
+jiti@^1.21.0:
+ version "1.21.0"
+ resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.0.tgz#7c97f8fe045724e136a397f7340475244156105d"
+ integrity sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==
+
js-base64@^3.7.2:
version "3.7.3"
resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-3.7.3.tgz#2e784bb0851636bf1e99ef12e4f3a8a8c9b7639f"
@@ -11007,6 +11301,11 @@ json5@^2.2.1:
resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.2.tgz#64471c5bdcc564c18f7c1d4df2e2297f2457c5ab"
integrity sha512-46Tk9JiOL2z7ytNQWFLpj99RZkVgeHf87yGQKsIkaPz1qSH9UczKH1rO7K3wgRselo0tYMUNfecYpm/p1vC7tQ==
+jsonc-parser@^3.2.0:
+ version "3.2.1"
+ resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.2.1.tgz#031904571ccf929d7670ee8c547545081cb37f1a"
+ integrity sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==
+
jsonfile@^6.0.1:
version "6.1.0"
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae"
@@ -11156,6 +11455,30 @@ lint-staged@10.0.10:
string-argv "0.3.1"
stringify-object "^3.3.0"
+listhen@^1.5.5:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/listhen/-/listhen-1.6.0.tgz#df26c527c59b87557be4d0408d4a09626bd946c8"
+ integrity sha512-z0RcEXVX5oTpY1bO02SKoTU/kmZSrFSngNNzHRM6KICR17PTq7ANush6AE6ztGJwJD4RLpBrVHd9GnV51J7s3w==
+ dependencies:
+ "@parcel/watcher" "^2.4.0"
+ "@parcel/watcher-wasm" "2.4.0"
+ citty "^0.1.5"
+ clipboardy "^4.0.0"
+ consola "^3.2.3"
+ crossws "^0.1.0"
+ defu "^6.1.4"
+ get-port-please "^3.1.2"
+ h3 "^1.10.1"
+ http-shutdown "^1.2.2"
+ jiti "^1.21.0"
+ mlly "^1.5.0"
+ node-forge "^1.3.1"
+ pathe "^1.1.2"
+ std-env "^3.7.0"
+ ufo "^1.3.2"
+ untun "^0.1.3"
+ uqr "^0.1.2"
+
listr-silent-renderer@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz#924b5a3757153770bf1a8e3fbf74b8bbf3f9242e"
@@ -11244,6 +11567,11 @@ lodash.clonedeep@^4.5.0:
resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef"
integrity sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==
+lodash.defaults@^4.2.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c"
+ integrity sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==
+
lodash.flatmap@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.flatmap/-/lodash.flatmap-4.5.0.tgz#ef8cbf408f6e48268663345305c6acc0b778702e"
@@ -11254,6 +11582,11 @@ lodash.get@^4.4.2:
resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
integrity sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==
+lodash.isarguments@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a"
+ integrity sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==
+
lodash.isequal@4.5.0, lodash.isequal@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
@@ -11347,13 +11680,6 @@ loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0:
dependencies:
js-tokens "^3.0.0 || ^4.0.0"
-loupe@^2.3.1:
- version "2.3.6"
- resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.6.tgz#76e4af498103c532d1ecc9be102036a21f787b53"
- integrity sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==
- dependencies:
- get-func-name "^2.0.0"
-
lower-case@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28"
@@ -11361,6 +11687,11 @@ lower-case@^2.0.2:
dependencies:
tslib "^2.0.3"
+lru-cache@^10.0.2:
+ version "10.2.0"
+ resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.0.tgz#0bd445ca57363465900f4d1f9bd8db343a4d95c3"
+ integrity sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==
+
lru-cache@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
@@ -11876,7 +12207,7 @@ micromark@^3.0.0:
micromark-util-types "^1.0.1"
uvu "^0.5.0"
-micromatch@^4.0.0, micromatch@^4.0.2, micromatch@^4.0.4:
+micromatch@^4.0.0, micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.5:
version "4.0.5"
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6"
integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==
@@ -11919,6 +12250,11 @@ mimic-fn@^2.1.0:
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
+mimic-fn@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-4.0.0.tgz#60a90550d5cb0b239cca65d893b1a53b29871ecc"
+ integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==
+
min-indent@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869"
@@ -11999,6 +12335,16 @@ mkdirp@^1.0.3:
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
+mlly@^1.2.0, mlly@^1.5.0:
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/mlly/-/mlly-1.5.0.tgz#8428a4617d54cc083d3009030ac79739a0e5447a"
+ integrity sha512-NPVQvAY1xr1QoVeG0cy8yUYC7FQcOx6evl/RjT1wL5FvzPnzOysoqB/jmx/DhssT2dYa8nxECLAaFI/+gVLhDQ==
+ dependencies:
+ acorn "^8.11.3"
+ pathe "^1.1.2"
+ pkg-types "^1.0.3"
+ ufo "^1.3.2"
+
mocha@10.1.0, mocha@^9.1.4, mocha@^9.2.0:
version "10.1.0"
resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.1.0.tgz#dbf1114b7c3f9d0ca5de3133906aea3dfc89ef7a"
@@ -12026,39 +12372,12 @@ mocha@10.1.0, mocha@^9.1.4, mocha@^9.2.0:
yargs-parser "20.2.4"
yargs-unparser "2.0.0"
-mocha@^10.2.0:
- version "10.2.0"
- resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.2.0.tgz#1fd4a7c32ba5ac372e03a17eef435bd00e5c68b8"
- integrity sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==
- dependencies:
- ansi-colors "4.1.1"
- browser-stdout "1.3.1"
- chokidar "3.5.3"
- debug "4.3.4"
- diff "5.0.0"
- escape-string-regexp "4.0.0"
- find-up "5.0.0"
- glob "7.2.0"
- he "1.2.0"
- js-yaml "4.1.0"
- log-symbols "4.1.0"
- minimatch "5.0.1"
- ms "2.1.3"
- nanoid "3.3.3"
- serialize-javascript "6.0.0"
- strip-json-comments "3.1.1"
- supports-color "8.1.1"
- workerpool "6.2.1"
- yargs "16.2.0"
- yargs-parser "20.2.4"
- yargs-unparser "2.0.0"
-
modern-normalize@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/modern-normalize/-/modern-normalize-1.1.0.tgz#da8e80140d9221426bd4f725c6e11283d34f90b7"
integrity sha512-2lMlY1Yc1+CUy0gw4H95uNN7vjbpoED7NNRSBHE25nWfLBdmMzFCsPshlzbxHz+gYMcBEUN8V4pU16prcdPSgA==
-mri@^1.1.0:
+mri@^1.1.0, mri@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/mri/-/mri-1.2.0.tgz#6721480fec2a11a4889861115a48b6cbe7cc8f0b"
integrity sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==
@@ -12126,6 +12445,11 @@ nanoid@^3.3.1, nanoid@^3.3.4:
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab"
integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==
+napi-wasm@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/napi-wasm/-/napi-wasm-1.1.0.tgz#bbe617823765ae9c1bc12ff5942370eae7b2ba4e"
+ integrity sha512-lHwIAJbmLSjF9VDRm9GoVOy9AGp3aIvkjv+Kvz9h16QR3uSVYH78PNQUnT2U4X53mhlnV2M7wrhibQ3GHicDmg==
+
natural-compare@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
@@ -12224,10 +12548,10 @@ node-addon-api@^2.0.0:
resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32"
integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==
-node-domexception@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5"
- integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==
+node-addon-api@^7.0.0:
+ version "7.1.0"
+ resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-7.1.0.tgz#71f609369379c08e251c558527a107107b5e0fdb"
+ integrity sha512-mNcltoe1R8o7STTegSOHdnJNN7s5EUvhoS7ShnTHDyOSd+8H+UdWODq6qSv67PjC8Zc5JRT8+oLAMCr0SIXw7g==
node-emoji@^1.11.0:
version "1.11.0"
@@ -12236,6 +12560,11 @@ node-emoji@^1.11.0:
dependencies:
lodash "^4.17.21"
+node-fetch-native@^1.4.0, node-fetch-native@^1.4.1, node-fetch-native@^1.6.1:
+ version "1.6.1"
+ resolved "https://registry.yarnpkg.com/node-fetch-native/-/node-fetch-native-1.6.1.tgz#f95c74917d3cebc794cdae0cd2a9c7594aad0cb4"
+ integrity sha512-bW9T/uJDPAJB2YNYEpWzE54U5O3MQidXsOyTfnbKYtTtFexRvGzb1waphBN4ZwP6EcIvYYEOwW0b72BpAqydTw==
+
node-fetch@2.6.1, node-fetch@2.6.7:
version "2.6.7"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad"
@@ -12243,6 +12572,13 @@ node-fetch@2.6.1, node-fetch@2.6.7:
dependencies:
whatwg-url "^5.0.0"
+node-fetch@2.6.11:
+ version "2.6.11"
+ resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.11.tgz#cde7fc71deef3131ef80a738919f999e6edfff25"
+ integrity sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==
+ dependencies:
+ whatwg-url "^5.0.0"
+
node-fetch@^2.6.1, node-fetch@^2.6.12, node-fetch@^2.6.7:
version "2.6.12"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.12.tgz#02eb8e22074018e3d5a83016649d04df0e348fba"
@@ -12250,14 +12586,10 @@ node-fetch@^2.6.1, node-fetch@^2.6.12, node-fetch@^2.6.7:
dependencies:
whatwg-url "^5.0.0"
-node-fetch@^3.2.10:
- version "3.3.1"
- resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.3.1.tgz#b3eea7b54b3a48020e46f4f88b9c5a7430d20b2e"
- integrity sha512-cRVc/kyto/7E5shrWca1Wsea4y6tL9iYJE5FBCius3JQfb/4P4I295PfhgbJQBLTx6lATE4z+wK0rPM4VS2uow==
- dependencies:
- data-uri-to-buffer "^4.0.0"
- fetch-blob "^3.1.4"
- formdata-polyfill "^4.0.10"
+node-forge@^1.3.1:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3"
+ integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==
node-gyp-build@^4.2.0, node-gyp-build@^4.3.0:
version "4.6.0"
@@ -12336,6 +12668,13 @@ npm-run-path@^4.0.0, npm-run-path@^4.0.1:
dependencies:
path-key "^3.0.0"
+npm-run-path@^5.1.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-5.2.0.tgz#224cdd22c755560253dd71b83a1ef2f758b2e955"
+ integrity sha512-W4/tgAXFqFA0iL7fk0+uQ3g7wkL8xJmx3XdK0VGb4cHW//eZTtKGvFBBoRKVTpY7n6ze4NL9ly7rgXcHufqXKg==
+ dependencies:
+ path-key "^4.0.0"
+
npmlog@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b"
@@ -12459,6 +12798,20 @@ oblivious-set@1.1.1:
resolved "https://registry.yarnpkg.com/oblivious-set/-/oblivious-set-1.1.1.tgz#d9d38e9491d51f27a5c3ec1681d2ba40aa81e98b"
integrity sha512-Oh+8fK09mgGmAshFdH6hSVco6KZmd1tTwNFWj35OvzdmJTMZtAkbn05zar2iG3v6sDs1JLEtOiBGNb6BHwkb2w==
+ofetch@^1.3.3:
+ version "1.3.3"
+ resolved "https://registry.yarnpkg.com/ofetch/-/ofetch-1.3.3.tgz#588cb806a28e5c66c2c47dd8994f9059a036d8c0"
+ integrity sha512-s1ZCMmQWXy4b5K/TW9i/DtiN8Ku+xCiHcjQ6/J/nDdssirrQNOoB165Zu8EqLMA2lln1JUth9a0aW9Ap2ctrUg==
+ dependencies:
+ destr "^2.0.1"
+ node-fetch-native "^1.4.0"
+ ufo "^1.3.0"
+
+ohash@^1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/ohash/-/ohash-1.1.3.tgz#f12c3c50bfe7271ce3fd1097d42568122ccdcf07"
+ integrity sha512-zuHHiGTYTA1sYJ/wZN+t5HKZaH23i4yI1HMwbuXm24Nid7Dv0KcuRlKoNKS9UNfAVSBlnGLcuQrnOKWOZoEGaw==
+
on-exit-leak-free@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-0.2.0.tgz#b39c9e3bf7690d890f4861558b0d7b90a442d209"
@@ -12485,6 +12838,13 @@ onetime@^5.1.0, onetime@^5.1.2:
dependencies:
mimic-fn "^2.1.0"
+onetime@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/onetime/-/onetime-6.0.0.tgz#7c24c18ed1fd2e9bca4bd26806a33613c77d34b4"
+ integrity sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==
+ dependencies:
+ mimic-fn "^4.0.0"
+
opener@^1.5.2:
version "1.5.2"
resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598"
@@ -12644,6 +13004,11 @@ path-key@^3.0.0, path-key@^3.1.0:
resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
+path-key@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/path-key/-/path-key-4.0.0.tgz#295588dc3aee64154f877adb9d780b81c554bf18"
+ integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==
+
path-parse@^1.0.7:
version "1.0.7"
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
@@ -12654,6 +13019,11 @@ path-type@^4.0.0:
resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
+pathe@^1.1.0, pathe@^1.1.1, pathe@^1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/pathe/-/pathe-1.1.2.tgz#6c4cb47a945692e48a1ddd6e4094d170516437ec"
+ integrity sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==
+
pathval@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d"
@@ -12732,6 +13102,15 @@ pkg-dir@^4.2.0:
dependencies:
find-up "^4.0.0"
+pkg-types@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/pkg-types/-/pkg-types-1.0.3.tgz#988b42ab19254c01614d13f4f65a2cfc7880f868"
+ integrity sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==
+ dependencies:
+ jsonc-parser "^3.2.0"
+ mlly "^1.2.0"
+ pathe "^1.1.0"
+
please-upgrade-node@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz#aeddd3f994c933e4ad98b99d9a556efa0e2fe942"
@@ -13368,12 +13747,12 @@ qs@~6.5.2:
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad"
integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==
-query-string@7.1.1:
- version "7.1.1"
- resolved "https://registry.yarnpkg.com/query-string/-/query-string-7.1.1.tgz#754620669db978625a90f635f12617c271a088e1"
- integrity sha512-MplouLRDHBZSG9z7fpuAAcI7aAYjDLhtsiVZsevsfaHWDS2IDdORKbSd1kWUA+V4zyva/HZoSfpwnYMMQDhb0w==
+query-string@7.1.3:
+ version "7.1.3"
+ resolved "https://registry.yarnpkg.com/query-string/-/query-string-7.1.3.tgz#a1cf90e994abb113a325804a972d98276fe02328"
+ integrity sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==
dependencies:
- decode-uri-component "^0.2.0"
+ decode-uri-component "^0.2.2"
filter-obj "^1.1.0"
split-on-first "^1.0.0"
strict-uri-encode "^2.0.0"
@@ -13403,6 +13782,11 @@ quick-lru@^5.1.1:
resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932"
integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==
+radix3@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/radix3/-/radix3-1.1.0.tgz#9745df67a49c522e94a33d0a93cf743f104b6e0d"
+ integrity sha512-pNsHDxbGORSvuSScqNJ+3Km6QAVqk8CfsCBIEoDgpqLrkD2f3QM4I7d1ozJJ172OmIcoUcerZaNWqtLkRXTV3A==
+
ramda@0.28.0, ramda@^0.28.0:
version "0.28.0"
resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.28.0.tgz#acd785690100337e8b063cab3470019be427cc97"
@@ -13506,16 +13890,11 @@ react-clientside-effect@^1.2.6:
dependencies:
"@babel/runtime" "^7.12.13"
-react-content-loader@6.2.1:
+react-content-loader@6.2.1, react-content-loader@^6.1.0:
version "6.2.1"
resolved "https://registry.yarnpkg.com/react-content-loader/-/react-content-loader-6.2.1.tgz#8feb733c2d2495002e1b216f13707f2b5f2a8ead"
integrity sha512-6ONbFX+Hi3SHuP66JB8CPvJn372pj+qwltJV0J8z/8MFrq98I1cbFdZuhDWeQXu3CFxiiDTXJn7DFxx2ZvrO7g==
-react-content-loader@^6.1.0:
- version "6.2.0"
- resolved "https://registry.yarnpkg.com/react-content-loader/-/react-content-loader-6.2.0.tgz#cd8fee8160b8fda6610d0c69ce5aee7b8094cba6"
- integrity sha512-r1dI6S+uHNLW68qraLE2njJYOuy6976PpCExuCZUcABWbfnF3FMcmuESRI8L4Bj45wnZ7n8g71hkPLzbma7/Cw==
-
react-device-detect@^2.1.2:
version "2.2.2"
resolved "https://registry.yarnpkg.com/react-device-detect/-/react-device-detect-2.2.2.tgz#dbabbce798ec359c83f574c3edb24cf1cca641a5"
@@ -13580,15 +13959,15 @@ react-hook-form@7.31.3:
resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.31.3.tgz#b61bafb9a7435f91695351a7a9f714d8c4df0121"
integrity sha512-NVZdCWViIWXXXlQ3jxVQH0NuNfwPf8A/0KvuCxrM9qxtP1qYosfR2ZudarziFrVOC7eTUbWbm1T4OyYCwv9oSQ==
-react-icons@4.11.0:
+react-icons@4.11.0, react-icons@^4.3.1:
version "4.11.0"
resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-4.11.0.tgz#4b0e31c9bfc919608095cc429c4f1846f4d66c65"
integrity sha512-V+4khzYcE5EBk/BvcuYRq6V/osf11ODUM2J8hg2FDSswRrGvqiYUYPRy4OdrWaQOBj4NcpJfmHZLNaD+VH0TyA==
-react-icons@^4.3.1:
- version "4.7.1"
- resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-4.7.1.tgz#0f4b25a5694e6972677cb189d2a72eabea7a8345"
- integrity sha512-yHd3oKGMgm7zxo3EA7H2n7vxSoiGmHk5t6Ou4bXsfcgWyhfDKMpyKfhHR6Bjnn63c+YXBLBPUql9H4wPJM6sXw==
+react-intersection-observer@9.5.3:
+ version "9.5.3"
+ resolved "https://registry.yarnpkg.com/react-intersection-observer/-/react-intersection-observer-9.5.3.tgz#f47a31ed3a0359cbbfdb91a53d7470ac2ab7b3c7"
+ integrity sha512-NJzagSdUPS5rPhaLsHXYeJbsvdpbJwL6yCHtMk91hc0ufQ2BnXis+0QQ9NBh6n9n+Q3OyjR6OQLShYbaNBkThQ==
react-is@^16.10.2, react-is@^16.12.0, react-is@^16.13.1, react-is@^16.7.0:
version "16.13.1"
@@ -13769,10 +14148,10 @@ react-virtualized-auto-sizer@1.0.6:
resolved "https://registry.yarnpkg.com/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.6.tgz#66c5b1c9278064c5ef1699ed40a29c11518f97ca"
integrity sha512-7tQ0BmZqfVF6YYEWcIGuoR3OdYe8I/ZFbNclFlGOC3pMqunkYF/oL30NCjSGl9sMEb17AnzixDz98Kqc3N76HQ==
-react-window@1.8.9:
- version "1.8.9"
- resolved "https://registry.yarnpkg.com/react-window/-/react-window-1.8.9.tgz#24bc346be73d0468cdf91998aac94e32bc7fa6a8"
- integrity sha512-+Eqx/fj1Aa5WnhRfj9dJg4VYATGwIUP2ItwItiJ6zboKWA6EX3lYDAXfGF2hyNqplEprhbtjbipiADEcwQ823Q==
+react-window@1.8.10:
+ version "1.8.10"
+ resolved "https://registry.yarnpkg.com/react-window/-/react-window-1.8.10.tgz#9e6b08548316814b443f7002b1cf8fd3a1bdde03"
+ integrity sha512-Y0Cx+dnU6NLa5/EvoHukUD0BklJ8qITCtVEPY1C/nL8wwoZ0b5aEw8Ff1dOVHw7fCzMt55XfJDd8S8W8LCaUCg==
dependencies:
"@babel/runtime" "^7.0.0"
memoize-one ">=3.1.1 <6"
@@ -13818,9 +14197,9 @@ readable-stream@^2.0.6:
util-deprecate "~1.0.1"
readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.5.0, readable-stream@^3.6.0:
- version "3.6.1"
- resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.1.tgz#f9f9b5f536920253b3d26e7660e7da4ccff9bb62"
- integrity sha512-+rQmrWMYGA90yenhTYsLWAsLsqVC8osOw6PKE1HDYiO0gdPeKe/xDHNzIAIn4C91YQ6oenEhfYqqc1883qHbjQ==
+ version "3.6.2"
+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967"
+ integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==
dependencies:
inherits "^2.0.3"
string_decoder "^1.1.1"
@@ -13873,6 +14252,18 @@ redent@^3.0.0:
indent-string "^4.0.0"
strip-indent "^3.0.0"
+redis-errors@^1.0.0, redis-errors@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/redis-errors/-/redis-errors-1.2.0.tgz#eb62d2adb15e4eaf4610c04afe1529384250abad"
+ integrity sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==
+
+redis-parser@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/redis-parser/-/redis-parser-3.0.0.tgz#b66d828cdcafe6b4b8a428a7def4c6bcac31c8b4"
+ integrity sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==
+ dependencies:
+ redis-errors "^1.0.0"
+
reduce-css-calc@^2.1.8:
version "2.1.8"
resolved "https://registry.yarnpkg.com/reduce-css-calc/-/reduce-css-calc-2.1.8.tgz#7ef8761a28d614980dc0c982f772c93f7a99de03"
@@ -14007,7 +14398,7 @@ resolve.exports@^1.1.0:
resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-1.1.0.tgz#5ce842b94b05146c0e03076985d1d0e7e48c90c9"
integrity sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==
-resolve@1.22.8:
+resolve@1.22.8, resolve@^1.12.0, resolve@^1.19.0, resolve@^1.20.0, resolve@^1.22.0:
version "1.22.8"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d"
integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==
@@ -14016,15 +14407,6 @@ resolve@1.22.8:
path-parse "^1.0.7"
supports-preserve-symlinks-flag "^1.0.0"
-resolve@^1.12.0, resolve@^1.19.0, resolve@^1.20.0, resolve@^1.22.0:
- version "1.22.1"
- resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177"
- integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==
- dependencies:
- is-core-module "^2.9.0"
- path-parse "^1.0.7"
- supports-preserve-symlinks-flag "^1.0.0"
-
resolve@^2.0.0-next.3:
version "2.0.0-next.4"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.4.tgz#3d37a113d6429f496ec4752d2a2e58efb1fd4660"
@@ -14192,9 +14574,9 @@ safe-regex-test@^1.0.0:
is-regex "^1.1.4"
safe-stable-stringify@^2.1.0:
- version "2.4.2"
- resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.4.2.tgz#ec7b037768098bf65310d1d64370de0dc02353aa"
- integrity sha512-gMxvPJYhP0O9n2pvcfYfIuYgbledAOJFcqRThtPRmjscaipiwcwPPKLytpVzMkG2HAN87Qmo2d4PtGiri1dSLA==
+ version "2.4.3"
+ resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz#138c84b6f6edb3db5f8ef3ef7115b8f55ccbf886"
+ integrity sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==
"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
version "2.1.2"
@@ -14347,6 +14729,11 @@ signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7:
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9"
integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==
+signal-exit@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04"
+ integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==
+
simple-swizzle@^0.2.2:
version "0.2.2"
resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a"
@@ -14461,9 +14848,9 @@ split-on-first@^1.0.0:
integrity sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==
split2@^4.0.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/split2/-/split2-4.1.0.tgz#101907a24370f85bb782f08adaabe4e281ecf809"
- integrity sha512-VBiJxFkxiXRlUIeyMQi8s4hgvKCSjtknJv/LVYbrgALPwf5zSKmEwV9Lst25AkvMDnvxODugjdl6KZgwKM1WYQ==
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4"
+ integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==
sprintf-js@~1.0.2:
version "1.0.3"
@@ -14499,11 +14886,21 @@ stacktrace-parser@^0.1.10:
dependencies:
type-fest "^0.7.1"
+standard-as-callback@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/standard-as-callback/-/standard-as-callback-2.1.0.tgz#8953fc05359868a77b5b9739a665c5977bb7df45"
+ integrity sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==
+
"statuses@>= 1.5.0 < 2":
version "1.5.0"
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==
+std-env@^3.7.0:
+ version "3.7.0"
+ resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.7.0.tgz#c9f7386ced6ecf13360b6c6c55b8aaa4ef7481d2"
+ integrity sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==
+
stream-browserify@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-3.0.0.tgz#22b0a2850cdf6503e73085da1fc7b7d0c2122f2f"
@@ -14513,9 +14910,9 @@ stream-browserify@^3.0.0:
readable-stream "^3.5.0"
stream-shift@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d"
- integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.3.tgz#85b8fab4d71010fc3ba8772e8046cc49b8a3864b"
+ integrity sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==
stream-transform@^3.2.1:
version "3.2.1"
@@ -14678,6 +15075,11 @@ strip-final-newline@^2.0.0:
resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad"
integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==
+strip-final-newline@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz#52894c313fbff318835280aed60ff71ebf12b8fd"
+ integrity sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==
+
strip-hex-prefix@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz#0c5f155fef1151373377de9dbb588da05500e36f"
@@ -14799,6 +15201,11 @@ symbol-tree@^3.2.4:
resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2"
integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==
+system-architecture@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/system-architecture/-/system-architecture-0.1.0.tgz#71012b3ac141427d97c67c56bc7921af6bff122d"
+ integrity sha512-ulAk51I9UVUyJgxlv9M6lFot2WP3e7t8Kz9+IS6D4rVba1tR9kON+Ey69f+1R4Q8cd45Lod6a4IcJIxnzGc/zA==
+
tailwind-merge@1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/tailwind-merge/-/tailwind-merge-1.6.0.tgz#dd652005544aa0b04628e69688b7108265f0d441"
@@ -15104,7 +15511,7 @@ ts-mocha@^9.0.2:
optionalDependencies:
tsconfig-paths "^3.5.0"
-ts-node@10.9.1, ts-node@^10.7.0, ts-node@^10.9.1:
+ts-node@10.9.1, ts-node@^10.7.0:
version "10.9.1"
resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b"
integrity sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==
@@ -15301,6 +15708,11 @@ uc.micro@^1.0.1:
resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac"
integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==
+ufo@^1.3.0, ufo@^1.3.1, ufo@^1.3.2:
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/ufo/-/ufo-1.3.2.tgz#c7d719d0628a1c80c006d2240e0d169f6e3c0496"
+ integrity sha512-o+ORpgGwaYQXgqGDwd+hkS4PuZ3QnmqMMxRuajK/a38L6fTpcE5GPIfrf+L/KemFzfUpeUQc1rRS1iDBozvnFA==
+
uint8arrays@^3.0.0, uint8arrays@^3.1.0:
version "3.1.1"
resolved "https://registry.yarnpkg.com/uint8arrays/-/uint8arrays-3.1.1.tgz#2d8762acce159ccd9936057572dade9459f65ae0"
@@ -15318,6 +15730,27 @@ unbox-primitive@^1.0.2:
has-symbols "^1.0.3"
which-boxed-primitive "^1.0.2"
+uncrypto@^0.1.3:
+ version "0.1.3"
+ resolved "https://registry.yarnpkg.com/uncrypto/-/uncrypto-0.1.3.tgz#e1288d609226f2d02d8d69ee861fa20d8348ef2b"
+ integrity sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==
+
+unenv@^1.9.0:
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/unenv/-/unenv-1.9.0.tgz#469502ae85be1bd3a6aa60f810972b1a904ca312"
+ integrity sha512-QKnFNznRxmbOF1hDgzpqrlIf6NC5sbZ2OJ+5Wl3OX8uM+LUJXbj4TXvLJCtwbPTmbMHCLIz6JLKNinNsMShK9g==
+ dependencies:
+ consola "^3.2.3"
+ defu "^6.1.3"
+ mime "^3.0.0"
+ node-fetch-native "^1.6.1"
+ pathe "^1.1.1"
+
+unfetch@^4.2.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/unfetch/-/unfetch-4.2.0.tgz#7e21b0ef7d363d8d9af0fb929a5555f6ef97a3be"
+ integrity sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA==
+
unified@^10.0.0:
version "10.1.2"
resolved "https://registry.yarnpkg.com/unified/-/unified-10.1.2.tgz#b1d64e55dafe1f0b98bb6c719881103ecf6c86df"
@@ -15407,6 +15840,32 @@ unstated-next@^1.1.0:
resolved "https://registry.yarnpkg.com/unstated-next/-/unstated-next-1.1.0.tgz#7bb4911a12fdf3cc8ad3eb11a0b315e4a8685ea8"
integrity sha512-AAn47ZncPvgBGOvMcn8tSRxsrqwf2VdAPxLASTuLJvZt4rhKfDvUkmYZLGfclImSfTVMv7tF4ynaVxin0JjDCA==
+unstorage@^1.9.0:
+ version "1.10.1"
+ resolved "https://registry.yarnpkg.com/unstorage/-/unstorage-1.10.1.tgz#bf8cc00a406e40a6293e893da9807057d95875b0"
+ integrity sha512-rWQvLRfZNBpF+x8D3/gda5nUCQL2PgXy2jNG4U7/Rc9BGEv9+CAJd0YyGCROUBKs9v49Hg8huw3aih5Bf5TAVw==
+ dependencies:
+ anymatch "^3.1.3"
+ chokidar "^3.5.3"
+ destr "^2.0.2"
+ h3 "^1.8.2"
+ ioredis "^5.3.2"
+ listhen "^1.5.5"
+ lru-cache "^10.0.2"
+ mri "^1.2.0"
+ node-fetch-native "^1.4.1"
+ ofetch "^1.3.3"
+ ufo "^1.3.1"
+
+untun@^0.1.3:
+ version "0.1.3"
+ resolved "https://registry.yarnpkg.com/untun/-/untun-0.1.3.tgz#5d10dee37a3a5737ff03d158be877dae0a0e58a6"
+ integrity sha512-4luGP9LMYszMRZwsvyUd9MrxgEGZdZuZgpVQHEEX0lCYFESasVRvZd0EYpCkOIbJKHMuv0LskpXc/8Un+MJzEQ==
+ dependencies:
+ citty "^0.1.5"
+ consola "^3.2.3"
+ pathe "^1.1.1"
+
update-browserslist-db@^1.0.9:
version "1.0.10"
resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz#0f54b876545726f17d00cd9a2561e6dade943ff3"
@@ -15415,6 +15874,11 @@ update-browserslist-db@^1.0.9:
escalade "^3.1.1"
picocolors "^1.0.0"
+uqr@^0.1.2:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/uqr/-/uqr-0.1.2.tgz#5c6cd5dcff9581f9bb35b982cb89e2c483a41d7d"
+ integrity sha512-MJu7ypHq6QasgF5YRTjqscSzQp/W11zoUk6kvmlH+fmWEs63Y0Eib13hYFwAzagRJcVY8WVnlV+eBDUGMJ5IbA==
+
uri-js@^4.2.2:
version "4.4.1"
resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
@@ -15615,11 +16079,6 @@ wcwidth@^1.0.1:
dependencies:
defaults "^1.0.3"
-web-streams-polyfill@^3.0.3:
- version "3.2.1"
- resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz#71c2718c52b45fd49dbeee88634b3a60ceab42a6"
- integrity sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==
-
web3-utils@^1.3.4:
version "1.10.0"
resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.10.0.tgz#ca4c1b431a765c14ac7f773e92e0fd9377ccf578"
@@ -15726,9 +16185,9 @@ which-collection@^1.0.1:
is-weakset "^2.0.1"
which-module@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
- integrity sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.1.tgz#776b1fe35d90aebe99e8ac15eb24093389a4a409"
+ integrity sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==
which-typed-array@^1.1.2, which-typed-array@^1.1.8:
version "1.1.9"
@@ -15828,10 +16287,10 @@ ws@^7.2.0, ws@^7.3.1, ws@^7.4.0, ws@^7.4.5, ws@^7.5.1:
resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591"
integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==
-ws@^8.11.0, ws@^8.5.0:
- version "8.13.0"
- resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0"
- integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==
+ws@^8.11.0, ws@^8.16.0, ws@^8.5.0:
+ version "8.16.0"
+ resolved "https://registry.yarnpkg.com/ws/-/ws-8.16.0.tgz#d1cd774f36fbc07165066a60e40323eab6446fd4"
+ integrity sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==
ws@~8.2.3:
version "8.2.3"