Skip to content

Commit

Permalink
merge: update from upstream/main with fixed conflicts
Browse files Browse the repository at this point in the history
  • Loading branch information
ggnine-jito committed Nov 11, 2024
1 parent 24abd5c commit edca25e
Show file tree
Hide file tree
Showing 490 changed files with 51,026 additions and 10,854 deletions.
1 change: 1 addition & 0 deletions .env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ DEVNET_RPC=https://mango.devnet.rpcpool.com

DEFAULT_GOVERNANCE_PROGRAM_ID=GTesTBiEWE32WHXXE2S4XbZvA5CrEc4xs6ZgRe895dP

NEXT_PUBLIC_JUPTER_SWAP_API_ENDPOINT=https://quote-api.jup.ag/v6
NEXT_PUBLIC_API_ENDPOINT=https://api.realms.today/graphql
NEXT_PUBLIC_DISCORD_APPLICATION_CLIENT_ID=1042836142560645130
NEXT_PUBLIC_DISCORD_MATCHDAY_CLIENT_ID=1044361939322683442
Expand Down
57 changes: 26 additions & 31 deletions .github/workflows/ci-main-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,29 +15,24 @@ jobs:
contents: read
security-events: write

strategy:
fail-fast: false
matrix:
language: ['javascript']

steps:
- name: Checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Initialise CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
languages: 'javascript'

- name: Run CodeQL
uses: github/codeql-action/analyze@v2

sca:
name: Dependency Scan
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v4

# Report all vulnerabilities GitHub security tab
- name: Report on all vulnerabilities
Expand All @@ -59,41 +54,41 @@ jobs:
format: 'table'
severity: 'CRITICAL'
exit-code: '1'

- name: Upload scan results
uses: github/codeql-action/upload-sarif@v2
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: 'trivy-results.sarif'

test:
name: Run Tests
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
name: Run Tests
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Setup Node
uses: actions/setup-node@v3
with:
node-version: lts/*
cache: yarn
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 20
cache: yarn

- name: Cache dependencies
uses: actions/cache@v3
with:
path: '**/node_modules'
key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}
- name: Cache dependencies
uses: actions/cache@v3
with:
path: '**/node_modules'
key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}

- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Install dependencies
run: yarn ci

- name: Run tests
run: yarn test-all
- name: Run tests
run: yarn test-all

pass:
name: All tests pass
needs: ['sast', 'sca', 'test']
runs-on: ubuntu-latest
steps:
- run: echo ok
- run: echo ok
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
lts/gallium
lts/iron
1 change: 1 addition & 0 deletions .vscode/deploy.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Please deploy
1 change: 0 additions & 1 deletion .yarnrc
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
--frozen-lockfile true
--add.exact true
ignore-scripts true
2 changes: 2 additions & 0 deletions @types/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@ export interface EndpointInfo {
name: EndpointTypes
url: string
}

export type GovernanceRole = 'council' | 'community';
259 changes: 259 additions & 0 deletions DriftStakeVoterPlugin/DriftVoterClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,259 @@
import { BN, Program, Provider } from '@coral-xyz/anchor'
import { Client } from '@solana/governance-program-library'
import {
getTokenOwnerRecordAddress,
SYSTEM_PROGRAM_ID,
} from '@solana/spl-governance'
import { PublicKey, TransactionInstruction } from '@solana/web3.js'
import { DriftStakeVoter, IDL } from './idl/driftStakeVoter'
import { IDL as DriftIDL } from './idl/drift'
import {
getInsuranceFundStakeAccountPublicKey,
getInsuranceFundVaultPublicKey,
getSpotMarketPublicKey,
unstakeSharesToAmountWithOpenRequest,
} from './driftSdk'
import { fetchTokenAccountByPubkey } from '@hooks/queries/tokenAccount'
import { DRIFT_STAKE_VOTER_PLUGIN } from './constants'
import { fetchRealmByPubkey } from '@hooks/queries/realm'
import queryClient from '@hooks/queries/queryClient'

