Skip to content

Commit

Permalink
Merge branch 'main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
0xShuk authored Oct 4, 2024
2 parents 7e2147d + 28afc52 commit 0f12e46
Show file tree
Hide file tree
Showing 22 changed files with 325 additions and 111 deletions.
109 changes: 66 additions & 43 deletions VoterWeightPlugins/clients/PythVoterWeightPluginClient.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import {Client} from "@solana/governance-program-library";
import {PublicKey, TransactionInstruction} from "@solana/web3.js";
import BN from "bn.js";
import {PythClient, StakeAccount, StakeConnection} from "@pythnetwork/staking";
import {Provider, Wallet} from "@coral-xyz/anchor";
import {Program, Provider, Wallet} from "@coral-xyz/anchor";
import {VoterWeightAction} from "@solana/spl-governance";
import {convertVoterWeightActionToType} from "../lib/utils";
import queryClient from "@hooks/queries/queryClient";
import { getMaxVoterWeightRecordAddress, getVoterWeightRecordAddress, PythStakingClient, StakeAccountPositions } from "@pythnetwork/staking-sdk";

// A wrapper for the PythClient from @pythnetwork/staking, that implements the generic plugin client interface
// A wrapper for the PythClient from @pythnetwork/staking-sdk, that implements the generic plugin client interface
export class PythVoterWeightPluginClient extends Client<any> {
readonly requiresInputVoterWeight = false;
// The pyth plugin does not have a registrar account
Expand All @@ -16,23 +16,36 @@ export class PythVoterWeightPluginClient extends Client<any> {
}

async getMaxVoterWeightRecordPDA() {
const maxVoterWeightPk = (await this.client.program.methods.updateMaxVoterWeight().pubkeys()).maxVoterRecord

if (!maxVoterWeightPk) return null;
const [address, bump] = getMaxVoterWeightRecordAddress();

return {
maxVoterWeightPk,
maxVoterWeightRecordBump: 0 // This is wrong for Pyth - but it doesn't matter as it is not used
maxVoterWeightPk: address,
maxVoterWeightRecordBump: bump,
}
}

async getMaxVoterWeightRecord(realm: PublicKey, mint: PublicKey) {
const {maxVoterWeightPk} = await this.getMaxVoterWeightRecordPDA();
return this.client.stakingProgram.account.maxVoterWeightRecord.fetch(
maxVoterWeightPk,
);
}

async getVoterWeightRecordPDA(realm: PublicKey, mint: PublicKey, voter: PublicKey) {
const { voterWeightAccount } = await this.getUpdateVoterWeightPks([], voter, VoterWeightAction.CastVote, PublicKey.default);
const stakeAccount = await this.getStakeAccount(voter)
const [address, bump] = getVoterWeightRecordAddress(stakeAccount);

return {
voterWeightPk: voterWeightAccount,
voterWeightRecordBump: 0 // This is wrong for Pyth - but it doesn't matter as it is not used
};
voterWeightPk: address,
voterWeightRecordBump: bump,
}
}

async getVoterWeightRecord(realm: PublicKey, mint: PublicKey, walletPk: PublicKey) {
const {voterWeightPk} = await this.getVoterWeightRecordPDA(realm, mint, walletPk);
return this.client.stakingProgram.account.voterWeightRecord.fetch(
voterWeightPk,
);
}

// NO-OP Pyth records are created through the Pyth dApp.
Expand All @@ -45,54 +58,64 @@ export class PythVoterWeightPluginClient extends Client<any> {
return null;
}

