From b4196fcf7d0d64923da108182cd6f69f236e8eba Mon Sep 17 00:00:00 2001 From: bry Date: Fri, 3 Jan 2025 13:05:04 -0600 Subject: [PATCH] create atas prior to claiming rewards --- .../src/utils/formPositionClaims.ts | 111 +++++++++++------- 1 file changed, 67 insertions(+), 44 deletions(-) diff --git a/packages/voter-stake-registry-hooks/src/utils/formPositionClaims.ts b/packages/voter-stake-registry-hooks/src/utils/formPositionClaims.ts index 03f1e4854..9365d8180 100644 --- a/packages/voter-stake-registry-hooks/src/utils/formPositionClaims.ts +++ b/packages/voter-stake-registry-hooks/src/utils/formPositionClaims.ts @@ -1,4 +1,4 @@ -import { AnchorProvider, BN, Program } from "@coral-xyz/anchor"; +import { AnchorProvider, BN } from "@coral-xyz/anchor"; import { PROGRAM_ID as CIRCUIT_BREAKER_PROGRAM_ID, accountWindowedBreakerKey, @@ -12,7 +12,12 @@ import { init, subDaoEpochInfoKey, } from "@helium/helium-sub-daos-sdk"; -import { HNT_MINT, chunks, truthy } from "@helium/spl-utils"; +import { + HNT_MINT, + chunks, + fetchBackwardsCompatibleIdl, + truthy, +} from "@helium/spl-utils"; import { PROGRAM_ID as VSR_PROGRAM_ID, isClaimed, @@ -20,6 +25,7 @@ import { import { ASSOCIATED_TOKEN_PROGRAM_ID, TOKEN_PROGRAM_ID, + createAssociatedTokenAccountIdempotentInstruction, getAssociatedTokenAddressSync, } from "@solana/spl-token"; import { @@ -30,7 +36,6 @@ import { SystemProgram, TransactionInstruction, } from "@solana/web3.js"; -import { fetchBackwardsCompatibleIdl } from "@helium/spl-utils"; import { PositionWithMeta, SubDao } from "../sdk/types"; const DAO = daoKey(HNT_MINT)[0]; @@ -45,7 +50,10 @@ export const formPositionClaims = async ({ hsdProgramId: PublicKey; }): Promise => { const instructions: TransactionInstruction[][] = []; - const hsdIdl = await fetchBackwardsCompatibleIdl(hsdProgramId, provider as any); + const hsdIdl = await fetchBackwardsCompatibleIdl( + hsdProgramId, + provider as any + ); const hsdProgram = await init(provider as any, hsdProgramId, hsdIdl); const connNoCache = new Connection(provider.connection.rpcEndpoint); const clock = await connNoCache.getAccountInfo(SYSVAR_CLOCK_PUBKEY); @@ -90,7 +98,9 @@ export const formPositionClaims = async ({ } return acc; }, {} as Record); - const daoAcc = await hsdProgram.account.daoV0.fetch(Object.values(subDaos)[0].dao); + const daoAcc = await hsdProgram.account.daoV0.fetch( + Object.values(subDaos)[0].dao + ); for (const [idx, position] of positions.entries()) { bucketedEpochsByPosition[position.pubkey.toBase58()] = @@ -129,8 +139,9 @@ export const formPositionClaims = async ({ // Chunk size is 128 because we want each chunk to correspond to the 128 bits in bitmap for (const chunk of chunks(epochsToClaim, 128)) { - const daoEpochInfoKeys = chunk.map((epoch) => - daoEpochInfoKey(subDaoAcc.dao, epoch.mul(new BN(EPOCH_LENGTH)))[0] + const daoEpochInfoKeys = chunk.map( + (epoch) => + daoEpochInfoKey(subDaoAcc.dao, epoch.mul(new BN(EPOCH_LENGTH)))[0] ); const daoEpochInfoAccounts = await getMultipleAccounts({ connection: hsdProgram.provider.connection, @@ -163,7 +174,10 @@ export const formPositionClaims = async ({ subDao: delegatedPosition.account!.subDao, delegatedPosition: delegatedPosition.key, hntMint: daoAcc.hntMint, - daoEpochInfo: daoEpochInfoKey(subDaoAcc.dao, epoch.mul(new BN(EPOCH_LENGTH)))[0], + daoEpochInfo: daoEpochInfoKey( + subDaoAcc.dao, + epoch.mul(new BN(EPOCH_LENGTH)) + )[0], delegatorPool: daoAcc.delegatorPool, delegatorAta: getAssociatedTokenAddressSync( daoAcc.hntMint, @@ -180,41 +194,41 @@ export const formPositionClaims = async ({ }) .instruction(); } else { - return hsdProgram.methods - .claimRewardsV0({ - epoch, - }) - .accountsStrict({ - position: position.pubkey, - mint: position.mint, - positionTokenAccount: getAssociatedTokenAddressSync( - position.mint, - provider.wallet.publicKey - ), - positionAuthority: provider.wallet.publicKey, - registrar: position.registrar, - dao: DAO, - subDao: delegatedPosition.account!.subDao, - delegatedPosition: delegatedPosition.key, - dntMint: subDaoAcc.dntMint, - subDaoEpochInfo: subDaoEpochInfoKey( - subDao, - epoch.mul(new BN(EPOCH_LENGTH)) - )[0], - delegatorPool: subDaoAcc.delegatorPool, - delegatorAta: getAssociatedTokenAddressSync( - subDaoAcc.dntMint, - provider.wallet.publicKey - ), - delegatorPoolCircuitBreaker: accountWindowedBreakerKey( - subDaoAcc.delegatorPool - )[0], - vsrProgram: VSR_PROGRAM_ID, - systemProgram: SystemProgram.programId, - circuitBreakerProgram: CIRCUIT_BREAKER_PROGRAM_ID, - associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID, - tokenProgram: TOKEN_PROGRAM_ID, - }) + return hsdProgram.methods + .claimRewardsV0({ + epoch, + }) + .accountsStrict({ + position: position.pubkey, + mint: position.mint, + positionTokenAccount: getAssociatedTokenAddressSync( + position.mint, + provider.wallet.publicKey + ), + positionAuthority: provider.wallet.publicKey, + registrar: position.registrar, + dao: DAO, + subDao: delegatedPosition.account!.subDao, + delegatedPosition: delegatedPosition.key, + dntMint: subDaoAcc.dntMint, + subDaoEpochInfo: subDaoEpochInfoKey( + subDao, + epoch.mul(new BN(EPOCH_LENGTH)) + )[0], + delegatorPool: subDaoAcc.delegatorPool, + delegatorAta: getAssociatedTokenAddressSync( + subDaoAcc.dntMint, + provider.wallet.publicKey + ), + delegatorPoolCircuitBreaker: accountWindowedBreakerKey( + subDaoAcc.delegatorPool + )[0], + vsrProgram: VSR_PROGRAM_ID, + systemProgram: SystemProgram.programId, + circuitBreakerProgram: CIRCUIT_BREAKER_PROGRAM_ID, + associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID, + tokenProgram: TOKEN_PROGRAM_ID, + }) .instruction(); } }) @@ -225,6 +239,15 @@ export const formPositionClaims = async ({ } instructions.push( + [HNT_MINT, ...[...subDaoKeys].map((subDao) => new PublicKey(subDao))].map( + (mint) => + createAssociatedTokenAccountIdempotentInstruction( + provider.wallet.publicKey, + provider.wallet.publicKey, + mint, + getAssociatedTokenAddressSync(mint, provider.wallet.publicKey) + ) + ), ...Object.entries(bucketedEpochsByPosition).reduce( (acc, [_, instructions]) => { instructions.map((ixs, idx) => { @@ -256,4 +279,4 @@ async function getMultipleAccounts({ } return results; -} \ No newline at end of file +}