export class DriftVoterClient extends Client<DriftStakeVoter> {
readonly requiresInputVoterWeight = true

async _fetchRegistrar(realm: PublicKey, mint: PublicKey) {
const { registrar: registrarPk } = this.getRegistrarPDA(realm, mint)
const registrar = await queryClient.fetchQuery(
['Drift', 'Plugin Registrar', registrarPk],
() => this.program.account.registrar.fetch(registrarPk)
)
return registrar
}

constructor(
public program: Program<DriftStakeVoter>,
public devnet: boolean
) {
super(program, devnet)
}

async calculateMaxVoterWeight(
_realm: PublicKey,
_mint: PublicKey
): Promise<BN | null> {
console.log(
'drift voter client was just asked to calculate max voter weight'
)
const { result: realm } = await fetchRealmByPubkey(
this.program.provider.connection,
_realm
)
console.log('drift voter client realm', 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,
inputVoterWeight: BN
): Promise<BN | null> {
const registrar = await this._fetchRegistrar(realm, mint)
const spotMarketIndex = registrar.spotMarketIndex // could just hardcode spotmarket pk
const driftProgramId = registrar.driftProgramId // likewise
const drift = new Program(DriftIDL, driftProgramId, this.program.provider)
const spotMarketPk = await getSpotMarketPublicKey(
driftProgramId,
spotMarketIndex
)
const insuranceFundVaultPk = await getInsuranceFundVaultPublicKey(
driftProgramId,
spotMarketIndex
)
const insuranceFundStakePk = await getInsuranceFundStakeAccountPublicKey(
driftProgramId,
voter,
spotMarketIndex
)

const insuranceFundStake = await queryClient.fetchQuery({
queryKey: ['Insurance Fund Stake', insuranceFundStakePk.toString()],
queryFn: async () =>
drift.account.insuranceFundStake.fetchNullable(insuranceFundStakePk),
})

if (insuranceFundStake === null) {
console.log('drift voter client', 'no insurance fund stake account found')
return inputVoterWeight
}

const spotMarket = await queryClient.fetchQuery({
queryKey: ['Drift Spot Market', spotMarketPk.toString()],
queryFn: async () => drift.account.spotMarket.fetchNullable(spotMarketPk),
})

if (spotMarket === null) {
console.log('Drift spot market not found: ' + spotMarketPk.toString())
return inputVoterWeight
}

const insuranceFundVault = await fetchTokenAccountByPubkey(
this.program.provider.connection,
insuranceFundVaultPk
)
if (insuranceFundVault.result === undefined) {
console.log(
'Insurance fund vault not found: ' + insuranceFundVaultPk.toString()
)
return inputVoterWeight
}

const nShares = insuranceFundStake.ifShares
const withdrawRequestShares = insuranceFundStake.lastWithdrawRequestShares
const withdrawRequestAmount = insuranceFundStake.lastWithdrawRequestValue
const totalIfShares = spotMarket.insuranceFund.totalShares
const insuranceFundVaultBalance = insuranceFundVault.result?.amount

const amount = unstakeSharesToAmountWithOpenRequest(
nShares,
withdrawRequestShares,
withdrawRequestAmount,
totalIfShares,
insuranceFundVaultBalance
)

return amount.add(inputVoterWeight)
}

async updateVoterWeightRecord(
voter: PublicKey,
realm: PublicKey,
mint: PublicKey
//action?: VoterWeightAction | undefined,
//inputRecordCallback?: (() => Promise<PublicKey>) | undefined
): Promise<{
pre: TransactionInstruction[]
post?: TransactionInstruction[] | undefined
}> {
const connection = this.program.provider.connection
const { result: realmAccount } = await fetchRealmByPubkey(connection, realm)
if (!realmAccount) throw new Error('Realm not found')
const tokenOwnerRecordPk = await getTokenOwnerRecordAddress(
realmAccount?.owner,
realm,
mint,
voter
)
const { voterWeightPk } = await this.getVoterWeightRecordPDA(
realm,
mint,
voter
)
const { registrar: registrarPk } = this.getRegistrarPDA(realm, mint)
const registrar = await this._fetchRegistrar(realm, mint)
const spotMarketIndex = registrar.spotMarketIndex // could just hardcode spotmarket pk
const driftProgramId = registrar.driftProgramId // likewise
const drift = new Program(DriftIDL, driftProgramId, this.program.provider)

//const drift = new Program(DriftIDL, driftProgramId, this.program.provider)
const spotMarketPk = await getSpotMarketPublicKey(
driftProgramId,
spotMarketIndex
)
const insuranceFundVaultPk = await getInsuranceFundVaultPublicKey(
driftProgramId,
spotMarketIndex
)
const insuranceFundStakePk = await getInsuranceFundStakeAccountPublicKey(
driftProgramId,
voter,
spotMarketIndex
)

const spotMarket = await queryClient.fetchQuery({
queryKey: ['Drift Spot Market', spotMarketPk.toString()],
queryFn: async () => drift.account.spotMarket.fetchNullable(spotMarketPk),
})
const spotMarketPkOrNull = spotMarket === null ? null : spotMarketPk

const insuranceFundVault = await fetchTokenAccountByPubkey(
this.program.provider.connection,
insuranceFundVaultPk
)
const insuranceFundVaultPkOrNull =
insuranceFundVault.found === false ? null : insuranceFundVaultPk

let insuranceFundStake:
| Awaited<ReturnType<typeof drift.account.insuranceFundStake.fetch>>
| undefined
try {
insuranceFundStake = await drift.account.insuranceFundStake.fetch(
insuranceFundStakePk
)
} catch (e) {
console.log('drift voter client', 'no insurance fund stake account found')
insuranceFundStake = undefined
}
const stakePkOrNull =
insuranceFundStake === undefined ? null : insuranceFundStakePk

const ix = await this.program.methods
.updateVoterWeightRecord()
.accountsStrict({
voterWeightRecord: voterWeightPk,
registrar: registrarPk,
driftProgram: driftProgramId,
spotMarket: spotMarketPkOrNull,
insuranceFundStake: stakePkOrNull,
insuranceFundVault: insuranceFundVaultPkOrNull,
tokenOwnerRecord: tokenOwnerRecordPk,
})
.instruction()

return { pre: [ix] }
}

// 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(DRIFT_STAKE_VOTER_PLUGIN),
devnet = false
): Promise<DriftVoterClient> {
return new DriftVoterClient(
new Program<DriftStakeVoter>(IDL, programId, provider),
devnet
)
}

async createVoterWeightRecord(
voter: PublicKey,
realm: PublicKey,
mint: PublicKey
): Promise<TransactionInstruction | null> {
const { voterWeightPk } = await this.getVoterWeightRecordPDA(
realm,
mint,
voter
)
const { registrar } = this.getRegistrarPDA(realm, mint)

return this.program.methods
.createVoterWeightRecord(voter)
.accounts({
voterWeightRecord: voterWeightPk,
registrar,
payer: voter,
systemProgram: SYSTEM_PROGRAM_ID,
})
.instruction()
}
}
Loading

0 comments on commit edca25e

Please sign in to comment.