Skip to content

Commit cb427fa

Browse files
feat(staking): add create staking account (#1899)
* feat(staking): add create staking account * go * go * go * go
1 parent 52bbbb4 commit cb427fa

File tree

6 files changed

+152
-13
lines changed

6 files changed

+152
-13
lines changed

apps/staking/src/api.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -336,11 +336,10 @@ export const loadAccountHistory = async (
336336
};
337337

338338
export const createStakeAccountAndDeposit = async (
339-
_client: PythStakingClient,
340-
_amount: bigint,
339+
client: PythStakingClient,
340+
amount: bigint,
341341
): Promise<PublicKey> => {
342-
await new Promise((resolve) => setTimeout(resolve, MOCK_DELAY));
343-
throw new NotImplementedError();
342+
return client.createStakeAccountAndDeposit(amount);
344343
};
345344

346345
export const deposit = async (

governance/pyth_staking_sdk/eslint.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export default [
66
rules: {
77
"n/no-unpublished-import": "off",
88
"unicorn/no-null": "off",
9+
"unicorn/prefer-node-protocol": "off",
910
},
1011
},
1112
];

governance/pyth_staking_sdk/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
"dependencies": {
3535
"@coral-xyz/anchor": "^0.30.1",
3636
"@pythnetwork/solana-utils": "workspace:*",
37+
"@solana/spl-governance": "^0.3.28",
3738
"@solana/spl-token": "^0.3.7",
3839
"@solana/web3.js": "^1.95.3"
3940
}

governance/pyth_staking_sdk/src/constants.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export const FRACTION_PRECISION_N = 1_000_000n;
1313

1414
export const POSITION_BUFFER_SIZE = 200;
1515
export const POSITIONS_ACCOUNT_HEADER_SIZE = DISCRIMINATOR_SIZE + 32;
16+
export const POSITIONS_ACCOUNT_SIZE = DISCRIMINATOR_SIZE + 32;
1617

1718
export const STAKING_PROGRAM_ADDRESS = new PublicKey(
1819
"pytS9TjG1qyAZypk7n8rw8gfW9sUaqqYyMhJQ4E7JCQ",
@@ -25,3 +26,7 @@ export const INTEGRITY_POOL_PROGRAM_ADDRESS = new PublicKey(
2526
export const PUBLISHER_CAPS_PROGRAM_ADDRESS = new PublicKey(
2627
"pytcD8uUjPxSLMsNqoVnm9dXQw9tKJJf3CQnGwa8oL7",
2728
);
29+
30+
export const GOVERNANCE_ADDRESS = new PublicKey(
31+
"pytGY6tWRgGinSCvRLnSv4fHfBTMoiDGiCsesmHWM6U",
32+
);

governance/pyth_staking_sdk/src/pyth-staking-client.ts

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
1+
import * as crypto from "crypto";
2+
13
import { AnchorProvider, BN, Program } from "@coral-xyz/anchor";
4+
import {
5+
getTokenOwnerRecordAddress,
6+
PROGRAM_VERSION_V2,
7+
withCreateTokenOwnerRecord,
8+
} from "@solana/spl-governance";
29
import {
310
type Account,
411
createTransferInstruction,
@@ -9,10 +16,12 @@ import type { AnchorWallet } from "@solana/wallet-adapter-react";
916
import {
1017
Connection,
1118
PublicKey,
19+
SystemProgram,
1220
Transaction,
1321
TransactionInstruction,
1422
} from "@solana/web3.js";
1523

24+
import { GOVERNANCE_ADDRESS, POSITIONS_ACCOUNT_SIZE } from "./constants";
1625
import {
1726
getConfigAddress,
1827
getPoolConfigAddress,
@@ -334,6 +343,99 @@ export class PythStakingClient {
334343
return sendTransaction(instructions, this.connection, this.wallet);
335344
}
336345

346+
public async hasGovernanceRecord(config: GlobalConfig): Promise<boolean> {
347+
const tokenOwnerRecordAddress = await getTokenOwnerRecordAddress(
348+
GOVERNANCE_ADDRESS,
349+
config.pythGovernanceRealm,
350+
config.pythTokenMint,
351+
this.wallet.publicKey,
352+
);
353+
const voterAccountInfo =
354+
await this.stakingProgram.provider.connection.getAccountInfo(
355+
tokenOwnerRecordAddress,
356+
);
357+
358+
return Boolean(voterAccountInfo);
359+
}
360+
361+
public async createStakeAccountAndDeposit(amount: bigint) {
362+
const globalConfig = await this.getGlobalConfig();
363+
364+
const senderTokenAccount = await getAssociatedTokenAddress(
365+
globalConfig.pythTokenMint,
366+
this.wallet.publicKey,
367+
);
368+
369+
const nonce = crypto.randomBytes(16).toString("hex");
370+
const stakeAccountPositions = await PublicKey.createWithSeed(
371+
this.wallet.publicKey,
372+
nonce,
373+
this.stakingProgram.programId,
374+
);
375+
376+
const minimumBalance =
377+
await this.stakingProgram.provider.connection.getMinimumBalanceForRentExemption(
378+
POSITIONS_ACCOUNT_SIZE,
379+
);
380+
381+
const instructions = [];
382+
383+
instructions.push(
384+
SystemProgram.createAccountWithSeed({
385+
fromPubkey: this.wallet.publicKey,
386+
newAccountPubkey: stakeAccountPositions,
387+
basePubkey: this.wallet.publicKey,
388+
seed: nonce,
389+
lamports: minimumBalance,
390+
space: POSITIONS_ACCOUNT_SIZE,
391+
programId: this.stakingProgram.programId,
392+
}),
393+
await this.stakingProgram.methods
394+
.createStakeAccount(this.wallet.publicKey, { fullyVested: {} })
395+
.accounts({
396+
stakeAccountPositions,
397+
})
398+
.instruction(),
399+
await this.stakingProgram.methods
400+
.createVoterRecord()
401+
.accounts({
402+
stakeAccountPositions,
403+
})
404+
.instruction(),
405+
);
406+
407+
if (!(await this.hasGovernanceRecord(globalConfig))) {
408+
await withCreateTokenOwnerRecord(
409+
instructions,
410+
GOVERNANCE_ADDRESS,
411+
PROGRAM_VERSION_V2,
412+
globalConfig.pythGovernanceRealm,
413+
this.wallet.publicKey,
414+
globalConfig.pythTokenMint,
415+
this.wallet.publicKey,
416+
);
417+
}
418+
419+
instructions.push(
420+
await this.stakingProgram.methods
421+
.joinDaoLlc(globalConfig.agreementHash)
422+
.accounts({
423+
stakeAccountPositions,
424+
})
425+
.instruction(),
426+
createTransferInstruction(
427+
senderTokenAccount,
428+
getStakeAccountCustodyAddress(stakeAccountPositions),
429+
this.wallet.publicKey,
430+
amount,
431+
),
432+
);
433+
434+
await sendTransaction(instructions, this.connection, this.wallet);
435+
436+
return stakeAccountPositions;
437+
}
438+
337439
public async depositTokensToStakeAccountCustody(
338440
stakeAccountPositions: PublicKey,
339441
amount: bigint,

0 commit comments

Comments
 (0)