private async getStakeAccount(voter: PublicKey): Promise<StakeAccount> {
private async getStakeAccount(voter: PublicKey): Promise<PublicKey> {
return queryClient.fetchQuery({
queryKey: ['pyth getStakeAccount', voter],
queryFn: () => this.client.getMainAccount(voter),
queryKey: ['pyth getStakeAccount', voter.toBase58()],
queryFn: () => this.client.getMainStakeAccount(voter).then(x => x?.stakeAccountPosition),
})
}

private async getUpdateVoterWeightPks(instructions: TransactionInstruction[], voter: PublicKey, action: VoterWeightAction, target?: PublicKey) {
async updateVoterWeightRecord(
voter: PublicKey,
realm: PublicKey,
mint: PublicKey,
action: VoterWeightAction,
inputRecordCallback?: () => Promise<PublicKey>,
target?: PublicKey
) {
const stakeAccount = await this.getStakeAccount(voter)

if (!stakeAccount) throw new Error("Stake account not found for voter " + voter.toString());
return this.client.withUpdateVoterWeight(
instructions,
const ix = await this.client.getUpdateVoterWeightInstruction(
stakeAccount,
{ [convertVoterWeightActionToType(action)]: {} } as any,
target
);
}

async updateVoterWeightRecord(voter: PublicKey, realm: PublicKey, mint: PublicKey, action: VoterWeightAction, inputRecordCallback?: () => Promise<PublicKey>, target?: PublicKey) {
const instructions: TransactionInstruction[] = [];
await this.getUpdateVoterWeightPks(instructions, voter, action, target);

return { pre: instructions };
target,
)

return { pre: [ix] };
}
// NO-OP
async updateMaxVoterWeightRecord(): Promise<TransactionInstruction | null> {
return null;
}
async calculateVoterWeight(voter: PublicKey): Promise<BN | null> {
const stakeAccount = await this.getStakeAccount(voter)

if (stakeAccount) {
return stakeAccount.getVoterWeight(await this.client.getTime()).toBN()
} else {
return new BN(0)
}
const voterWeight = await this.client.getVoterWeight(voter);
return new BN(voterWeight.toString());
}
constructor(program: typeof PythClient.prototype.program, private client: StakeConnection, devnet:boolean) {
super(program, devnet);

constructor(
program: Program<any>,
private client: PythStakingClient
) {
super(program);
}

static async connect(provider: Provider, devnet = false, wallet: Wallet): Promise<PythVoterWeightPluginClient> {
const pythClient = await PythClient.connect(
provider.connection,
wallet
)
static async connect(provider: Provider, programId: PublicKey, wallet: Wallet): Promise<PythVoterWeightPluginClient> {
const pythClient = new PythStakingClient({
connection: provider.connection,
wallet,
})

const dummyProgram = new Program(
{
version: "",
name: 'unrecognised',
accounts: [],
instructions: []
},
programId,
provider
);

return new PythVoterWeightPluginClient(pythClient.program, pythClient, devnet);
return new PythVoterWeightPluginClient(dummyProgram, pythClient);
}
}
2 changes: 1 addition & 1 deletion VoterWeightPlugins/clients/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export const loadClient = (
case 'gateway':
return GatewayClient.connect(provider)
case 'pyth':
return PythVoterWeightPluginClient.connect(provider, undefined, signer)
return PythVoterWeightPluginClient.connect(provider, programId, signer)
case 'VSR':
return VsrClient.connect(provider, programId)
case 'HeliumVSR':
Expand Down
2 changes: 2 additions & 0 deletions components/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import { tryParsePublicKey } from '@tools/core/pubkey'
import { useAsync } from 'react-async-hook'
import { useVsrClient } from '../VoterWeightPlugins/useVsrClient'
import { useRealmVoterWeightPlugins } from '@hooks/useRealmVoterWeightPlugins'
import TermsPopupModal from './TermsPopup'

const Notifications = dynamic(() => import('../components/Notification'), {
ssr: false,
Expand Down Expand Up @@ -327,6 +328,7 @@ export function AppContents(props: Props) {
<TransactionLoader></TransactionLoader>
<NftVotingCountingModal />
<PageBodyContainer>{props.children}</PageBodyContainer>
<TermsPopupModal />
</GatewayProvider>
</ThemeProvider>
</ErrorBoundary>
Expand Down
2 changes: 1 addition & 1 deletion components/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ const Footer = () => {
<SocialIcons className="mb-5" />
<div className="flex flex-col justify-center sm:space-x-2 text-center text-sm opacity-70 sm:flex-row sm:text-sm sm:text-left">
<div className="flex-shrink-0">
© 2023 Solana Technology Services LLC
© 2024 Realms Today Ltd
</div>
<span className="hidden sm:block mx-2">|</span>
<Link href="https://realms.today/terms" passHref>
Expand Down
57 changes: 57 additions & 0 deletions components/TermsPopup.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import Modal from "./Modal"
import Button, { SecondaryButton } from './Button'
import { useEffect, useState } from "react"
import { useRouter } from "next/router"

const TermsPopupModal = () => {
const [openModal, setOpenModal] = useState(true)
const [isClient, setIsClient] = useState(false)
const router = useRouter()

useEffect(() => {
setIsClient(true)
}, [])

useEffect(() => {
if (localStorage) {
const isTermAccepted = typeof window !== "undefined" ?
localStorage.getItem("accept-terms") === "true" :
false

if (isTermAccepted) {
setOpenModal(false)
}
}
})

const acceptTerms = () => {
localStorage.setItem("accept-terms", "true")
setOpenModal(false)
}

const rejectTerms = () => {
localStorage.setItem("accept-terms", "false")
router.push("https://realms.today?terms=rejected")
}

return (
<>
{isClient && openModal ?
(<Modal isOpen={openModal && isClient} onClose={() => setOpenModal(false)} bgClickClose={false} hideClose={true}>
<p className="text-justify">
The operating entity of this site and owner of the related intellectual property has
changed. The new operator is Realms Today Ltd. (the New Operator). We have accordingly
amended the Terms and the Private Policy governing the relationship between our users
and the New Operator. By clicking "accept", you represent and warrant that you agree to
the revised Terms and Private Policy.
</p>
<div className="flex gap-4 mt-4 justify-center">
<Button onClick={acceptTerms}>Accept</Button>
<SecondaryButton onClick={rejectTerms}>Reject</SecondaryButton>
</div>
</Modal>) : null
}
</>)
}

export default TermsPopupModal;
6 changes: 4 additions & 2 deletions hooks/PythNetwork/useScalingFactor.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
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";
import { PythStakingClient } from "@pythnetwork/staking-sdk";

/**
* Returns undefined for everything except the Pyth DAO
Expand All @@ -20,7 +20,9 @@ export default function usePythScalingFactor(): number | undefined {

const { data: scalingFactor } = useQuery(["pyth-scaling-factor"],
async (): Promise<number> => {
const pythClient = await PythClient.connect(connection, {} as NodeWallet)
const pythClient = new PythStakingClient({
connection,
})
return pythClient.getScalingFactor()
}, { enabled: plugin == "pyth" })

Expand Down
15 changes: 5 additions & 10 deletions hooks/queries/governancePower.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { StakeConnection } from "@parcl-oss/staking"
import {
LegacyVoterWeightAdapter,
} from '@models/voteWeights'
import { PythClient } from '@pythnetwork/staking'
import { PythStakingClient } from "@pythnetwork/staking-sdk";
import NodeWallet from '@coral-xyz/anchor/dist/cjs/nodewallet'
import { findPluginName } from '@constants/plugins'
import { useRealmVoterWeightPlugins } from '@hooks/useRealmVoterWeightPlugins'
Expand Down Expand Up @@ -102,17 +102,12 @@ export const getPythGovPower = async (
): Promise<BN> => {
if (!user) return new BN(0)

const pythClient = await PythClient.connect(
const pythClient = new PythStakingClient({
connection,
new NodeWallet(new Keypair())
)
const stakeAccount = await pythClient.getMainAccount(user)
})
const voterWeight = await pythClient.getVoterWeight(user)

if (stakeAccount) {
return stakeAccount.getVoterWeight(await pythClient.getTime()).toBN()
} else {
return new BN(0)
}
return new BN(voterWeight.toString())
}

export const getParclGovPower = async (
Expand Down
4 changes: 2 additions & 2 deletions hooks/useTreasuryInfo/convertAccountToAsset.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { BigNumber } from 'bignumber.js'

import { AccountType, AssetAccount } from '@utils/uiTypes/assets'
import { AssetType, Asset } from '@models/treasury/Asset'
import { getTreasuryAccountItemInfoV2 } from '@utils/treasuryTools'
import { getTreasuryAccountItemInfoV2Async } from '@utils/treasuryTools'
import TokenIcon from '@components/treasuryV2/icons/TokenIcon'
import { WSOL_MINT } from '@components/instructions/tools'
import { abbreviateAddress } from '@utils/formatting'
Expand All @@ -16,7 +16,7 @@ export const convertAccountToAsset = async (
councilMintAddress?: string,
communityMintAddress?: string
): Promise<Asset | null> => {
const info = getTreasuryAccountItemInfoV2(account)
const info = await getTreasuryAccountItemInfoV2Async(account)

switch (account.type) {
case AccountType.AUXILIARY_TOKEN:
Expand Down
2 changes: 1 addition & 1 deletion hub/components/GlobalFooter/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export function GlobalFooter(props: Props) {
'sm:text-sm',
)}
>
<div>© 2022 Solana Technology Services LLC</div>
<div>© 2024 Realms Today Ltd</div>
<div className="hidden sm:block mx-2">|</div>
<a href="https://realms.today/terms" target="_blank" rel="noreferrer">
Terms
Expand Down
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
},
"dependencies": {
"@blockworks-foundation/mango-mints-redemption": "0.0.11",
"@blockworks-foundation/mango-v4": "0.33.4",
"@blockworks-foundation/mango-v4": "0.33.5",
"@blockworks-foundation/mango-v4-settings": "0.14.24",
"@blockworks-foundation/mangolana": "0.0.18",
"@bonfida/spl-name-service": "0.1.47",
Expand Down Expand Up @@ -69,7 +69,8 @@
"@project-serum/serum": "0.13.65",
"@project-serum/sol-wallet-adapter": "0.2.6",
"@pythnetwork/client": "2.17.0",
"@pythnetwork/staking": "2.3.1",
"@pythnetwork/staking-sdk": "0.0.2",
"@pythnetwork/staking-wasm": "0.3.5",
"@radix-ui/react-accordion": "1.0.0",
"@radix-ui/react-aspect-ratio": "1.0.0",
"@radix-ui/react-dialog": "1.0.0",
Expand Down Expand Up @@ -228,6 +229,7 @@
"@types/bn.js": "5.1.0",
"@project-serum/sol-wallet-adapter": "0.2.6",
"@project-serum/serum": "0.13.65",
"@pythnetwork/staking-sdk/@coral-xyz/anchor": "0.30.1",
"@coral-xyz/anchor": "0.29.0",
"@coral-xyz/borsh": "0.27.0",
"bignumber.js": "9.0.2",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,7 @@ const EditToken = ({
const currentToken = mangoGroup!.banksMapByMint.get(formTokenPk)![0]
const groupInsuranceFund = mangoGroup.mintInfosMapByMint.get(formTokenPk)
?.groupInsuranceFund

console.log(currentToken.tier)
const vals = {
oraclePk: currentToken.oracle.toBase58(),
fallbackOracle: currentToken.fallbackOracle.toBase58(),
Expand Down Expand Up @@ -488,6 +488,7 @@ const EditToken = ({
platformLiquidationFee: currentToken.platformLiquidationFee.toNumber(),
collateralFeePerDay: currentToken.collateralFeePerDay,
disableAssetLiquidation: !currentToken.allowAssetLiquidation,
tier: currentToken.tier,
}
setForm((prevForm) => ({
...prevForm,
Expand Down Expand Up @@ -917,6 +918,13 @@ const EditToken = ({
type: InstructionInputType.SWITCH,
name: 'forceWithdraw',
},
{
label: keyToLabel['tier'],
subtitle: getAdditionalLabelInfo('tier'),
initialValue: form.tier,
type: InstructionInputType.INPUT,
name: 'tier',
},
]

return (
Expand Down
Loading

0 comments on commit 0f12e46

Please sign in to comment.