-
Notifications
You must be signed in to change notification settings - Fork 38
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
16 changed files
with
6,701 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
import { Provider, BN, Program } from "@coral-xyz/anchor"; | ||
import { Keypair, PublicKey, TransactionInstruction } from "@solana/web3.js"; | ||
import idl from "./idl.json"; | ||
import tokenIdl from "./token-idl.json"; | ||
import {BonkPlugin} from "./type"; | ||
import { Client } from "@solana/governance-program-library"; | ||
import { fetchRealmByPubkey } from "@hooks/queries/realm"; | ||
import { TokenVoter } from "./token-type"; | ||
import { bonkRegistrarKey, bonkSdrKey, bonkVwrKey, tokenVoterKey, tokenVwrKey } from "./utils"; | ||
import { SplTokenStaking,stakingIdl } from "./stake"; | ||
import { VoterWeightAction, getTokenOwnerRecordAddress } from "@solana/spl-governance"; | ||
import { BONK_PLUGIN_PK } from "@constants/plugins"; | ||
|
||
export class BonkClient extends Client<BonkPlugin> { | ||
readonly requiresInputVoterWeight = true | ||
private tokenPlugin: Program<TokenVoter> | ||
private splTokenStaking: Program<SplTokenStaking> | ||
|
||
constructor( | ||
public program: Program<BonkPlugin>, | ||
tokenVoterProgram: Program<TokenVoter>, | ||
splTokenProgram: Program<SplTokenStaking> | ||
) { | ||
super(program) | ||
this.tokenPlugin = tokenVoterProgram | ||
this.splTokenStaking = splTokenProgram | ||
} | ||
|
||
private async fetchSdrs( | ||
voter: PublicKey, | ||
stakePool: PublicKey | ||
) { | ||
const sdrs = await this.splTokenStaking.account.stakeDepositReceipt.all([ | ||
{ | ||
memcmp: { | ||
offset: 8, | ||
bytes: voter.toBase58(), | ||
} | ||
}, | ||
{ | ||
memcmp: { | ||
offset: 72, | ||
bytes: stakePool.toBase58(), | ||
}, | ||
} | ||
]) | ||
|
||
const activeSdrs = sdrs.filter(sdr => | ||
sdr.account.depositTimestamp.add(sdr.account.lockupDuration).toNumber() > Date.now() /1000 | ||
) | ||
|
||
return activeSdrs | ||
} | ||
|
||
async calculateMaxVoterWeight( | ||
_realm: PublicKey, | ||
_mint: PublicKey | ||
): Promise<BN | null> { | ||
const { result: realm } = await fetchRealmByPubkey( | ||
this.program.provider.connection, | ||
_realm | ||
) | ||
|
||
return realm?.account.config?.communityMintMaxVoteWeightSource.value ?? null // TODO this code should not actually be called because this is not a max voter weight plugin | ||
} | ||
|
||
|
||
async calculateVoterWeight( | ||
voter: PublicKey, | ||
realm: PublicKey, | ||
mint: PublicKey | ||
): Promise<BN | null> { | ||
try { | ||
console.log("I have been called") | ||
const bonkRegistrarAddress = bonkRegistrarKey(realm, mint, this.program.programId) | ||
const bonkRegistrar = await this.program.account.registrar.fetch(bonkRegistrarAddress) | ||
|
||
const tokenVoterAddress = tokenVoterKey(realm, mint, voter, this.tokenPlugin.programId)[0] | ||
const tokenVoterAccount = await this.tokenPlugin.account.voter.fetch(tokenVoterAddress) | ||
const depositedTokens = tokenVoterAccount.deposits[0].amountDepositedNative | ||
const activeSdrs = await this.fetchSdrs(voter, bonkRegistrar.stakePool) | ||
const sdrBalance = activeSdrs.reduce((a,b) => a.add(b.account.depositAmount), new BN(0)) | ||
return depositedTokens.add(sdrBalance) | ||
} catch(e) { | ||
console.log(e) | ||
return null | ||
} | ||
} | ||
|
||
async updateVoterWeightRecord( | ||
voter: PublicKey, | ||
realm: PublicKey, | ||
mint: PublicKey, | ||
action?: VoterWeightAction, | ||
//inputRecordCallback?: (() => Promise<PublicKey>) | undefined | ||
): Promise<{ | ||
pre: TransactionInstruction[] | ||
post?: TransactionInstruction[] | undefined | ||
}> { | ||
const tokenVwrAddress = tokenVwrKey(realm, mint, voter, this.tokenPlugin.programId)[0] | ||
const bonkVwrAddresss = bonkVwrKey(realm, mint, voter, this.program.programId)[0] | ||
const sdrAddress = bonkSdrKey(bonkVwrAddresss, this.program.programId)[0] | ||
const bonkRegistrarAddress = bonkRegistrarKey(realm, mint, this.program.programId) | ||
const bonkRegistrar = await this.program.account.registrar.fetch(bonkRegistrarAddress) | ||
const tokenOwnerRecord = await getTokenOwnerRecordAddress( | ||
bonkRegistrar.governanceProgramId, realm, mint, voter | ||
) | ||
|
||
const proposal = Keypair.generate().publicKey | ||
const governance = Keypair.generate().publicKey | ||
|
||
const activeSdrs = await this.fetchSdrs(voter, bonkRegistrar.stakePool) | ||
const remainingAccounts = activeSdrs.map(sdr => ({ | ||
pubkey: sdr.publicKey, | ||
isWritable: false, | ||
isSigner: false | ||
})) | ||
|
||
const bonkUpdateIx = await this.program.methods.updateVoterWeightRecord( | ||
activeSdrs.length, | ||
proposal, | ||
{createProposal: {}} | ||
).accounts({ | ||
registrar: bonkRegistrarAddress, | ||
voterWeightRecord: bonkVwrAddresss, | ||
inputVoterWeight: tokenVwrAddress, | ||
governance, | ||
proposal, | ||
voterAuthority: voter, | ||
voterTokenOwnerRecord: tokenOwnerRecord, | ||
stakeDepositRecord: sdrAddress | ||
}) | ||
.remainingAccounts(remainingAccounts) | ||
.instruction() | ||
|
||
return {pre: [bonkUpdateIx]} | ||
} | ||
|
||
// NO-OP | ||
async createMaxVoterWeightRecord(): Promise<TransactionInstruction | null> { | ||
return null | ||
} | ||
|
||
// NO-OP | ||
async updateMaxVoterWeightRecord(): Promise<TransactionInstruction | null> { | ||
return null | ||
} | ||
|
||
static async connect( | ||
provider: Provider, | ||
programId = new PublicKey(BONK_PLUGIN_PK), | ||
) { | ||
const DEFAULT_TOKEN_VOTER_PROGRAMID = new PublicKey("HA99cuBQCCzZu1zuHN2qBxo2FBo1cxNLwKkdt6Prhy8v") | ||
const DEFAULT_SPL_STAKING_PROGRAMID = new PublicKey("STAKEkKzbdeKkqzKpLkNQD3SUuLgshDKCD7U8duxAbB") | ||
console.log(programId.toBase58(), "Main kayah") | ||
return new BonkClient( | ||
new Program<BonkPlugin>(idl as BonkPlugin, programId, provider), | ||
new Program<TokenVoter>(tokenIdl as TokenVoter, DEFAULT_TOKEN_VOTER_PROGRAMID, provider), | ||
new Program<SplTokenStaking>(stakingIdl as SplTokenStaking, DEFAULT_SPL_STAKING_PROGRAMID, provider) | ||
) | ||
} | ||
|
||
async createVoterWeightRecord( | ||
voter: PublicKey, | ||
realm: PublicKey, | ||
mint: PublicKey | ||
): Promise<TransactionInstruction | null> { | ||
return null | ||
} | ||
|
||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
import { GovernancePowerTitle } from "@components/TokenBalance/TokenBalanceCardWrapper" | ||
import { TokenDeposit } from "@components/TokenBalance/TokenDeposit" | ||
import { BN } from "@coral-xyz/anchor" | ||
import { useRealmCommunityMintInfoQuery, useRealmCouncilMintInfoQuery } from "@hooks/queries/mintInfo" | ||
import { useRealmQuery } from "@hooks/queries/realm" | ||
import { useRealmVoterWeightPlugins } from "@hooks/useRealmVoterWeightPlugins" | ||
import useWalletOnePointOh from "@hooks/useWalletOnePointOh" | ||
import { GoverningTokenRole } from "@solana/spl-governance" | ||
|
||
const BonkBalanceCard = () => { | ||
const mint = useRealmCommunityMintInfoQuery().data?.result | ||
const councilMint = useRealmCouncilMintInfoQuery().data?.result | ||
const realm = useRealmQuery().data?.result | ||
|
||
const wallet = useWalletOnePointOh() | ||
const connected = !!wallet?.connected | ||
const { | ||
ownVoterWeight: communityOwnVoterWeight, | ||
} = useRealmVoterWeightPlugins('community') | ||
const councilDepositVisible = realm?.account.config.councilMint !== undefined | ||
|
||
return ( | ||
<> | ||
{mint ? ( | ||
<div className={`${`w-full gap-8 md:gap-12`}`}> | ||
<GovernancePowerTitle /> | ||
{!connected && ( | ||
<div className={'text-xs text-white/50 mt-8'}> | ||
Connect your wallet to see governance power | ||
</div> | ||
)} | ||
<div className="w-full"> | ||
{ | ||
communityOwnVoterWeight && | ||
<div className=""> | ||
<div className="flex flex-row items-center gap-x-2"> | ||
<h3>Bonk Power:</h3> | ||
<h3 className=""> | ||
{communityOwnVoterWeight.value?.div(new BN(10**mint.decimals)).toNumber()}. | ||
{communityOwnVoterWeight.value?.mod(new BN(10**mint.decimals)).toNumber()} {' '} | ||
</h3> | ||
</div> | ||
<div className="text-orange text-sm mb-4"> | ||
<a href="https://bonkdao.com">Kindly visit bonkdao.com to adjust governing power</a> | ||
</div> | ||
</div> | ||
} | ||
{councilDepositVisible && ( | ||
<TokenDeposit | ||
mint={councilMint} | ||
tokenRole={GoverningTokenRole.Council} | ||
inAccountDetails={true} | ||
/> | ||
)} | ||
</div> | ||
</div> | ||
) : ( | ||
<> | ||
<div className="h-12 mb-4 rounded-lg animate-pulse bg-bkg-3" /> | ||
<div className="h-10 rounded-lg animate-pulse bg-bkg-3" /> | ||
</> | ||
)} | ||
</> | ||
) | ||
} | ||
|
||
export default BonkBalanceCard |
Oops, something went wrong.