diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index ed4c49b..bf36ede 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -154,9 +154,7 @@ jobs: name: jito_tip_router_program.so path: integration_tests/tests/fixtures/ - uses: taiki-e/install-action@nextest - # Test the non-BPF tests and the BPF tests separately - - run: cargo nextest run --all-features -E 'not test(bpf)' - - run: cargo nextest run --all-features -E 'test(bpf)' + - run: cargo nextest run --all-features env: SBF_OUT_DIR: ${{ github.workspace }}/integration_tests/tests/fixtures diff --git a/.gitignore b/.gitignore index 3b003a6..ade2598 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,5 @@ node_modules # Debugging program_errors.json test_errors.output -tests.output \ No newline at end of file +tests.output +integration_tests/tests/fixtures/jito_tip_router_program.so diff --git a/clients/js/jito_tip_router/accounts/weightTable.ts b/clients/js/jito_tip_router/accounts/weightTable.ts index 2e051e9..98614be 100644 --- a/clients/js/jito_tip_router/accounts/weightTable.ts +++ b/clients/js/jito_tip_router/accounts/weightTable.ts @@ -69,7 +69,7 @@ export function getWeightTableEncoder(): Encoder { ['slotCreated', getU64Encoder()], ['bump', getU8Encoder()], ['reserved', getArrayEncoder(getU8Encoder(), { size: 128 })], - ['table', getArrayEncoder(getWeightEntryEncoder(), { size: 32 })], + ['table', getArrayEncoder(getWeightEntryEncoder(), { size: 64 })], ]); } @@ -81,7 +81,7 @@ export function getWeightTableDecoder(): Decoder { ['slotCreated', getU64Decoder()], ['bump', getU8Decoder()], ['reserved', getArrayDecoder(getU8Decoder(), { size: 128 })], - ['table', getArrayDecoder(getWeightEntryDecoder(), { size: 32 })], + ['table', getArrayDecoder(getWeightEntryDecoder(), { size: 64 })], ]); } diff --git a/clients/js/jito_tip_router/instructions/distributeBaseNcnRewardRoute.ts b/clients/js/jito_tip_router/instructions/distributeBaseNcnRewardRoute.ts index 358712f..e3865ca 100644 --- a/clients/js/jito_tip_router/instructions/distributeBaseNcnRewardRoute.ts +++ b/clients/js/jito_tip_router/instructions/distributeBaseNcnRewardRoute.ts @@ -8,8 +8,6 @@ import { combineCodec, - getOptionDecoder, - getOptionEncoder, getStructDecoder, getStructEncoder, getU64Decoder, @@ -25,8 +23,6 @@ import { type IInstruction, type IInstructionWithAccounts, type IInstructionWithData, - type Option, - type OptionOrNullable, type ReadonlyAccount, type WritableAccount, } from '@solana/web3.js'; @@ -79,12 +75,12 @@ export type DistributeBaseNcnRewardRouteInstruction< export type DistributeBaseNcnRewardRouteInstructionData = { discriminator: number; ncnFeeGroup: number; - firstSlotOfNcnEpoch: Option; + epoch: bigint; }; export type DistributeBaseNcnRewardRouteInstructionDataArgs = { ncnFeeGroup: number; - firstSlotOfNcnEpoch: OptionOrNullable; + epoch: number | bigint; }; export function getDistributeBaseNcnRewardRouteInstructionDataEncoder(): Encoder { @@ -92,7 +88,7 @@ export function getDistributeBaseNcnRewardRouteInstructionDataEncoder(): Encoder getStructEncoder([ ['discriminator', getU8Encoder()], ['ncnFeeGroup', getU8Encoder()], - ['firstSlotOfNcnEpoch', getOptionEncoder(getU64Encoder())], + ['epoch', getU64Encoder()], ]), (value) => ({ ...value, @@ -105,7 +101,7 @@ export function getDistributeBaseNcnRewardRouteInstructionDataDecoder(): Decoder return getStructDecoder([ ['discriminator', getU8Decoder()], ['ncnFeeGroup', getU8Decoder()], - ['firstSlotOfNcnEpoch', getOptionDecoder(getU64Decoder())], + ['epoch', getU64Decoder()], ]); } @@ -136,7 +132,7 @@ export type DistributeBaseNcnRewardRouteInput< ncnRewardRouter: Address; restakingProgram: Address; ncnFeeGroup: DistributeBaseNcnRewardRouteInstructionDataArgs['ncnFeeGroup']; - firstSlotOfNcnEpoch: DistributeBaseNcnRewardRouteInstructionDataArgs['firstSlotOfNcnEpoch']; + epoch: DistributeBaseNcnRewardRouteInstructionDataArgs['epoch']; }; export function getDistributeBaseNcnRewardRouteInstruction< diff --git a/clients/js/jito_tip_router/instructions/distributeBaseRewards.ts b/clients/js/jito_tip_router/instructions/distributeBaseRewards.ts index 951c63a..264b54c 100644 --- a/clients/js/jito_tip_router/instructions/distributeBaseRewards.ts +++ b/clients/js/jito_tip_router/instructions/distributeBaseRewards.ts @@ -8,8 +8,6 @@ import { combineCodec, - getOptionDecoder, - getOptionEncoder, getStructDecoder, getStructEncoder, getU64Decoder, @@ -25,8 +23,6 @@ import { type IInstruction, type IInstructionWithAccounts, type IInstructionWithData, - type Option, - type OptionOrNullable, type ReadonlyAccount, type WritableAccount, } from '@solana/web3.js'; @@ -75,12 +71,12 @@ export type DistributeBaseRewardsInstruction< export type DistributeBaseRewardsInstructionData = { discriminator: number; baseFeeGroup: number; - firstSlotOfNcnEpoch: Option; + epoch: bigint; }; export type DistributeBaseRewardsInstructionDataArgs = { baseFeeGroup: number; - firstSlotOfNcnEpoch: OptionOrNullable; + epoch: number | bigint; }; export function getDistributeBaseRewardsInstructionDataEncoder(): Encoder { @@ -88,7 +84,7 @@ export function getDistributeBaseRewardsInstructionDataEncoder(): Encoder ({ ...value, @@ -101,7 +97,7 @@ export function getDistributeBaseRewardsInstructionDataDecoder(): Decoder; restakingProgram: Address; baseFeeGroup: DistributeBaseRewardsInstructionDataArgs['baseFeeGroup']; - firstSlotOfNcnEpoch: DistributeBaseRewardsInstructionDataArgs['firstSlotOfNcnEpoch']; + epoch: DistributeBaseRewardsInstructionDataArgs['epoch']; }; export function getDistributeBaseRewardsInstruction< diff --git a/clients/js/jito_tip_router/instructions/distributeNcnOperatorRewards.ts b/clients/js/jito_tip_router/instructions/distributeNcnOperatorRewards.ts index 3e347dd..80e6bf0 100644 --- a/clients/js/jito_tip_router/instructions/distributeNcnOperatorRewards.ts +++ b/clients/js/jito_tip_router/instructions/distributeNcnOperatorRewards.ts @@ -8,8 +8,6 @@ import { combineCodec, - getOptionDecoder, - getOptionEncoder, getStructDecoder, getStructEncoder, getU64Decoder, @@ -25,8 +23,6 @@ import { type IInstruction, type IInstructionWithAccounts, type IInstructionWithData, - type Option, - type OptionOrNullable, type ReadonlyAccount, type WritableAccount, } from '@solana/web3.js'; @@ -75,12 +71,12 @@ export type DistributeNcnOperatorRewardsInstruction< export type DistributeNcnOperatorRewardsInstructionData = { discriminator: number; ncnFeeGroup: number; - firstSlotOfNcnEpoch: Option; + epoch: bigint; }; export type DistributeNcnOperatorRewardsInstructionDataArgs = { ncnFeeGroup: number; - firstSlotOfNcnEpoch: OptionOrNullable; + epoch: number | bigint; }; export function getDistributeNcnOperatorRewardsInstructionDataEncoder(): Encoder { @@ -88,7 +84,7 @@ export function getDistributeNcnOperatorRewardsInstructionDataEncoder(): Encoder getStructEncoder([ ['discriminator', getU8Encoder()], ['ncnFeeGroup', getU8Encoder()], - ['firstSlotOfNcnEpoch', getOptionEncoder(getU64Encoder())], + ['epoch', getU64Encoder()], ]), (value) => ({ ...value, @@ -101,7 +97,7 @@ export function getDistributeNcnOperatorRewardsInstructionDataDecoder(): Decoder return getStructDecoder([ ['discriminator', getU8Decoder()], ['ncnFeeGroup', getU8Decoder()], - ['firstSlotOfNcnEpoch', getOptionDecoder(getU64Decoder())], + ['epoch', getU64Decoder()], ]); } @@ -130,7 +126,7 @@ export type DistributeNcnOperatorRewardsInput< ncnRewardRouter: Address; restakingProgram: Address; ncnFeeGroup: DistributeNcnOperatorRewardsInstructionDataArgs['ncnFeeGroup']; - firstSlotOfNcnEpoch: DistributeNcnOperatorRewardsInstructionDataArgs['firstSlotOfNcnEpoch']; + epoch: DistributeNcnOperatorRewardsInstructionDataArgs['epoch']; }; export function getDistributeNcnOperatorRewardsInstruction< diff --git a/clients/js/jito_tip_router/instructions/distributeNcnVaultRewards.ts b/clients/js/jito_tip_router/instructions/distributeNcnVaultRewards.ts index 3b592c7..7287290 100644 --- a/clients/js/jito_tip_router/instructions/distributeNcnVaultRewards.ts +++ b/clients/js/jito_tip_router/instructions/distributeNcnVaultRewards.ts @@ -8,8 +8,6 @@ import { combineCodec, - getOptionDecoder, - getOptionEncoder, getStructDecoder, getStructEncoder, getU64Decoder, @@ -25,8 +23,6 @@ import { type IInstruction, type IInstructionWithAccounts, type IInstructionWithData, - type Option, - type OptionOrNullable, type ReadonlyAccount, type WritableAccount, } from '@solana/web3.js'; @@ -75,12 +71,12 @@ export type DistributeNcnVaultRewardsInstruction< export type DistributeNcnVaultRewardsInstructionData = { discriminator: number; ncnFeeGroup: number; - firstSlotOfNcnEpoch: Option; + epoch: bigint; }; export type DistributeNcnVaultRewardsInstructionDataArgs = { ncnFeeGroup: number; - firstSlotOfNcnEpoch: OptionOrNullable; + epoch: number | bigint; }; export function getDistributeNcnVaultRewardsInstructionDataEncoder(): Encoder { @@ -88,7 +84,7 @@ export function getDistributeNcnVaultRewardsInstructionDataEncoder(): Encoder ({ ...value, @@ -101,7 +97,7 @@ export function getDistributeNcnVaultRewardsInstructionDataDecoder(): Decoder; ncnRewardRouter: Address; ncnFeeGroup: DistributeNcnVaultRewardsInstructionDataArgs['ncnFeeGroup']; - firstSlotOfNcnEpoch: DistributeNcnVaultRewardsInstructionDataArgs['firstSlotOfNcnEpoch']; + epoch: DistributeNcnVaultRewardsInstructionDataArgs['epoch']; }; export function getDistributeNcnVaultRewardsInstruction< diff --git a/clients/js/jito_tip_router/instructions/index.ts b/clients/js/jito_tip_router/instructions/index.ts index fc6d751..87ffbe2 100644 --- a/clients/js/jito_tip_router/instructions/index.ts +++ b/clients/js/jito_tip_router/instructions/index.ts @@ -20,6 +20,10 @@ export * from './initializeNcnRewardRouter'; export * from './initializeOperatorSnapshot'; export * from './initializeTrackedMints'; export * from './initializeWeightTable'; +export * from './reallocBallotBox'; +export * from './reallocBaseRewardRouter'; +export * from './reallocOperatorSnapshot'; +export * from './reallocWeightTable'; export * from './registerMint'; export * from './routeBaseRewards'; export * from './routeNcnRewards'; diff --git a/clients/js/jito_tip_router/instructions/initializeBaseRewardRouter.ts b/clients/js/jito_tip_router/instructions/initializeBaseRewardRouter.ts index e748277..9cce92f 100644 --- a/clients/js/jito_tip_router/instructions/initializeBaseRewardRouter.ts +++ b/clients/js/jito_tip_router/instructions/initializeBaseRewardRouter.ts @@ -8,8 +8,6 @@ import { combineCodec, - getOptionDecoder, - getOptionEncoder, getStructDecoder, getStructEncoder, getU64Decoder, @@ -26,8 +24,6 @@ import { type IInstruction, type IInstructionWithAccounts, type IInstructionWithData, - type Option, - type OptionOrNullable, type ReadonlyAccount, type TransactionSigner, type WritableAccount, @@ -80,18 +76,18 @@ export type InitializeBaseRewardRouterInstruction< export type InitializeBaseRewardRouterInstructionData = { discriminator: number; - firstSlotOfNcnEpoch: Option; + epoch: bigint; }; export type InitializeBaseRewardRouterInstructionDataArgs = { - firstSlotOfNcnEpoch: OptionOrNullable; + epoch: number | bigint; }; export function getInitializeBaseRewardRouterInstructionDataEncoder(): Encoder { return transformEncoder( getStructEncoder([ ['discriminator', getU8Encoder()], - ['firstSlotOfNcnEpoch', getOptionEncoder(getU64Encoder())], + ['epoch', getU64Encoder()], ]), (value) => ({ ...value, @@ -103,7 +99,7 @@ export function getInitializeBaseRewardRouterInstructionDataEncoder(): Encoder { return getStructDecoder([ ['discriminator', getU8Decoder()], - ['firstSlotOfNcnEpoch', getOptionDecoder(getU64Decoder())], + ['epoch', getU64Decoder()], ]); } @@ -131,7 +127,7 @@ export type InitializeBaseRewardRouterInput< payer: TransactionSigner; restakingProgram: Address; systemProgram?: Address; - firstSlotOfNcnEpoch: InitializeBaseRewardRouterInstructionDataArgs['firstSlotOfNcnEpoch']; + epoch: InitializeBaseRewardRouterInstructionDataArgs['epoch']; }; export function getInitializeBaseRewardRouterInstruction< diff --git a/clients/js/jito_tip_router/instructions/initializeEpochSnapshot.ts b/clients/js/jito_tip_router/instructions/initializeEpochSnapshot.ts index 7abc93a..9dee829 100644 --- a/clients/js/jito_tip_router/instructions/initializeEpochSnapshot.ts +++ b/clients/js/jito_tip_router/instructions/initializeEpochSnapshot.ts @@ -8,8 +8,6 @@ import { combineCodec, - getOptionDecoder, - getOptionEncoder, getStructDecoder, getStructEncoder, getU64Decoder, @@ -26,8 +24,6 @@ import { type IInstruction, type IInstructionWithAccounts, type IInstructionWithData, - type Option, - type OptionOrNullable, type ReadonlyAccount, type TransactionSigner, type WritableAccount, @@ -92,18 +88,18 @@ export type InitializeEpochSnapshotInstruction< export type InitializeEpochSnapshotInstructionData = { discriminator: number; - firstSlotOfNcnEpoch: Option; + epoch: bigint; }; export type InitializeEpochSnapshotInstructionDataArgs = { - firstSlotOfNcnEpoch: OptionOrNullable; + epoch: number | bigint; }; export function getInitializeEpochSnapshotInstructionDataEncoder(): Encoder { return transformEncoder( getStructEncoder([ ['discriminator', getU8Encoder()], - ['firstSlotOfNcnEpoch', getOptionEncoder(getU64Encoder())], + ['epoch', getU64Encoder()], ]), (value) => ({ ...value, @@ -115,7 +111,7 @@ export function getInitializeEpochSnapshotInstructionDataEncoder(): Encoder { return getStructDecoder([ ['discriminator', getU8Decoder()], - ['firstSlotOfNcnEpoch', getOptionDecoder(getU64Decoder())], + ['epoch', getU64Decoder()], ]); } @@ -149,7 +145,7 @@ export type InitializeEpochSnapshotInput< payer: TransactionSigner; restakingProgram: Address; systemProgram?: Address; - firstSlotOfNcnEpoch: InitializeEpochSnapshotInstructionDataArgs['firstSlotOfNcnEpoch']; + epoch: InitializeEpochSnapshotInstructionDataArgs['epoch']; }; export function getInitializeEpochSnapshotInstruction< diff --git a/clients/js/jito_tip_router/instructions/initializeNcnRewardRouter.ts b/clients/js/jito_tip_router/instructions/initializeNcnRewardRouter.ts index 72f3994..33c6d45 100644 --- a/clients/js/jito_tip_router/instructions/initializeNcnRewardRouter.ts +++ b/clients/js/jito_tip_router/instructions/initializeNcnRewardRouter.ts @@ -8,8 +8,6 @@ import { combineCodec, - getOptionDecoder, - getOptionEncoder, getStructDecoder, getStructEncoder, getU64Decoder, @@ -26,8 +24,6 @@ import { type IInstruction, type IInstructionWithAccounts, type IInstructionWithData, - type Option, - type OptionOrNullable, type ReadonlyAccount, type TransactionSigner, type WritableAccount, @@ -85,12 +81,12 @@ export type InitializeNcnRewardRouterInstruction< export type InitializeNcnRewardRouterInstructionData = { discriminator: number; ncnFeeGroup: number; - firstSlotOfNcnEpoch: Option; + epoch: bigint; }; export type InitializeNcnRewardRouterInstructionDataArgs = { ncnFeeGroup: number; - firstSlotOfNcnEpoch: OptionOrNullable; + epoch: number | bigint; }; export function getInitializeNcnRewardRouterInstructionDataEncoder(): Encoder { @@ -98,7 +94,7 @@ export function getInitializeNcnRewardRouterInstructionDataEncoder(): Encoder ({ ...value, @@ -111,7 +107,7 @@ export function getInitializeNcnRewardRouterInstructionDataDecoder(): Decoder; systemProgram?: Address; ncnFeeGroup: InitializeNcnRewardRouterInstructionDataArgs['ncnFeeGroup']; - firstSlotOfNcnEpoch: InitializeNcnRewardRouterInstructionDataArgs['firstSlotOfNcnEpoch']; + epoch: InitializeNcnRewardRouterInstructionDataArgs['epoch']; }; export function getInitializeNcnRewardRouterInstruction< diff --git a/clients/js/jito_tip_router/instructions/initializeOperatorSnapshot.ts b/clients/js/jito_tip_router/instructions/initializeOperatorSnapshot.ts index ab51067..80f15fa 100644 --- a/clients/js/jito_tip_router/instructions/initializeOperatorSnapshot.ts +++ b/clients/js/jito_tip_router/instructions/initializeOperatorSnapshot.ts @@ -8,8 +8,6 @@ import { combineCodec, - getOptionDecoder, - getOptionEncoder, getStructDecoder, getStructEncoder, getU64Decoder, @@ -26,8 +24,6 @@ import { type IInstruction, type IInstructionWithAccounts, type IInstructionWithData, - type Option, - type OptionOrNullable, type ReadonlyAccount, type TransactionSigner, type WritableAccount, @@ -96,18 +92,18 @@ export type InitializeOperatorSnapshotInstruction< export type InitializeOperatorSnapshotInstructionData = { discriminator: number; - firstSlotOfNcnEpoch: Option; + epoch: bigint; }; export type InitializeOperatorSnapshotInstructionDataArgs = { - firstSlotOfNcnEpoch: OptionOrNullable; + epoch: number | bigint; }; export function getInitializeOperatorSnapshotInstructionDataEncoder(): Encoder { return transformEncoder( getStructEncoder([ ['discriminator', getU8Encoder()], - ['firstSlotOfNcnEpoch', getOptionEncoder(getU64Encoder())], + ['epoch', getU64Encoder()], ]), (value) => ({ ...value, @@ -119,7 +115,7 @@ export function getInitializeOperatorSnapshotInstructionDataEncoder(): Encoder { return getStructDecoder([ ['discriminator', getU8Decoder()], - ['firstSlotOfNcnEpoch', getOptionDecoder(getU64Decoder())], + ['epoch', getU64Decoder()], ]); } @@ -155,7 +151,7 @@ export type InitializeOperatorSnapshotInput< payer: TransactionSigner; restakingProgram: Address; systemProgram?: Address; - firstSlotOfNcnEpoch: InitializeOperatorSnapshotInstructionDataArgs['firstSlotOfNcnEpoch']; + epoch: InitializeOperatorSnapshotInstructionDataArgs['epoch']; }; export function getInitializeOperatorSnapshotInstruction< diff --git a/clients/js/jito_tip_router/instructions/initializeWeightTable.ts b/clients/js/jito_tip_router/instructions/initializeWeightTable.ts index 4b948ed..0f4efe7 100644 --- a/clients/js/jito_tip_router/instructions/initializeWeightTable.ts +++ b/clients/js/jito_tip_router/instructions/initializeWeightTable.ts @@ -8,8 +8,6 @@ import { combineCodec, - getOptionDecoder, - getOptionEncoder, getStructDecoder, getStructEncoder, getU64Decoder, @@ -26,8 +24,6 @@ import { type IInstruction, type IInstructionWithAccounts, type IInstructionWithData, - type Option, - type OptionOrNullable, type ReadonlyAccount, type TransactionSigner, type WritableAccount, @@ -84,18 +80,18 @@ export type InitializeWeightTableInstruction< export type InitializeWeightTableInstructionData = { discriminator: number; - firstSlotOfNcnEpoch: Option; + epoch: bigint; }; export type InitializeWeightTableInstructionDataArgs = { - firstSlotOfNcnEpoch: OptionOrNullable; + epoch: number | bigint; }; export function getInitializeWeightTableInstructionDataEncoder(): Encoder { return transformEncoder( getStructEncoder([ ['discriminator', getU8Encoder()], - ['firstSlotOfNcnEpoch', getOptionEncoder(getU64Encoder())], + ['epoch', getU64Encoder()], ]), (value) => ({ ...value, @@ -107,7 +103,7 @@ export function getInitializeWeightTableInstructionDataEncoder(): Encoder { return getStructDecoder([ ['discriminator', getU8Decoder()], - ['firstSlotOfNcnEpoch', getOptionDecoder(getU64Decoder())], + ['epoch', getU64Decoder()], ]); } @@ -137,7 +133,7 @@ export type InitializeWeightTableInput< payer: TransactionSigner; restakingProgram: Address; systemProgram?: Address; - firstSlotOfNcnEpoch: InitializeWeightTableInstructionDataArgs['firstSlotOfNcnEpoch']; + epoch: InitializeWeightTableInstructionDataArgs['epoch']; }; export function getInitializeWeightTableInstruction< diff --git a/clients/js/jito_tip_router/instructions/reallocBallotBox.ts b/clients/js/jito_tip_router/instructions/reallocBallotBox.ts new file mode 100644 index 0000000..ce036fb --- /dev/null +++ b/clients/js/jito_tip_router/instructions/reallocBallotBox.ts @@ -0,0 +1,241 @@ +/** + * This code was AUTOGENERATED using the kinobi library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun kinobi to update it. + * + * @see https://github.com/kinobi-so/kinobi + */ + +import { + combineCodec, + getStructDecoder, + getStructEncoder, + getU64Decoder, + getU64Encoder, + getU8Decoder, + getU8Encoder, + transformEncoder, + type Address, + type Codec, + type Decoder, + type Encoder, + type IAccountMeta, + type IAccountSignerMeta, + type IInstruction, + type IInstructionWithAccounts, + type IInstructionWithData, + type ReadonlyAccount, + type TransactionSigner, + type WritableAccount, + type WritableSignerAccount, +} from '@solana/web3.js'; +import { JITO_TIP_ROUTER_PROGRAM_ADDRESS } from '../programs'; +import { getAccountMetaFactory, type ResolvedAccount } from '../shared'; + +export const REALLOC_BALLOT_BOX_DISCRIMINATOR = 23; + +export function getReallocBallotBoxDiscriminatorBytes() { + return getU8Encoder().encode(REALLOC_BALLOT_BOX_DISCRIMINATOR); +} + +export type ReallocBallotBoxInstruction< + TProgram extends string = typeof JITO_TIP_ROUTER_PROGRAM_ADDRESS, + TAccountNcnConfig extends string | IAccountMeta = string, + TAccountBallotBox extends string | IAccountMeta = string, + TAccountNcn extends string | IAccountMeta = string, + TAccountPayer extends string | IAccountMeta = string, + TAccountSystemProgram extends + | string + | IAccountMeta = '11111111111111111111111111111111', + TRemainingAccounts extends readonly IAccountMeta[] = [], +> = IInstruction & + IInstructionWithData & + IInstructionWithAccounts< + [ + TAccountNcnConfig extends string + ? ReadonlyAccount + : TAccountNcnConfig, + TAccountBallotBox extends string + ? WritableAccount + : TAccountBallotBox, + TAccountNcn extends string ? ReadonlyAccount : TAccountNcn, + TAccountPayer extends string + ? WritableSignerAccount & + IAccountSignerMeta + : TAccountPayer, + TAccountSystemProgram extends string + ? ReadonlyAccount + : TAccountSystemProgram, + ...TRemainingAccounts, + ] + >; + +export type ReallocBallotBoxInstructionData = { + discriminator: number; + epoch: bigint; +}; + +export type ReallocBallotBoxInstructionDataArgs = { epoch: number | bigint }; + +export function getReallocBallotBoxInstructionDataEncoder(): Encoder { + return transformEncoder( + getStructEncoder([ + ['discriminator', getU8Encoder()], + ['epoch', getU64Encoder()], + ]), + (value) => ({ ...value, discriminator: REALLOC_BALLOT_BOX_DISCRIMINATOR }) + ); +} + +export function getReallocBallotBoxInstructionDataDecoder(): Decoder { + return getStructDecoder([ + ['discriminator', getU8Decoder()], + ['epoch', getU64Decoder()], + ]); +} + +export function getReallocBallotBoxInstructionDataCodec(): Codec< + ReallocBallotBoxInstructionDataArgs, + ReallocBallotBoxInstructionData +> { + return combineCodec( + getReallocBallotBoxInstructionDataEncoder(), + getReallocBallotBoxInstructionDataDecoder() + ); +} + +export type ReallocBallotBoxInput< + TAccountNcnConfig extends string = string, + TAccountBallotBox extends string = string, + TAccountNcn extends string = string, + TAccountPayer extends string = string, + TAccountSystemProgram extends string = string, +> = { + ncnConfig: Address; + ballotBox: Address; + ncn: Address; + payer: TransactionSigner; + systemProgram?: Address; + epoch: ReallocBallotBoxInstructionDataArgs['epoch']; +}; + +export function getReallocBallotBoxInstruction< + TAccountNcnConfig extends string, + TAccountBallotBox extends string, + TAccountNcn extends string, + TAccountPayer extends string, + TAccountSystemProgram extends string, + TProgramAddress extends Address = typeof JITO_TIP_ROUTER_PROGRAM_ADDRESS, +>( + input: ReallocBallotBoxInput< + TAccountNcnConfig, + TAccountBallotBox, + TAccountNcn, + TAccountPayer, + TAccountSystemProgram + >, + config?: { programAddress?: TProgramAddress } +): ReallocBallotBoxInstruction< + TProgramAddress, + TAccountNcnConfig, + TAccountBallotBox, + TAccountNcn, + TAccountPayer, + TAccountSystemProgram +> { + // Program address. + const programAddress = + config?.programAddress ?? JITO_TIP_ROUTER_PROGRAM_ADDRESS; + + // Original accounts. + const originalAccounts = { + ncnConfig: { value: input.ncnConfig ?? null, isWritable: false }, + ballotBox: { value: input.ballotBox ?? null, isWritable: true }, + ncn: { value: input.ncn ?? null, isWritable: false }, + payer: { value: input.payer ?? null, isWritable: true }, + systemProgram: { value: input.systemProgram ?? null, isWritable: false }, + }; + const accounts = originalAccounts as Record< + keyof typeof originalAccounts, + ResolvedAccount + >; + + // Original args. + const args = { ...input }; + + // Resolve default values. + if (!accounts.systemProgram.value) { + accounts.systemProgram.value = + '11111111111111111111111111111111' as Address<'11111111111111111111111111111111'>; + } + + const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); + const instruction = { + accounts: [ + getAccountMeta(accounts.ncnConfig), + getAccountMeta(accounts.ballotBox), + getAccountMeta(accounts.ncn), + getAccountMeta(accounts.payer), + getAccountMeta(accounts.systemProgram), + ], + programAddress, + data: getReallocBallotBoxInstructionDataEncoder().encode( + args as ReallocBallotBoxInstructionDataArgs + ), + } as ReallocBallotBoxInstruction< + TProgramAddress, + TAccountNcnConfig, + TAccountBallotBox, + TAccountNcn, + TAccountPayer, + TAccountSystemProgram + >; + + return instruction; +} + +export type ParsedReallocBallotBoxInstruction< + TProgram extends string = typeof JITO_TIP_ROUTER_PROGRAM_ADDRESS, + TAccountMetas extends readonly IAccountMeta[] = readonly IAccountMeta[], +> = { + programAddress: Address; + accounts: { + ncnConfig: TAccountMetas[0]; + ballotBox: TAccountMetas[1]; + ncn: TAccountMetas[2]; + payer: TAccountMetas[3]; + systemProgram: TAccountMetas[4]; + }; + data: ReallocBallotBoxInstructionData; +}; + +export function parseReallocBallotBoxInstruction< + TProgram extends string, + TAccountMetas extends readonly IAccountMeta[], +>( + instruction: IInstruction & + IInstructionWithAccounts & + IInstructionWithData +): ParsedReallocBallotBoxInstruction { + if (instruction.accounts.length < 5) { + // TODO: Coded error. + throw new Error('Not enough accounts'); + } + let accountIndex = 0; + const getNextAccount = () => { + const accountMeta = instruction.accounts![accountIndex]!; + accountIndex += 1; + return accountMeta; + }; + return { + programAddress: instruction.programAddress, + accounts: { + ncnConfig: getNextAccount(), + ballotBox: getNextAccount(), + ncn: getNextAccount(), + payer: getNextAccount(), + systemProgram: getNextAccount(), + }, + data: getReallocBallotBoxInstructionDataDecoder().decode(instruction.data), + }; +} diff --git a/clients/js/jito_tip_router/instructions/reallocBaseRewardRouter.ts b/clients/js/jito_tip_router/instructions/reallocBaseRewardRouter.ts new file mode 100644 index 0000000..9dbed08 --- /dev/null +++ b/clients/js/jito_tip_router/instructions/reallocBaseRewardRouter.ts @@ -0,0 +1,251 @@ +/** + * This code was AUTOGENERATED using the kinobi library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun kinobi to update it. + * + * @see https://github.com/kinobi-so/kinobi + */ + +import { + combineCodec, + getStructDecoder, + getStructEncoder, + getU64Decoder, + getU64Encoder, + getU8Decoder, + getU8Encoder, + transformEncoder, + type Address, + type Codec, + type Decoder, + type Encoder, + type IAccountMeta, + type IAccountSignerMeta, + type IInstruction, + type IInstructionWithAccounts, + type IInstructionWithData, + type ReadonlyAccount, + type TransactionSigner, + type WritableAccount, + type WritableSignerAccount, +} from '@solana/web3.js'; +import { JITO_TIP_ROUTER_PROGRAM_ADDRESS } from '../programs'; +import { getAccountMetaFactory, type ResolvedAccount } from '../shared'; + +export const REALLOC_BASE_REWARD_ROUTER_DISCRIMINATOR = 25; + +export function getReallocBaseRewardRouterDiscriminatorBytes() { + return getU8Encoder().encode(REALLOC_BASE_REWARD_ROUTER_DISCRIMINATOR); +} + +export type ReallocBaseRewardRouterInstruction< + TProgram extends string = typeof JITO_TIP_ROUTER_PROGRAM_ADDRESS, + TAccountNcnConfig extends string | IAccountMeta = string, + TAccountBaseRewardRouter extends string | IAccountMeta = string, + TAccountNcn extends string | IAccountMeta = string, + TAccountPayer extends string | IAccountMeta = string, + TAccountSystemProgram extends + | string + | IAccountMeta = '11111111111111111111111111111111', + TRemainingAccounts extends readonly IAccountMeta[] = [], +> = IInstruction & + IInstructionWithData & + IInstructionWithAccounts< + [ + TAccountNcnConfig extends string + ? ReadonlyAccount + : TAccountNcnConfig, + TAccountBaseRewardRouter extends string + ? WritableAccount + : TAccountBaseRewardRouter, + TAccountNcn extends string ? ReadonlyAccount : TAccountNcn, + TAccountPayer extends string + ? WritableSignerAccount & + IAccountSignerMeta + : TAccountPayer, + TAccountSystemProgram extends string + ? ReadonlyAccount + : TAccountSystemProgram, + ...TRemainingAccounts, + ] + >; + +export type ReallocBaseRewardRouterInstructionData = { + discriminator: number; + epoch: bigint; +}; + +export type ReallocBaseRewardRouterInstructionDataArgs = { + epoch: number | bigint; +}; + +export function getReallocBaseRewardRouterInstructionDataEncoder(): Encoder { + return transformEncoder( + getStructEncoder([ + ['discriminator', getU8Encoder()], + ['epoch', getU64Encoder()], + ]), + (value) => ({ + ...value, + discriminator: REALLOC_BASE_REWARD_ROUTER_DISCRIMINATOR, + }) + ); +} + +export function getReallocBaseRewardRouterInstructionDataDecoder(): Decoder { + return getStructDecoder([ + ['discriminator', getU8Decoder()], + ['epoch', getU64Decoder()], + ]); +} + +export function getReallocBaseRewardRouterInstructionDataCodec(): Codec< + ReallocBaseRewardRouterInstructionDataArgs, + ReallocBaseRewardRouterInstructionData +> { + return combineCodec( + getReallocBaseRewardRouterInstructionDataEncoder(), + getReallocBaseRewardRouterInstructionDataDecoder() + ); +} + +export type ReallocBaseRewardRouterInput< + TAccountNcnConfig extends string = string, + TAccountBaseRewardRouter extends string = string, + TAccountNcn extends string = string, + TAccountPayer extends string = string, + TAccountSystemProgram extends string = string, +> = { + ncnConfig: Address; + baseRewardRouter: Address; + ncn: Address; + payer: TransactionSigner; + systemProgram?: Address; + epoch: ReallocBaseRewardRouterInstructionDataArgs['epoch']; +}; + +export function getReallocBaseRewardRouterInstruction< + TAccountNcnConfig extends string, + TAccountBaseRewardRouter extends string, + TAccountNcn extends string, + TAccountPayer extends string, + TAccountSystemProgram extends string, + TProgramAddress extends Address = typeof JITO_TIP_ROUTER_PROGRAM_ADDRESS, +>( + input: ReallocBaseRewardRouterInput< + TAccountNcnConfig, + TAccountBaseRewardRouter, + TAccountNcn, + TAccountPayer, + TAccountSystemProgram + >, + config?: { programAddress?: TProgramAddress } +): ReallocBaseRewardRouterInstruction< + TProgramAddress, + TAccountNcnConfig, + TAccountBaseRewardRouter, + TAccountNcn, + TAccountPayer, + TAccountSystemProgram +> { + // Program address. + const programAddress = + config?.programAddress ?? JITO_TIP_ROUTER_PROGRAM_ADDRESS; + + // Original accounts. + const originalAccounts = { + ncnConfig: { value: input.ncnConfig ?? null, isWritable: false }, + baseRewardRouter: { + value: input.baseRewardRouter ?? null, + isWritable: true, + }, + ncn: { value: input.ncn ?? null, isWritable: false }, + payer: { value: input.payer ?? null, isWritable: true }, + systemProgram: { value: input.systemProgram ?? null, isWritable: false }, + }; + const accounts = originalAccounts as Record< + keyof typeof originalAccounts, + ResolvedAccount + >; + + // Original args. + const args = { ...input }; + + // Resolve default values. + if (!accounts.systemProgram.value) { + accounts.systemProgram.value = + '11111111111111111111111111111111' as Address<'11111111111111111111111111111111'>; + } + + const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); + const instruction = { + accounts: [ + getAccountMeta(accounts.ncnConfig), + getAccountMeta(accounts.baseRewardRouter), + getAccountMeta(accounts.ncn), + getAccountMeta(accounts.payer), + getAccountMeta(accounts.systemProgram), + ], + programAddress, + data: getReallocBaseRewardRouterInstructionDataEncoder().encode( + args as ReallocBaseRewardRouterInstructionDataArgs + ), + } as ReallocBaseRewardRouterInstruction< + TProgramAddress, + TAccountNcnConfig, + TAccountBaseRewardRouter, + TAccountNcn, + TAccountPayer, + TAccountSystemProgram + >; + + return instruction; +} + +export type ParsedReallocBaseRewardRouterInstruction< + TProgram extends string = typeof JITO_TIP_ROUTER_PROGRAM_ADDRESS, + TAccountMetas extends readonly IAccountMeta[] = readonly IAccountMeta[], +> = { + programAddress: Address; + accounts: { + ncnConfig: TAccountMetas[0]; + baseRewardRouter: TAccountMetas[1]; + ncn: TAccountMetas[2]; + payer: TAccountMetas[3]; + systemProgram: TAccountMetas[4]; + }; + data: ReallocBaseRewardRouterInstructionData; +}; + +export function parseReallocBaseRewardRouterInstruction< + TProgram extends string, + TAccountMetas extends readonly IAccountMeta[], +>( + instruction: IInstruction & + IInstructionWithAccounts & + IInstructionWithData +): ParsedReallocBaseRewardRouterInstruction { + if (instruction.accounts.length < 5) { + // TODO: Coded error. + throw new Error('Not enough accounts'); + } + let accountIndex = 0; + const getNextAccount = () => { + const accountMeta = instruction.accounts![accountIndex]!; + accountIndex += 1; + return accountMeta; + }; + return { + programAddress: instruction.programAddress, + accounts: { + ncnConfig: getNextAccount(), + baseRewardRouter: getNextAccount(), + ncn: getNextAccount(), + payer: getNextAccount(), + systemProgram: getNextAccount(), + }, + data: getReallocBaseRewardRouterInstructionDataDecoder().decode( + instruction.data + ), + }; +} diff --git a/clients/js/jito_tip_router/instructions/reallocOperatorSnapshot.ts b/clients/js/jito_tip_router/instructions/reallocOperatorSnapshot.ts new file mode 100644 index 0000000..a44af73 --- /dev/null +++ b/clients/js/jito_tip_router/instructions/reallocOperatorSnapshot.ts @@ -0,0 +1,330 @@ +/** + * This code was AUTOGENERATED using the kinobi library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun kinobi to update it. + * + * @see https://github.com/kinobi-so/kinobi + */ + +import { + combineCodec, + getStructDecoder, + getStructEncoder, + getU64Decoder, + getU64Encoder, + getU8Decoder, + getU8Encoder, + transformEncoder, + type Address, + type Codec, + type Decoder, + type Encoder, + type IAccountMeta, + type IAccountSignerMeta, + type IInstruction, + type IInstructionWithAccounts, + type IInstructionWithData, + type ReadonlyAccount, + type TransactionSigner, + type WritableAccount, + type WritableSignerAccount, +} from '@solana/web3.js'; +import { JITO_TIP_ROUTER_PROGRAM_ADDRESS } from '../programs'; +import { getAccountMetaFactory, type ResolvedAccount } from '../shared'; + +export const REALLOC_OPERATOR_SNAPSHOT_DISCRIMINATOR = 24; + +export function getReallocOperatorSnapshotDiscriminatorBytes() { + return getU8Encoder().encode(REALLOC_OPERATOR_SNAPSHOT_DISCRIMINATOR); +} + +export type ReallocOperatorSnapshotInstruction< + TProgram extends string = typeof JITO_TIP_ROUTER_PROGRAM_ADDRESS, + TAccountNcnConfig extends string | IAccountMeta = string, + TAccountRestakingConfig extends string | IAccountMeta = string, + TAccountNcn extends string | IAccountMeta = string, + TAccountOperator extends string | IAccountMeta = string, + TAccountNcnOperatorState extends string | IAccountMeta = string, + TAccountEpochSnapshot extends string | IAccountMeta = string, + TAccountOperatorSnapshot extends string | IAccountMeta = string, + TAccountPayer extends string | IAccountMeta = string, + TAccountRestakingProgram extends string | IAccountMeta = string, + TAccountSystemProgram extends + | string + | IAccountMeta = '11111111111111111111111111111111', + TRemainingAccounts extends readonly IAccountMeta[] = [], +> = IInstruction & + IInstructionWithData & + IInstructionWithAccounts< + [ + TAccountNcnConfig extends string + ? ReadonlyAccount + : TAccountNcnConfig, + TAccountRestakingConfig extends string + ? ReadonlyAccount + : TAccountRestakingConfig, + TAccountNcn extends string ? ReadonlyAccount : TAccountNcn, + TAccountOperator extends string + ? ReadonlyAccount + : TAccountOperator, + TAccountNcnOperatorState extends string + ? ReadonlyAccount + : TAccountNcnOperatorState, + TAccountEpochSnapshot extends string + ? WritableAccount + : TAccountEpochSnapshot, + TAccountOperatorSnapshot extends string + ? WritableAccount + : TAccountOperatorSnapshot, + TAccountPayer extends string + ? WritableSignerAccount & + IAccountSignerMeta + : TAccountPayer, + TAccountRestakingProgram extends string + ? ReadonlyAccount + : TAccountRestakingProgram, + TAccountSystemProgram extends string + ? ReadonlyAccount + : TAccountSystemProgram, + ...TRemainingAccounts, + ] + >; + +export type ReallocOperatorSnapshotInstructionData = { + discriminator: number; + epoch: bigint; +}; + +export type ReallocOperatorSnapshotInstructionDataArgs = { + epoch: number | bigint; +}; + +export function getReallocOperatorSnapshotInstructionDataEncoder(): Encoder { + return transformEncoder( + getStructEncoder([ + ['discriminator', getU8Encoder()], + ['epoch', getU64Encoder()], + ]), + (value) => ({ + ...value, + discriminator: REALLOC_OPERATOR_SNAPSHOT_DISCRIMINATOR, + }) + ); +} + +export function getReallocOperatorSnapshotInstructionDataDecoder(): Decoder { + return getStructDecoder([ + ['discriminator', getU8Decoder()], + ['epoch', getU64Decoder()], + ]); +} + +export function getReallocOperatorSnapshotInstructionDataCodec(): Codec< + ReallocOperatorSnapshotInstructionDataArgs, + ReallocOperatorSnapshotInstructionData +> { + return combineCodec( + getReallocOperatorSnapshotInstructionDataEncoder(), + getReallocOperatorSnapshotInstructionDataDecoder() + ); +} + +export type ReallocOperatorSnapshotInput< + TAccountNcnConfig extends string = string, + TAccountRestakingConfig extends string = string, + TAccountNcn extends string = string, + TAccountOperator extends string = string, + TAccountNcnOperatorState extends string = string, + TAccountEpochSnapshot extends string = string, + TAccountOperatorSnapshot extends string = string, + TAccountPayer extends string = string, + TAccountRestakingProgram extends string = string, + TAccountSystemProgram extends string = string, +> = { + ncnConfig: Address; + restakingConfig: Address; + ncn: Address; + operator: Address; + ncnOperatorState: Address; + epochSnapshot: Address; + operatorSnapshot: Address; + payer: TransactionSigner; + restakingProgram: Address; + systemProgram?: Address; + epoch: ReallocOperatorSnapshotInstructionDataArgs['epoch']; +}; + +export function getReallocOperatorSnapshotInstruction< + TAccountNcnConfig extends string, + TAccountRestakingConfig extends string, + TAccountNcn extends string, + TAccountOperator extends string, + TAccountNcnOperatorState extends string, + TAccountEpochSnapshot extends string, + TAccountOperatorSnapshot extends string, + TAccountPayer extends string, + TAccountRestakingProgram extends string, + TAccountSystemProgram extends string, + TProgramAddress extends Address = typeof JITO_TIP_ROUTER_PROGRAM_ADDRESS, +>( + input: ReallocOperatorSnapshotInput< + TAccountNcnConfig, + TAccountRestakingConfig, + TAccountNcn, + TAccountOperator, + TAccountNcnOperatorState, + TAccountEpochSnapshot, + TAccountOperatorSnapshot, + TAccountPayer, + TAccountRestakingProgram, + TAccountSystemProgram + >, + config?: { programAddress?: TProgramAddress } +): ReallocOperatorSnapshotInstruction< + TProgramAddress, + TAccountNcnConfig, + TAccountRestakingConfig, + TAccountNcn, + TAccountOperator, + TAccountNcnOperatorState, + TAccountEpochSnapshot, + TAccountOperatorSnapshot, + TAccountPayer, + TAccountRestakingProgram, + TAccountSystemProgram +> { + // Program address. + const programAddress = + config?.programAddress ?? JITO_TIP_ROUTER_PROGRAM_ADDRESS; + + // Original accounts. + const originalAccounts = { + ncnConfig: { value: input.ncnConfig ?? null, isWritable: false }, + restakingConfig: { + value: input.restakingConfig ?? null, + isWritable: false, + }, + ncn: { value: input.ncn ?? null, isWritable: false }, + operator: { value: input.operator ?? null, isWritable: false }, + ncnOperatorState: { + value: input.ncnOperatorState ?? null, + isWritable: false, + }, + epochSnapshot: { value: input.epochSnapshot ?? null, isWritable: true }, + operatorSnapshot: { + value: input.operatorSnapshot ?? null, + isWritable: true, + }, + payer: { value: input.payer ?? null, isWritable: true }, + restakingProgram: { + value: input.restakingProgram ?? null, + isWritable: false, + }, + systemProgram: { value: input.systemProgram ?? null, isWritable: false }, + }; + const accounts = originalAccounts as Record< + keyof typeof originalAccounts, + ResolvedAccount + >; + + // Original args. + const args = { ...input }; + + // Resolve default values. + if (!accounts.systemProgram.value) { + accounts.systemProgram.value = + '11111111111111111111111111111111' as Address<'11111111111111111111111111111111'>; + } + + const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); + const instruction = { + accounts: [ + getAccountMeta(accounts.ncnConfig), + getAccountMeta(accounts.restakingConfig), + getAccountMeta(accounts.ncn), + getAccountMeta(accounts.operator), + getAccountMeta(accounts.ncnOperatorState), + getAccountMeta(accounts.epochSnapshot), + getAccountMeta(accounts.operatorSnapshot), + getAccountMeta(accounts.payer), + getAccountMeta(accounts.restakingProgram), + getAccountMeta(accounts.systemProgram), + ], + programAddress, + data: getReallocOperatorSnapshotInstructionDataEncoder().encode( + args as ReallocOperatorSnapshotInstructionDataArgs + ), + } as ReallocOperatorSnapshotInstruction< + TProgramAddress, + TAccountNcnConfig, + TAccountRestakingConfig, + TAccountNcn, + TAccountOperator, + TAccountNcnOperatorState, + TAccountEpochSnapshot, + TAccountOperatorSnapshot, + TAccountPayer, + TAccountRestakingProgram, + TAccountSystemProgram + >; + + return instruction; +} + +export type ParsedReallocOperatorSnapshotInstruction< + TProgram extends string = typeof JITO_TIP_ROUTER_PROGRAM_ADDRESS, + TAccountMetas extends readonly IAccountMeta[] = readonly IAccountMeta[], +> = { + programAddress: Address; + accounts: { + ncnConfig: TAccountMetas[0]; + restakingConfig: TAccountMetas[1]; + ncn: TAccountMetas[2]; + operator: TAccountMetas[3]; + ncnOperatorState: TAccountMetas[4]; + epochSnapshot: TAccountMetas[5]; + operatorSnapshot: TAccountMetas[6]; + payer: TAccountMetas[7]; + restakingProgram: TAccountMetas[8]; + systemProgram: TAccountMetas[9]; + }; + data: ReallocOperatorSnapshotInstructionData; +}; + +export function parseReallocOperatorSnapshotInstruction< + TProgram extends string, + TAccountMetas extends readonly IAccountMeta[], +>( + instruction: IInstruction & + IInstructionWithAccounts & + IInstructionWithData +): ParsedReallocOperatorSnapshotInstruction { + if (instruction.accounts.length < 10) { + // TODO: Coded error. + throw new Error('Not enough accounts'); + } + let accountIndex = 0; + const getNextAccount = () => { + const accountMeta = instruction.accounts![accountIndex]!; + accountIndex += 1; + return accountMeta; + }; + return { + programAddress: instruction.programAddress, + accounts: { + ncnConfig: getNextAccount(), + restakingConfig: getNextAccount(), + ncn: getNextAccount(), + operator: getNextAccount(), + ncnOperatorState: getNextAccount(), + epochSnapshot: getNextAccount(), + operatorSnapshot: getNextAccount(), + payer: getNextAccount(), + restakingProgram: getNextAccount(), + systemProgram: getNextAccount(), + }, + data: getReallocOperatorSnapshotInstructionDataDecoder().decode( + instruction.data + ), + }; +} diff --git a/clients/js/jito_tip_router/instructions/reallocWeightTable.ts b/clients/js/jito_tip_router/instructions/reallocWeightTable.ts new file mode 100644 index 0000000..70e6605 --- /dev/null +++ b/clients/js/jito_tip_router/instructions/reallocWeightTable.ts @@ -0,0 +1,257 @@ +/** + * This code was AUTOGENERATED using the kinobi library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun kinobi to update it. + * + * @see https://github.com/kinobi-so/kinobi + */ + +import { + combineCodec, + getStructDecoder, + getStructEncoder, + getU64Decoder, + getU64Encoder, + getU8Decoder, + getU8Encoder, + transformEncoder, + type Address, + type Codec, + type Decoder, + type Encoder, + type IAccountMeta, + type IAccountSignerMeta, + type IInstruction, + type IInstructionWithAccounts, + type IInstructionWithData, + type ReadonlyAccount, + type TransactionSigner, + type WritableAccount, + type WritableSignerAccount, +} from '@solana/web3.js'; +import { JITO_TIP_ROUTER_PROGRAM_ADDRESS } from '../programs'; +import { getAccountMetaFactory, type ResolvedAccount } from '../shared'; + +export const REALLOC_WEIGHT_TABLE_DISCRIMINATOR = 26; + +export function getReallocWeightTableDiscriminatorBytes() { + return getU8Encoder().encode(REALLOC_WEIGHT_TABLE_DISCRIMINATOR); +} + +export type ReallocWeightTableInstruction< + TProgram extends string = typeof JITO_TIP_ROUTER_PROGRAM_ADDRESS, + TAccountNcnConfig extends string | IAccountMeta = string, + TAccountWeightTable extends string | IAccountMeta = string, + TAccountNcn extends string | IAccountMeta = string, + TAccountTrackedMints extends string | IAccountMeta = string, + TAccountPayer extends string | IAccountMeta = string, + TAccountSystemProgram extends + | string + | IAccountMeta = '11111111111111111111111111111111', + TRemainingAccounts extends readonly IAccountMeta[] = [], +> = IInstruction & + IInstructionWithData & + IInstructionWithAccounts< + [ + TAccountNcnConfig extends string + ? ReadonlyAccount + : TAccountNcnConfig, + TAccountWeightTable extends string + ? WritableAccount + : TAccountWeightTable, + TAccountNcn extends string ? ReadonlyAccount : TAccountNcn, + TAccountTrackedMints extends string + ? ReadonlyAccount + : TAccountTrackedMints, + TAccountPayer extends string + ? WritableSignerAccount & + IAccountSignerMeta + : TAccountPayer, + TAccountSystemProgram extends string + ? ReadonlyAccount + : TAccountSystemProgram, + ...TRemainingAccounts, + ] + >; + +export type ReallocWeightTableInstructionData = { + discriminator: number; + epoch: bigint; +}; + +export type ReallocWeightTableInstructionDataArgs = { epoch: number | bigint }; + +export function getReallocWeightTableInstructionDataEncoder(): Encoder { + return transformEncoder( + getStructEncoder([ + ['discriminator', getU8Encoder()], + ['epoch', getU64Encoder()], + ]), + (value) => ({ ...value, discriminator: REALLOC_WEIGHT_TABLE_DISCRIMINATOR }) + ); +} + +export function getReallocWeightTableInstructionDataDecoder(): Decoder { + return getStructDecoder([ + ['discriminator', getU8Decoder()], + ['epoch', getU64Decoder()], + ]); +} + +export function getReallocWeightTableInstructionDataCodec(): Codec< + ReallocWeightTableInstructionDataArgs, + ReallocWeightTableInstructionData +> { + return combineCodec( + getReallocWeightTableInstructionDataEncoder(), + getReallocWeightTableInstructionDataDecoder() + ); +} + +export type ReallocWeightTableInput< + TAccountNcnConfig extends string = string, + TAccountWeightTable extends string = string, + TAccountNcn extends string = string, + TAccountTrackedMints extends string = string, + TAccountPayer extends string = string, + TAccountSystemProgram extends string = string, +> = { + ncnConfig: Address; + weightTable: Address; + ncn: Address; + trackedMints: Address; + payer: TransactionSigner; + systemProgram?: Address; + epoch: ReallocWeightTableInstructionDataArgs['epoch']; +}; + +export function getReallocWeightTableInstruction< + TAccountNcnConfig extends string, + TAccountWeightTable extends string, + TAccountNcn extends string, + TAccountTrackedMints extends string, + TAccountPayer extends string, + TAccountSystemProgram extends string, + TProgramAddress extends Address = typeof JITO_TIP_ROUTER_PROGRAM_ADDRESS, +>( + input: ReallocWeightTableInput< + TAccountNcnConfig, + TAccountWeightTable, + TAccountNcn, + TAccountTrackedMints, + TAccountPayer, + TAccountSystemProgram + >, + config?: { programAddress?: TProgramAddress } +): ReallocWeightTableInstruction< + TProgramAddress, + TAccountNcnConfig, + TAccountWeightTable, + TAccountNcn, + TAccountTrackedMints, + TAccountPayer, + TAccountSystemProgram +> { + // Program address. + const programAddress = + config?.programAddress ?? JITO_TIP_ROUTER_PROGRAM_ADDRESS; + + // Original accounts. + const originalAccounts = { + ncnConfig: { value: input.ncnConfig ?? null, isWritable: false }, + weightTable: { value: input.weightTable ?? null, isWritable: true }, + ncn: { value: input.ncn ?? null, isWritable: false }, + trackedMints: { value: input.trackedMints ?? null, isWritable: false }, + payer: { value: input.payer ?? null, isWritable: true }, + systemProgram: { value: input.systemProgram ?? null, isWritable: false }, + }; + const accounts = originalAccounts as Record< + keyof typeof originalAccounts, + ResolvedAccount + >; + + // Original args. + const args = { ...input }; + + // Resolve default values. + if (!accounts.systemProgram.value) { + accounts.systemProgram.value = + '11111111111111111111111111111111' as Address<'11111111111111111111111111111111'>; + } + + const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); + const instruction = { + accounts: [ + getAccountMeta(accounts.ncnConfig), + getAccountMeta(accounts.weightTable), + getAccountMeta(accounts.ncn), + getAccountMeta(accounts.trackedMints), + getAccountMeta(accounts.payer), + getAccountMeta(accounts.systemProgram), + ], + programAddress, + data: getReallocWeightTableInstructionDataEncoder().encode( + args as ReallocWeightTableInstructionDataArgs + ), + } as ReallocWeightTableInstruction< + TProgramAddress, + TAccountNcnConfig, + TAccountWeightTable, + TAccountNcn, + TAccountTrackedMints, + TAccountPayer, + TAccountSystemProgram + >; + + return instruction; +} + +export type ParsedReallocWeightTableInstruction< + TProgram extends string = typeof JITO_TIP_ROUTER_PROGRAM_ADDRESS, + TAccountMetas extends readonly IAccountMeta[] = readonly IAccountMeta[], +> = { + programAddress: Address; + accounts: { + ncnConfig: TAccountMetas[0]; + weightTable: TAccountMetas[1]; + ncn: TAccountMetas[2]; + trackedMints: TAccountMetas[3]; + payer: TAccountMetas[4]; + systemProgram: TAccountMetas[5]; + }; + data: ReallocWeightTableInstructionData; +}; + +export function parseReallocWeightTableInstruction< + TProgram extends string, + TAccountMetas extends readonly IAccountMeta[], +>( + instruction: IInstruction & + IInstructionWithAccounts & + IInstructionWithData +): ParsedReallocWeightTableInstruction { + if (instruction.accounts.length < 6) { + // TODO: Coded error. + throw new Error('Not enough accounts'); + } + let accountIndex = 0; + const getNextAccount = () => { + const accountMeta = instruction.accounts![accountIndex]!; + accountIndex += 1; + return accountMeta; + }; + return { + programAddress: instruction.programAddress, + accounts: { + ncnConfig: getNextAccount(), + weightTable: getNextAccount(), + ncn: getNextAccount(), + trackedMints: getNextAccount(), + payer: getNextAccount(), + systemProgram: getNextAccount(), + }, + data: getReallocWeightTableInstructionDataDecoder().decode( + instruction.data + ), + }; +} diff --git a/clients/js/jito_tip_router/instructions/routeBaseRewards.ts b/clients/js/jito_tip_router/instructions/routeBaseRewards.ts index ade2a95..90d5d40 100644 --- a/clients/js/jito_tip_router/instructions/routeBaseRewards.ts +++ b/clients/js/jito_tip_router/instructions/routeBaseRewards.ts @@ -8,8 +8,6 @@ import { combineCodec, - getOptionDecoder, - getOptionEncoder, getStructDecoder, getStructEncoder, getU64Decoder, @@ -25,8 +23,6 @@ import { type IInstruction, type IInstructionWithAccounts, type IInstructionWithData, - type Option, - type OptionOrNullable, type ReadonlyAccount, type WritableAccount, } from '@solana/web3.js'; @@ -74,18 +70,16 @@ export type RouteBaseRewardsInstruction< export type RouteBaseRewardsInstructionData = { discriminator: number; - firstSlotOfNcnEpoch: Option; + epoch: bigint; }; -export type RouteBaseRewardsInstructionDataArgs = { - firstSlotOfNcnEpoch: OptionOrNullable; -}; +export type RouteBaseRewardsInstructionDataArgs = { epoch: number | bigint }; export function getRouteBaseRewardsInstructionDataEncoder(): Encoder { return transformEncoder( getStructEncoder([ ['discriminator', getU8Encoder()], - ['firstSlotOfNcnEpoch', getOptionEncoder(getU64Encoder())], + ['epoch', getU64Encoder()], ]), (value) => ({ ...value, discriminator: ROUTE_BASE_REWARDS_DISCRIMINATOR }) ); @@ -94,7 +88,7 @@ export function getRouteBaseRewardsInstructionDataEncoder(): Encoder { return getStructDecoder([ ['discriminator', getU8Decoder()], - ['firstSlotOfNcnEpoch', getOptionDecoder(getU64Decoder())], + ['epoch', getU64Decoder()], ]); } @@ -122,7 +116,7 @@ export type RouteBaseRewardsInput< ballotBox: Address; baseRewardRouter: Address; restakingProgram: Address; - firstSlotOfNcnEpoch: RouteBaseRewardsInstructionDataArgs['firstSlotOfNcnEpoch']; + epoch: RouteBaseRewardsInstructionDataArgs['epoch']; }; export function getRouteBaseRewardsInstruction< diff --git a/clients/js/jito_tip_router/instructions/routeNcnRewards.ts b/clients/js/jito_tip_router/instructions/routeNcnRewards.ts index 5304ce9..94de21a 100644 --- a/clients/js/jito_tip_router/instructions/routeNcnRewards.ts +++ b/clients/js/jito_tip_router/instructions/routeNcnRewards.ts @@ -8,8 +8,6 @@ import { combineCodec, - getOptionDecoder, - getOptionEncoder, getStructDecoder, getStructEncoder, getU64Decoder, @@ -25,8 +23,6 @@ import { type IInstruction, type IInstructionWithAccounts, type IInstructionWithData, - type Option, - type OptionOrNullable, type ReadonlyAccount, type WritableAccount, } from '@solana/web3.js'; @@ -75,12 +71,12 @@ export type RouteNcnRewardsInstruction< export type RouteNcnRewardsInstructionData = { discriminator: number; ncnFeeGroup: number; - firstSlotOfNcnEpoch: Option; + epoch: bigint; }; export type RouteNcnRewardsInstructionDataArgs = { ncnFeeGroup: number; - firstSlotOfNcnEpoch: OptionOrNullable; + epoch: number | bigint; }; export function getRouteNcnRewardsInstructionDataEncoder(): Encoder { @@ -88,7 +84,7 @@ export function getRouteNcnRewardsInstructionDataEncoder(): Encoder ({ ...value, discriminator: ROUTE_NCN_REWARDS_DISCRIMINATOR }) ); @@ -98,7 +94,7 @@ export function getRouteNcnRewardsInstructionDataDecoder(): Decoder; restakingProgram: Address; ncnFeeGroup: RouteNcnRewardsInstructionDataArgs['ncnFeeGroup']; - firstSlotOfNcnEpoch: RouteNcnRewardsInstructionDataArgs['firstSlotOfNcnEpoch']; + epoch: RouteNcnRewardsInstructionDataArgs['epoch']; }; export function getRouteNcnRewardsInstruction< diff --git a/clients/js/jito_tip_router/instructions/snapshotVaultOperatorDelegation.ts b/clients/js/jito_tip_router/instructions/snapshotVaultOperatorDelegation.ts index ef6b735..5d41d83 100644 --- a/clients/js/jito_tip_router/instructions/snapshotVaultOperatorDelegation.ts +++ b/clients/js/jito_tip_router/instructions/snapshotVaultOperatorDelegation.ts @@ -8,8 +8,6 @@ import { combineCodec, - getOptionDecoder, - getOptionEncoder, getStructDecoder, getStructEncoder, getU64Decoder, @@ -25,8 +23,6 @@ import { type IInstruction, type IInstructionWithAccounts, type IInstructionWithData, - type Option, - type OptionOrNullable, type ReadonlyAccount, type WritableAccount, } from '@solana/web3.js'; @@ -110,18 +106,18 @@ export type SnapshotVaultOperatorDelegationInstruction< export type SnapshotVaultOperatorDelegationInstructionData = { discriminator: number; - firstSlotOfNcnEpoch: Option; + epoch: bigint; }; export type SnapshotVaultOperatorDelegationInstructionDataArgs = { - firstSlotOfNcnEpoch: OptionOrNullable; + epoch: number | bigint; }; export function getSnapshotVaultOperatorDelegationInstructionDataEncoder(): Encoder { return transformEncoder( getStructEncoder([ ['discriminator', getU8Encoder()], - ['firstSlotOfNcnEpoch', getOptionEncoder(getU64Encoder())], + ['epoch', getU64Encoder()], ]), (value) => ({ ...value, @@ -133,7 +129,7 @@ export function getSnapshotVaultOperatorDelegationInstructionDataEncoder(): Enco export function getSnapshotVaultOperatorDelegationInstructionDataDecoder(): Decoder { return getStructDecoder([ ['discriminator', getU8Decoder()], - ['firstSlotOfNcnEpoch', getOptionDecoder(getU64Decoder())], + ['epoch', getU64Decoder()], ]); } @@ -177,7 +173,7 @@ export type SnapshotVaultOperatorDelegationInput< operatorSnapshot: Address; vaultProgram: Address; restakingProgram: Address; - firstSlotOfNcnEpoch: SnapshotVaultOperatorDelegationInstructionDataArgs['firstSlotOfNcnEpoch']; + epoch: SnapshotVaultOperatorDelegationInstructionDataArgs['epoch']; }; export function getSnapshotVaultOperatorDelegationInstruction< diff --git a/clients/js/jito_tip_router/programs/jitoTipRouter.ts b/clients/js/jito_tip_router/programs/jitoTipRouter.ts index a024c0a..fe1eff9 100644 --- a/clients/js/jito_tip_router/programs/jitoTipRouter.ts +++ b/clients/js/jito_tip_router/programs/jitoTipRouter.ts @@ -27,6 +27,10 @@ import { type ParsedInitializeOperatorSnapshotInstruction, type ParsedInitializeTrackedMintsInstruction, type ParsedInitializeWeightTableInstruction, + type ParsedReallocBallotBoxInstruction, + type ParsedReallocBaseRewardRouterInstruction, + type ParsedReallocOperatorSnapshotInstruction, + type ParsedReallocWeightTableInstruction, type ParsedRegisterMintInstruction, type ParsedRouteBaseRewardsInstruction, type ParsedRouteNcnRewardsInstruction, @@ -76,6 +80,10 @@ export enum JitoTipRouterInstruction { CastVote, SetMerkleRoot, SetTieBreaker, + ReallocBallotBox, + ReallocOperatorSnapshot, + ReallocBaseRewardRouter, + ReallocWeightTable, } export function identifyJitoTipRouterInstruction( @@ -151,6 +159,18 @@ export function identifyJitoTipRouterInstruction( if (containsBytes(data, getU8Encoder().encode(22), 0)) { return JitoTipRouterInstruction.SetTieBreaker; } + if (containsBytes(data, getU8Encoder().encode(23), 0)) { + return JitoTipRouterInstruction.ReallocBallotBox; + } + if (containsBytes(data, getU8Encoder().encode(24), 0)) { + return JitoTipRouterInstruction.ReallocOperatorSnapshot; + } + if (containsBytes(data, getU8Encoder().encode(25), 0)) { + return JitoTipRouterInstruction.ReallocBaseRewardRouter; + } + if (containsBytes(data, getU8Encoder().encode(26), 0)) { + return JitoTipRouterInstruction.ReallocWeightTable; + } throw new Error( 'The provided instruction could not be identified as a jitoTipRouter instruction.' ); @@ -227,4 +247,16 @@ export type ParsedJitoTipRouterInstruction< } & ParsedSetMerkleRootInstruction) | ({ instructionType: JitoTipRouterInstruction.SetTieBreaker; - } & ParsedSetTieBreakerInstruction); + } & ParsedSetTieBreakerInstruction) + | ({ + instructionType: JitoTipRouterInstruction.ReallocBallotBox; + } & ParsedReallocBallotBoxInstruction) + | ({ + instructionType: JitoTipRouterInstruction.ReallocOperatorSnapshot; + } & ParsedReallocOperatorSnapshotInstruction) + | ({ + instructionType: JitoTipRouterInstruction.ReallocBaseRewardRouter; + } & ParsedReallocBaseRewardRouterInstruction) + | ({ + instructionType: JitoTipRouterInstruction.ReallocWeightTable; + } & ParsedReallocWeightTableInstruction); diff --git a/clients/rust/jito_tip_router/src/generated/accounts/weight_table.rs b/clients/rust/jito_tip_router/src/generated/accounts/weight_table.rs index 9625c30..b272b18 100644 --- a/clients/rust/jito_tip_router/src/generated/accounts/weight_table.rs +++ b/clients/rust/jito_tip_router/src/generated/accounts/weight_table.rs @@ -23,7 +23,8 @@ pub struct WeightTable { pub bump: u8, #[cfg_attr(feature = "serde", serde(with = "serde_big_array::BigArray"))] pub reserved: [u8; 128], - pub table: [WeightEntry; 32], + #[cfg_attr(feature = "serde", serde(with = "serde_big_array::BigArray"))] + pub table: [WeightEntry; 64], } impl WeightTable { diff --git a/clients/rust/jito_tip_router/src/generated/instructions/distribute_base_ncn_reward_route.rs b/clients/rust/jito_tip_router/src/generated/instructions/distribute_base_ncn_reward_route.rs index cd5eb39..53692cd 100644 --- a/clients/rust/jito_tip_router/src/generated/instructions/distribute_base_ncn_reward_route.rs +++ b/clients/rust/jito_tip_router/src/generated/instructions/distribute_base_ncn_reward_route.rs @@ -100,7 +100,7 @@ impl Default for DistributeBaseNcnRewardRouteInstructionData { #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct DistributeBaseNcnRewardRouteInstructionArgs { pub ncn_fee_group: u8, - pub first_slot_of_ncn_epoch: Option, + pub epoch: u64, } /// Instruction builder for `DistributeBaseNcnRewardRoute`. @@ -124,7 +124,7 @@ pub struct DistributeBaseNcnRewardRouteBuilder { ncn_reward_router: Option, restaking_program: Option, ncn_fee_group: Option, - first_slot_of_ncn_epoch: Option, + epoch: Option, __remaining_accounts: Vec, } @@ -184,10 +184,9 @@ impl DistributeBaseNcnRewardRouteBuilder { self.ncn_fee_group = Some(ncn_fee_group); self } - /// `[optional argument]` #[inline(always)] - pub fn first_slot_of_ncn_epoch(&mut self, first_slot_of_ncn_epoch: u64) -> &mut Self { - self.first_slot_of_ncn_epoch = Some(first_slot_of_ncn_epoch); + pub fn epoch(&mut self, epoch: u64) -> &mut Self { + self.epoch = Some(epoch); self } /// Add an additional account to the instruction. @@ -230,7 +229,7 @@ impl DistributeBaseNcnRewardRouteBuilder { .ncn_fee_group .clone() .expect("ncn_fee_group is not set"), - first_slot_of_ncn_epoch: self.first_slot_of_ncn_epoch.clone(), + epoch: self.epoch.clone().expect("epoch is not set"), }; accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) @@ -423,7 +422,7 @@ impl<'a, 'b> DistributeBaseNcnRewardRouteCpiBuilder<'a, 'b> { ncn_reward_router: None, restaking_program: None, ncn_fee_group: None, - first_slot_of_ncn_epoch: None, + epoch: None, __remaining_accounts: Vec::new(), }); Self { instruction } @@ -486,10 +485,9 @@ impl<'a, 'b> DistributeBaseNcnRewardRouteCpiBuilder<'a, 'b> { self.instruction.ncn_fee_group = Some(ncn_fee_group); self } - /// `[optional argument]` #[inline(always)] - pub fn first_slot_of_ncn_epoch(&mut self, first_slot_of_ncn_epoch: u64) -> &mut Self { - self.instruction.first_slot_of_ncn_epoch = Some(first_slot_of_ncn_epoch); + pub fn epoch(&mut self, epoch: u64) -> &mut Self { + self.instruction.epoch = Some(epoch); self } /// Add an additional account to the instruction. @@ -539,7 +537,7 @@ impl<'a, 'b> DistributeBaseNcnRewardRouteCpiBuilder<'a, 'b> { .ncn_fee_group .clone() .expect("ncn_fee_group is not set"), - first_slot_of_ncn_epoch: self.instruction.first_slot_of_ncn_epoch.clone(), + epoch: self.instruction.epoch.clone().expect("epoch is not set"), }; let instruction = DistributeBaseNcnRewardRouteCpi { __program: self.instruction.__program, @@ -589,7 +587,7 @@ struct DistributeBaseNcnRewardRouteCpiBuilderInstruction<'a, 'b> { ncn_reward_router: Option<&'b solana_program::account_info::AccountInfo<'a>>, restaking_program: Option<&'b solana_program::account_info::AccountInfo<'a>>, ncn_fee_group: Option, - first_slot_of_ncn_epoch: Option, + epoch: Option, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<( &'b solana_program::account_info::AccountInfo<'a>, diff --git a/clients/rust/jito_tip_router/src/generated/instructions/distribute_base_rewards.rs b/clients/rust/jito_tip_router/src/generated/instructions/distribute_base_rewards.rs index ec1e0f7..50f5853 100644 --- a/clients/rust/jito_tip_router/src/generated/instructions/distribute_base_rewards.rs +++ b/clients/rust/jito_tip_router/src/generated/instructions/distribute_base_rewards.rs @@ -94,7 +94,7 @@ impl Default for DistributeBaseRewardsInstructionData { #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct DistributeBaseRewardsInstructionArgs { pub base_fee_group: u8, - pub first_slot_of_ncn_epoch: Option, + pub epoch: u64, } /// Instruction builder for `DistributeBaseRewards`. @@ -116,7 +116,7 @@ pub struct DistributeBaseRewardsBuilder { base_fee_wallet: Option, restaking_program: Option, base_fee_group: Option, - first_slot_of_ncn_epoch: Option, + epoch: Option, __remaining_accounts: Vec, } @@ -171,10 +171,9 @@ impl DistributeBaseRewardsBuilder { self.base_fee_group = Some(base_fee_group); self } - /// `[optional argument]` #[inline(always)] - pub fn first_slot_of_ncn_epoch(&mut self, first_slot_of_ncn_epoch: u64) -> &mut Self { - self.first_slot_of_ncn_epoch = Some(first_slot_of_ncn_epoch); + pub fn epoch(&mut self, epoch: u64) -> &mut Self { + self.epoch = Some(epoch); self } /// Add an additional account to the instruction. @@ -214,7 +213,7 @@ impl DistributeBaseRewardsBuilder { .base_fee_group .clone() .expect("base_fee_group is not set"), - first_slot_of_ncn_epoch: self.first_slot_of_ncn_epoch.clone(), + epoch: self.epoch.clone().expect("epoch is not set"), }; accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) @@ -395,7 +394,7 @@ impl<'a, 'b> DistributeBaseRewardsCpiBuilder<'a, 'b> { base_fee_wallet: None, restaking_program: None, base_fee_group: None, - first_slot_of_ncn_epoch: None, + epoch: None, __remaining_accounts: Vec::new(), }); Self { instruction } @@ -450,10 +449,9 @@ impl<'a, 'b> DistributeBaseRewardsCpiBuilder<'a, 'b> { self.instruction.base_fee_group = Some(base_fee_group); self } - /// `[optional argument]` #[inline(always)] - pub fn first_slot_of_ncn_epoch(&mut self, first_slot_of_ncn_epoch: u64) -> &mut Self { - self.instruction.first_slot_of_ncn_epoch = Some(first_slot_of_ncn_epoch); + pub fn epoch(&mut self, epoch: u64) -> &mut Self { + self.instruction.epoch = Some(epoch); self } /// Add an additional account to the instruction. @@ -503,7 +501,7 @@ impl<'a, 'b> DistributeBaseRewardsCpiBuilder<'a, 'b> { .base_fee_group .clone() .expect("base_fee_group is not set"), - first_slot_of_ncn_epoch: self.instruction.first_slot_of_ncn_epoch.clone(), + epoch: self.instruction.epoch.clone().expect("epoch is not set"), }; let instruction = DistributeBaseRewardsCpi { __program: self.instruction.__program, @@ -550,7 +548,7 @@ struct DistributeBaseRewardsCpiBuilderInstruction<'a, 'b> { base_fee_wallet: Option<&'b solana_program::account_info::AccountInfo<'a>>, restaking_program: Option<&'b solana_program::account_info::AccountInfo<'a>>, base_fee_group: Option, - first_slot_of_ncn_epoch: Option, + epoch: Option, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<( &'b solana_program::account_info::AccountInfo<'a>, diff --git a/clients/rust/jito_tip_router/src/generated/instructions/distribute_ncn_operator_rewards.rs b/clients/rust/jito_tip_router/src/generated/instructions/distribute_ncn_operator_rewards.rs index 130c238..40ce574 100644 --- a/clients/rust/jito_tip_router/src/generated/instructions/distribute_ncn_operator_rewards.rs +++ b/clients/rust/jito_tip_router/src/generated/instructions/distribute_ncn_operator_rewards.rs @@ -94,7 +94,7 @@ impl Default for DistributeNcnOperatorRewardsInstructionData { #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct DistributeNcnOperatorRewardsInstructionArgs { pub ncn_fee_group: u8, - pub first_slot_of_ncn_epoch: Option, + pub epoch: u64, } /// Instruction builder for `DistributeNcnOperatorRewards`. @@ -116,7 +116,7 @@ pub struct DistributeNcnOperatorRewardsBuilder { ncn_reward_router: Option, restaking_program: Option, ncn_fee_group: Option, - first_slot_of_ncn_epoch: Option, + epoch: Option, __remaining_accounts: Vec, } @@ -168,10 +168,9 @@ impl DistributeNcnOperatorRewardsBuilder { self.ncn_fee_group = Some(ncn_fee_group); self } - /// `[optional argument]` #[inline(always)] - pub fn first_slot_of_ncn_epoch(&mut self, first_slot_of_ncn_epoch: u64) -> &mut Self { - self.first_slot_of_ncn_epoch = Some(first_slot_of_ncn_epoch); + pub fn epoch(&mut self, epoch: u64) -> &mut Self { + self.epoch = Some(epoch); self } /// Add an additional account to the instruction. @@ -211,7 +210,7 @@ impl DistributeNcnOperatorRewardsBuilder { .ncn_fee_group .clone() .expect("ncn_fee_group is not set"), - first_slot_of_ncn_epoch: self.first_slot_of_ncn_epoch.clone(), + epoch: self.epoch.clone().expect("epoch is not set"), }; accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) @@ -392,7 +391,7 @@ impl<'a, 'b> DistributeNcnOperatorRewardsCpiBuilder<'a, 'b> { ncn_reward_router: None, restaking_program: None, ncn_fee_group: None, - first_slot_of_ncn_epoch: None, + epoch: None, __remaining_accounts: Vec::new(), }); Self { instruction } @@ -447,10 +446,9 @@ impl<'a, 'b> DistributeNcnOperatorRewardsCpiBuilder<'a, 'b> { self.instruction.ncn_fee_group = Some(ncn_fee_group); self } - /// `[optional argument]` #[inline(always)] - pub fn first_slot_of_ncn_epoch(&mut self, first_slot_of_ncn_epoch: u64) -> &mut Self { - self.instruction.first_slot_of_ncn_epoch = Some(first_slot_of_ncn_epoch); + pub fn epoch(&mut self, epoch: u64) -> &mut Self { + self.instruction.epoch = Some(epoch); self } /// Add an additional account to the instruction. @@ -500,7 +498,7 @@ impl<'a, 'b> DistributeNcnOperatorRewardsCpiBuilder<'a, 'b> { .ncn_fee_group .clone() .expect("ncn_fee_group is not set"), - first_slot_of_ncn_epoch: self.instruction.first_slot_of_ncn_epoch.clone(), + epoch: self.instruction.epoch.clone().expect("epoch is not set"), }; let instruction = DistributeNcnOperatorRewardsCpi { __program: self.instruction.__program, @@ -544,7 +542,7 @@ struct DistributeNcnOperatorRewardsCpiBuilderInstruction<'a, 'b> { ncn_reward_router: Option<&'b solana_program::account_info::AccountInfo<'a>>, restaking_program: Option<&'b solana_program::account_info::AccountInfo<'a>>, ncn_fee_group: Option, - first_slot_of_ncn_epoch: Option, + epoch: Option, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<( &'b solana_program::account_info::AccountInfo<'a>, diff --git a/clients/rust/jito_tip_router/src/generated/instructions/distribute_ncn_vault_rewards.rs b/clients/rust/jito_tip_router/src/generated/instructions/distribute_ncn_vault_rewards.rs index 9b6f36a..fe6660a 100644 --- a/clients/rust/jito_tip_router/src/generated/instructions/distribute_ncn_vault_rewards.rs +++ b/clients/rust/jito_tip_router/src/generated/instructions/distribute_ncn_vault_rewards.rs @@ -93,7 +93,7 @@ impl Default for DistributeNcnVaultRewardsInstructionData { #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct DistributeNcnVaultRewardsInstructionArgs { pub ncn_fee_group: u8, - pub first_slot_of_ncn_epoch: Option, + pub epoch: u64, } /// Instruction builder for `DistributeNcnVaultRewards`. @@ -115,7 +115,7 @@ pub struct DistributeNcnVaultRewardsBuilder { vault: Option, ncn_reward_router: Option, ncn_fee_group: Option, - first_slot_of_ncn_epoch: Option, + epoch: Option, __remaining_accounts: Vec, } @@ -164,10 +164,9 @@ impl DistributeNcnVaultRewardsBuilder { self.ncn_fee_group = Some(ncn_fee_group); self } - /// `[optional argument]` #[inline(always)] - pub fn first_slot_of_ncn_epoch(&mut self, first_slot_of_ncn_epoch: u64) -> &mut Self { - self.first_slot_of_ncn_epoch = Some(first_slot_of_ncn_epoch); + pub fn epoch(&mut self, epoch: u64) -> &mut Self { + self.epoch = Some(epoch); self } /// Add an additional account to the instruction. @@ -205,7 +204,7 @@ impl DistributeNcnVaultRewardsBuilder { .ncn_fee_group .clone() .expect("ncn_fee_group is not set"), - first_slot_of_ncn_epoch: self.first_slot_of_ncn_epoch.clone(), + epoch: self.epoch.clone().expect("epoch is not set"), }; accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) @@ -386,7 +385,7 @@ impl<'a, 'b> DistributeNcnVaultRewardsCpiBuilder<'a, 'b> { vault: None, ncn_reward_router: None, ncn_fee_group: None, - first_slot_of_ncn_epoch: None, + epoch: None, __remaining_accounts: Vec::new(), }); Self { instruction } @@ -438,10 +437,9 @@ impl<'a, 'b> DistributeNcnVaultRewardsCpiBuilder<'a, 'b> { self.instruction.ncn_fee_group = Some(ncn_fee_group); self } - /// `[optional argument]` #[inline(always)] - pub fn first_slot_of_ncn_epoch(&mut self, first_slot_of_ncn_epoch: u64) -> &mut Self { - self.instruction.first_slot_of_ncn_epoch = Some(first_slot_of_ncn_epoch); + pub fn epoch(&mut self, epoch: u64) -> &mut Self { + self.instruction.epoch = Some(epoch); self } /// Add an additional account to the instruction. @@ -491,7 +489,7 @@ impl<'a, 'b> DistributeNcnVaultRewardsCpiBuilder<'a, 'b> { .ncn_fee_group .clone() .expect("ncn_fee_group is not set"), - first_slot_of_ncn_epoch: self.instruction.first_slot_of_ncn_epoch.clone(), + epoch: self.instruction.epoch.clone().expect("epoch is not set"), }; let instruction = DistributeNcnVaultRewardsCpi { __program: self.instruction.__program, @@ -532,7 +530,7 @@ struct DistributeNcnVaultRewardsCpiBuilderInstruction<'a, 'b> { vault: Option<&'b solana_program::account_info::AccountInfo<'a>>, ncn_reward_router: Option<&'b solana_program::account_info::AccountInfo<'a>>, ncn_fee_group: Option, - first_slot_of_ncn_epoch: Option, + epoch: Option, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<( &'b solana_program::account_info::AccountInfo<'a>, diff --git a/clients/rust/jito_tip_router/src/generated/instructions/initialize_base_reward_router.rs b/clients/rust/jito_tip_router/src/generated/instructions/initialize_base_reward_router.rs index 2a1e5ed..7cac86f 100644 --- a/clients/rust/jito_tip_router/src/generated/instructions/initialize_base_reward_router.rs +++ b/clients/rust/jito_tip_router/src/generated/instructions/initialize_base_reward_router.rs @@ -92,7 +92,7 @@ impl Default for InitializeBaseRewardRouterInstructionData { #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct InitializeBaseRewardRouterInstructionArgs { - pub first_slot_of_ncn_epoch: Option, + pub epoch: u64, } /// Instruction builder for `InitializeBaseRewardRouter`. @@ -113,7 +113,7 @@ pub struct InitializeBaseRewardRouterBuilder { payer: Option, restaking_program: Option, system_program: Option, - first_slot_of_ncn_epoch: Option, + epoch: Option, __remaining_accounts: Vec, } @@ -161,10 +161,9 @@ impl InitializeBaseRewardRouterBuilder { self.system_program = Some(system_program); self } - /// `[optional argument]` #[inline(always)] - pub fn first_slot_of_ncn_epoch(&mut self, first_slot_of_ncn_epoch: u64) -> &mut Self { - self.first_slot_of_ncn_epoch = Some(first_slot_of_ncn_epoch); + pub fn epoch(&mut self, epoch: u64) -> &mut Self { + self.epoch = Some(epoch); self } /// Add an additional account to the instruction. @@ -202,7 +201,7 @@ impl InitializeBaseRewardRouterBuilder { .unwrap_or(solana_program::pubkey!("11111111111111111111111111111111")), }; let args = InitializeBaseRewardRouterInstructionArgs { - first_slot_of_ncn_epoch: self.first_slot_of_ncn_epoch.clone(), + epoch: self.epoch.clone().expect("epoch is not set"), }; accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) @@ -382,7 +381,7 @@ impl<'a, 'b> InitializeBaseRewardRouterCpiBuilder<'a, 'b> { payer: None, restaking_program: None, system_program: None, - first_slot_of_ncn_epoch: None, + epoch: None, __remaining_accounts: Vec::new(), }); Self { instruction } @@ -429,10 +428,9 @@ impl<'a, 'b> InitializeBaseRewardRouterCpiBuilder<'a, 'b> { self.instruction.system_program = Some(system_program); self } - /// `[optional argument]` #[inline(always)] - pub fn first_slot_of_ncn_epoch(&mut self, first_slot_of_ncn_epoch: u64) -> &mut Self { - self.instruction.first_slot_of_ncn_epoch = Some(first_slot_of_ncn_epoch); + pub fn epoch(&mut self, epoch: u64) -> &mut Self { + self.instruction.epoch = Some(epoch); self } /// Add an additional account to the instruction. @@ -477,7 +475,7 @@ impl<'a, 'b> InitializeBaseRewardRouterCpiBuilder<'a, 'b> { signers_seeds: &[&[&[u8]]], ) -> solana_program::entrypoint::ProgramResult { let args = InitializeBaseRewardRouterInstructionArgs { - first_slot_of_ncn_epoch: self.instruction.first_slot_of_ncn_epoch.clone(), + epoch: self.instruction.epoch.clone().expect("epoch is not set"), }; let instruction = InitializeBaseRewardRouterCpi { __program: self.instruction.__program, @@ -523,7 +521,7 @@ struct InitializeBaseRewardRouterCpiBuilderInstruction<'a, 'b> { payer: Option<&'b solana_program::account_info::AccountInfo<'a>>, restaking_program: Option<&'b solana_program::account_info::AccountInfo<'a>>, system_program: Option<&'b solana_program::account_info::AccountInfo<'a>>, - first_slot_of_ncn_epoch: Option, + epoch: Option, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<( &'b solana_program::account_info::AccountInfo<'a>, diff --git a/clients/rust/jito_tip_router/src/generated/instructions/initialize_epoch_snapshot.rs b/clients/rust/jito_tip_router/src/generated/instructions/initialize_epoch_snapshot.rs index 9660486..c88b51f 100644 --- a/clients/rust/jito_tip_router/src/generated/instructions/initialize_epoch_snapshot.rs +++ b/clients/rust/jito_tip_router/src/generated/instructions/initialize_epoch_snapshot.rs @@ -110,7 +110,7 @@ impl Default for InitializeEpochSnapshotInstructionData { #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct InitializeEpochSnapshotInstructionArgs { - pub first_slot_of_ncn_epoch: Option, + pub epoch: u64, } /// Instruction builder for `InitializeEpochSnapshot`. @@ -137,7 +137,7 @@ pub struct InitializeEpochSnapshotBuilder { payer: Option, restaking_program: Option, system_program: Option, - first_slot_of_ncn_epoch: Option, + epoch: Option, __remaining_accounts: Vec, } @@ -197,10 +197,9 @@ impl InitializeEpochSnapshotBuilder { self.system_program = Some(system_program); self } - /// `[optional argument]` #[inline(always)] - pub fn first_slot_of_ncn_epoch(&mut self, first_slot_of_ncn_epoch: u64) -> &mut Self { - self.first_slot_of_ncn_epoch = Some(first_slot_of_ncn_epoch); + pub fn epoch(&mut self, epoch: u64) -> &mut Self { + self.epoch = Some(epoch); self } /// Add an additional account to the instruction. @@ -239,7 +238,7 @@ impl InitializeEpochSnapshotBuilder { .unwrap_or(solana_program::pubkey!("11111111111111111111111111111111")), }; let args = InitializeEpochSnapshotInstructionArgs { - first_slot_of_ncn_epoch: self.first_slot_of_ncn_epoch.clone(), + epoch: self.epoch.clone().expect("epoch is not set"), }; accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) @@ -455,7 +454,7 @@ impl<'a, 'b> InitializeEpochSnapshotCpiBuilder<'a, 'b> { payer: None, restaking_program: None, system_program: None, - first_slot_of_ncn_epoch: None, + epoch: None, __remaining_accounts: Vec::new(), }); Self { instruction } @@ -526,10 +525,9 @@ impl<'a, 'b> InitializeEpochSnapshotCpiBuilder<'a, 'b> { self.instruction.system_program = Some(system_program); self } - /// `[optional argument]` #[inline(always)] - pub fn first_slot_of_ncn_epoch(&mut self, first_slot_of_ncn_epoch: u64) -> &mut Self { - self.instruction.first_slot_of_ncn_epoch = Some(first_slot_of_ncn_epoch); + pub fn epoch(&mut self, epoch: u64) -> &mut Self { + self.instruction.epoch = Some(epoch); self } /// Add an additional account to the instruction. @@ -574,7 +572,7 @@ impl<'a, 'b> InitializeEpochSnapshotCpiBuilder<'a, 'b> { signers_seeds: &[&[&[u8]]], ) -> solana_program::entrypoint::ProgramResult { let args = InitializeEpochSnapshotInstructionArgs { - first_slot_of_ncn_epoch: self.instruction.first_slot_of_ncn_epoch.clone(), + epoch: self.instruction.epoch.clone().expect("epoch is not set"), }; let instruction = InitializeEpochSnapshotCpi { __program: self.instruction.__program, @@ -635,7 +633,7 @@ struct InitializeEpochSnapshotCpiBuilderInstruction<'a, 'b> { payer: Option<&'b solana_program::account_info::AccountInfo<'a>>, restaking_program: Option<&'b solana_program::account_info::AccountInfo<'a>>, system_program: Option<&'b solana_program::account_info::AccountInfo<'a>>, - first_slot_of_ncn_epoch: Option, + epoch: Option, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<( &'b solana_program::account_info::AccountInfo<'a>, diff --git a/clients/rust/jito_tip_router/src/generated/instructions/initialize_ncn_reward_router.rs b/clients/rust/jito_tip_router/src/generated/instructions/initialize_ncn_reward_router.rs index 8ba880f..b19738a 100644 --- a/clients/rust/jito_tip_router/src/generated/instructions/initialize_ncn_reward_router.rs +++ b/clients/rust/jito_tip_router/src/generated/instructions/initialize_ncn_reward_router.rs @@ -99,7 +99,7 @@ impl Default for InitializeNcnRewardRouterInstructionData { #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct InitializeNcnRewardRouterInstructionArgs { pub ncn_fee_group: u8, - pub first_slot_of_ncn_epoch: Option, + pub epoch: u64, } /// Instruction builder for `InitializeNcnRewardRouter`. @@ -123,7 +123,7 @@ pub struct InitializeNcnRewardRouterBuilder { restaking_program: Option, system_program: Option, ncn_fee_group: Option, - first_slot_of_ncn_epoch: Option, + epoch: Option, __remaining_accounts: Vec, } @@ -181,10 +181,9 @@ impl InitializeNcnRewardRouterBuilder { self.ncn_fee_group = Some(ncn_fee_group); self } - /// `[optional argument]` #[inline(always)] - pub fn first_slot_of_ncn_epoch(&mut self, first_slot_of_ncn_epoch: u64) -> &mut Self { - self.first_slot_of_ncn_epoch = Some(first_slot_of_ncn_epoch); + pub fn epoch(&mut self, epoch: u64) -> &mut Self { + self.epoch = Some(epoch); self } /// Add an additional account to the instruction. @@ -227,7 +226,7 @@ impl InitializeNcnRewardRouterBuilder { .ncn_fee_group .clone() .expect("ncn_fee_group is not set"), - first_slot_of_ncn_epoch: self.first_slot_of_ncn_epoch.clone(), + epoch: self.epoch.clone().expect("epoch is not set"), }; accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) @@ -420,7 +419,7 @@ impl<'a, 'b> InitializeNcnRewardRouterCpiBuilder<'a, 'b> { restaking_program: None, system_program: None, ncn_fee_group: None, - first_slot_of_ncn_epoch: None, + epoch: None, __remaining_accounts: Vec::new(), }); Self { instruction } @@ -480,10 +479,9 @@ impl<'a, 'b> InitializeNcnRewardRouterCpiBuilder<'a, 'b> { self.instruction.ncn_fee_group = Some(ncn_fee_group); self } - /// `[optional argument]` #[inline(always)] - pub fn first_slot_of_ncn_epoch(&mut self, first_slot_of_ncn_epoch: u64) -> &mut Self { - self.instruction.first_slot_of_ncn_epoch = Some(first_slot_of_ncn_epoch); + pub fn epoch(&mut self, epoch: u64) -> &mut Self { + self.instruction.epoch = Some(epoch); self } /// Add an additional account to the instruction. @@ -533,7 +531,7 @@ impl<'a, 'b> InitializeNcnRewardRouterCpiBuilder<'a, 'b> { .ncn_fee_group .clone() .expect("ncn_fee_group is not set"), - first_slot_of_ncn_epoch: self.instruction.first_slot_of_ncn_epoch.clone(), + epoch: self.instruction.epoch.clone().expect("epoch is not set"), }; let instruction = InitializeNcnRewardRouterCpi { __program: self.instruction.__program, @@ -583,7 +581,7 @@ struct InitializeNcnRewardRouterCpiBuilderInstruction<'a, 'b> { restaking_program: Option<&'b solana_program::account_info::AccountInfo<'a>>, system_program: Option<&'b solana_program::account_info::AccountInfo<'a>>, ncn_fee_group: Option, - first_slot_of_ncn_epoch: Option, + epoch: Option, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<( &'b solana_program::account_info::AccountInfo<'a>, diff --git a/clients/rust/jito_tip_router/src/generated/instructions/initialize_operator_snapshot.rs b/clients/rust/jito_tip_router/src/generated/instructions/initialize_operator_snapshot.rs index a8218ee..e3340c9 100644 --- a/clients/rust/jito_tip_router/src/generated/instructions/initialize_operator_snapshot.rs +++ b/clients/rust/jito_tip_router/src/generated/instructions/initialize_operator_snapshot.rs @@ -116,7 +116,7 @@ impl Default for InitializeOperatorSnapshotInstructionData { #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct InitializeOperatorSnapshotInstructionArgs { - pub first_slot_of_ncn_epoch: Option, + pub epoch: u64, } /// Instruction builder for `InitializeOperatorSnapshot`. @@ -145,7 +145,7 @@ pub struct InitializeOperatorSnapshotBuilder { payer: Option, restaking_program: Option, system_program: Option, - first_slot_of_ncn_epoch: Option, + epoch: Option, __remaining_accounts: Vec, } @@ -216,10 +216,9 @@ impl InitializeOperatorSnapshotBuilder { self.system_program = Some(system_program); self } - /// `[optional argument]` #[inline(always)] - pub fn first_slot_of_ncn_epoch(&mut self, first_slot_of_ncn_epoch: u64) -> &mut Self { - self.first_slot_of_ncn_epoch = Some(first_slot_of_ncn_epoch); + pub fn epoch(&mut self, epoch: u64) -> &mut Self { + self.epoch = Some(epoch); self } /// Add an additional account to the instruction. @@ -263,7 +262,7 @@ impl InitializeOperatorSnapshotBuilder { .unwrap_or(solana_program::pubkey!("11111111111111111111111111111111")), }; let args = InitializeOperatorSnapshotInstructionArgs { - first_slot_of_ncn_epoch: self.first_slot_of_ncn_epoch.clone(), + epoch: self.epoch.clone().expect("epoch is not set"), }; accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) @@ -491,7 +490,7 @@ impl<'a, 'b> InitializeOperatorSnapshotCpiBuilder<'a, 'b> { payer: None, restaking_program: None, system_program: None, - first_slot_of_ncn_epoch: None, + epoch: None, __remaining_accounts: Vec::new(), }); Self { instruction } @@ -570,10 +569,9 @@ impl<'a, 'b> InitializeOperatorSnapshotCpiBuilder<'a, 'b> { self.instruction.system_program = Some(system_program); self } - /// `[optional argument]` #[inline(always)] - pub fn first_slot_of_ncn_epoch(&mut self, first_slot_of_ncn_epoch: u64) -> &mut Self { - self.instruction.first_slot_of_ncn_epoch = Some(first_slot_of_ncn_epoch); + pub fn epoch(&mut self, epoch: u64) -> &mut Self { + self.instruction.epoch = Some(epoch); self } /// Add an additional account to the instruction. @@ -618,7 +616,7 @@ impl<'a, 'b> InitializeOperatorSnapshotCpiBuilder<'a, 'b> { signers_seeds: &[&[&[u8]]], ) -> solana_program::entrypoint::ProgramResult { let args = InitializeOperatorSnapshotInstructionArgs { - first_slot_of_ncn_epoch: self.instruction.first_slot_of_ncn_epoch.clone(), + epoch: self.instruction.epoch.clone().expect("epoch is not set"), }; let instruction = InitializeOperatorSnapshotCpi { __program: self.instruction.__program, @@ -682,7 +680,7 @@ struct InitializeOperatorSnapshotCpiBuilderInstruction<'a, 'b> { payer: Option<&'b solana_program::account_info::AccountInfo<'a>>, restaking_program: Option<&'b solana_program::account_info::AccountInfo<'a>>, system_program: Option<&'b solana_program::account_info::AccountInfo<'a>>, - first_slot_of_ncn_epoch: Option, + epoch: Option, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<( &'b solana_program::account_info::AccountInfo<'a>, diff --git a/clients/rust/jito_tip_router/src/generated/instructions/initialize_weight_table.rs b/clients/rust/jito_tip_router/src/generated/instructions/initialize_weight_table.rs index b6bb6f5..32f48a6 100644 --- a/clients/rust/jito_tip_router/src/generated/instructions/initialize_weight_table.rs +++ b/clients/rust/jito_tip_router/src/generated/instructions/initialize_weight_table.rs @@ -98,7 +98,7 @@ impl Default for InitializeWeightTableInstructionData { #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct InitializeWeightTableInstructionArgs { - pub first_slot_of_ncn_epoch: Option, + pub epoch: u64, } /// Instruction builder for `InitializeWeightTable`. @@ -121,7 +121,7 @@ pub struct InitializeWeightTableBuilder { payer: Option, restaking_program: Option, system_program: Option, - first_slot_of_ncn_epoch: Option, + epoch: Option, __remaining_accounts: Vec, } @@ -171,10 +171,9 @@ impl InitializeWeightTableBuilder { self.system_program = Some(system_program); self } - /// `[optional argument]` #[inline(always)] - pub fn first_slot_of_ncn_epoch(&mut self, first_slot_of_ncn_epoch: u64) -> &mut Self { - self.first_slot_of_ncn_epoch = Some(first_slot_of_ncn_epoch); + pub fn epoch(&mut self, epoch: u64) -> &mut Self { + self.epoch = Some(epoch); self } /// Add an additional account to the instruction. @@ -211,7 +210,7 @@ impl InitializeWeightTableBuilder { .unwrap_or(solana_program::pubkey!("11111111111111111111111111111111")), }; let args = InitializeWeightTableInstructionArgs { - first_slot_of_ncn_epoch: self.first_slot_of_ncn_epoch.clone(), + epoch: self.epoch.clone().expect("epoch is not set"), }; accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) @@ -403,7 +402,7 @@ impl<'a, 'b> InitializeWeightTableCpiBuilder<'a, 'b> { payer: None, restaking_program: None, system_program: None, - first_slot_of_ncn_epoch: None, + epoch: None, __remaining_accounts: Vec::new(), }); Self { instruction } @@ -458,10 +457,9 @@ impl<'a, 'b> InitializeWeightTableCpiBuilder<'a, 'b> { self.instruction.system_program = Some(system_program); self } - /// `[optional argument]` #[inline(always)] - pub fn first_slot_of_ncn_epoch(&mut self, first_slot_of_ncn_epoch: u64) -> &mut Self { - self.instruction.first_slot_of_ncn_epoch = Some(first_slot_of_ncn_epoch); + pub fn epoch(&mut self, epoch: u64) -> &mut Self { + self.instruction.epoch = Some(epoch); self } /// Add an additional account to the instruction. @@ -506,7 +504,7 @@ impl<'a, 'b> InitializeWeightTableCpiBuilder<'a, 'b> { signers_seeds: &[&[&[u8]]], ) -> solana_program::entrypoint::ProgramResult { let args = InitializeWeightTableInstructionArgs { - first_slot_of_ncn_epoch: self.instruction.first_slot_of_ncn_epoch.clone(), + epoch: self.instruction.epoch.clone().expect("epoch is not set"), }; let instruction = InitializeWeightTableCpi { __program: self.instruction.__program, @@ -558,7 +556,7 @@ struct InitializeWeightTableCpiBuilderInstruction<'a, 'b> { payer: Option<&'b solana_program::account_info::AccountInfo<'a>>, restaking_program: Option<&'b solana_program::account_info::AccountInfo<'a>>, system_program: Option<&'b solana_program::account_info::AccountInfo<'a>>, - first_slot_of_ncn_epoch: Option, + epoch: Option, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<( &'b solana_program::account_info::AccountInfo<'a>, diff --git a/clients/rust/jito_tip_router/src/generated/instructions/mod.rs b/clients/rust/jito_tip_router/src/generated/instructions/mod.rs index 43ace98..a7e9a92 100644 --- a/clients/rust/jito_tip_router/src/generated/instructions/mod.rs +++ b/clients/rust/jito_tip_router/src/generated/instructions/mod.rs @@ -18,6 +18,10 @@ pub(crate) mod r#initialize_ncn_reward_router; pub(crate) mod r#initialize_operator_snapshot; pub(crate) mod r#initialize_tracked_mints; pub(crate) mod r#initialize_weight_table; +pub(crate) mod r#realloc_ballot_box; +pub(crate) mod r#realloc_base_reward_router; +pub(crate) mod r#realloc_operator_snapshot; +pub(crate) mod r#realloc_weight_table; pub(crate) mod r#register_mint; pub(crate) mod r#route_base_rewards; pub(crate) mod r#route_ncn_rewards; @@ -35,7 +39,8 @@ pub use self::{ r#initialize_base_reward_router::*, r#initialize_epoch_snapshot::*, r#initialize_n_c_n_config::*, r#initialize_ncn_reward_router::*, r#initialize_operator_snapshot::*, r#initialize_tracked_mints::*, r#initialize_weight_table::*, - r#register_mint::*, r#route_base_rewards::*, r#route_ncn_rewards::*, r#set_config_fees::*, - r#set_merkle_root::*, r#set_new_admin::*, r#set_tie_breaker::*, + r#realloc_ballot_box::*, r#realloc_base_reward_router::*, r#realloc_operator_snapshot::*, + r#realloc_weight_table::*, r#register_mint::*, r#route_base_rewards::*, r#route_ncn_rewards::*, + r#set_config_fees::*, r#set_merkle_root::*, r#set_new_admin::*, r#set_tie_breaker::*, r#set_tracked_mint_ncn_fee_group::*, r#snapshot_vault_operator_delegation::*, }; diff --git a/clients/rust/jito_tip_router/src/generated/instructions/realloc_ballot_box.rs b/clients/rust/jito_tip_router/src/generated/instructions/realloc_ballot_box.rs new file mode 100644 index 0000000..89280b8 --- /dev/null +++ b/clients/rust/jito_tip_router/src/generated/instructions/realloc_ballot_box.rs @@ -0,0 +1,468 @@ +//! This code was AUTOGENERATED using the kinobi library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun kinobi to update it. +//! +//! + +use borsh::{BorshDeserialize, BorshSerialize}; + +/// Accounts. +pub struct ReallocBallotBox { + pub ncn_config: solana_program::pubkey::Pubkey, + + pub ballot_box: solana_program::pubkey::Pubkey, + + pub ncn: solana_program::pubkey::Pubkey, + + pub payer: solana_program::pubkey::Pubkey, + + pub system_program: solana_program::pubkey::Pubkey, +} + +impl ReallocBallotBox { + pub fn instruction( + &self, + args: ReallocBallotBoxInstructionArgs, + ) -> solana_program::instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: ReallocBallotBoxInstructionArgs, + remaining_accounts: &[solana_program::instruction::AccountMeta], + ) -> solana_program::instruction::Instruction { + let mut accounts = Vec::with_capacity(5 + remaining_accounts.len()); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.ncn_config, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + self.ballot_box, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.ncn, false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + self.payer, true, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.system_program, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let mut data = ReallocBallotBoxInstructionData::new().try_to_vec().unwrap(); + let mut args = args.try_to_vec().unwrap(); + data.append(&mut args); + + solana_program::instruction::Instruction { + program_id: crate::JITO_TIP_ROUTER_ID, + accounts, + data, + } + } +} + +#[derive(BorshDeserialize, BorshSerialize)] +pub struct ReallocBallotBoxInstructionData { + discriminator: u8, +} + +impl ReallocBallotBoxInstructionData { + pub fn new() -> Self { + Self { discriminator: 23 } + } +} + +impl Default for ReallocBallotBoxInstructionData { + fn default() -> Self { + Self::new() + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct ReallocBallotBoxInstructionArgs { + pub epoch: u64, +} + +/// Instruction builder for `ReallocBallotBox`. +/// +/// ### Accounts: +/// +/// 0. `[]` ncn_config +/// 1. `[writable]` ballot_box +/// 2. `[]` ncn +/// 3. `[writable, signer]` payer +/// 4. `[optional]` system_program (default to `11111111111111111111111111111111`) +#[derive(Clone, Debug, Default)] +pub struct ReallocBallotBoxBuilder { + ncn_config: Option, + ballot_box: Option, + ncn: Option, + payer: Option, + system_program: Option, + epoch: Option, + __remaining_accounts: Vec, +} + +impl ReallocBallotBoxBuilder { + pub fn new() -> Self { + Self::default() + } + #[inline(always)] + pub fn ncn_config(&mut self, ncn_config: solana_program::pubkey::Pubkey) -> &mut Self { + self.ncn_config = Some(ncn_config); + self + } + #[inline(always)] + pub fn ballot_box(&mut self, ballot_box: solana_program::pubkey::Pubkey) -> &mut Self { + self.ballot_box = Some(ballot_box); + self + } + #[inline(always)] + pub fn ncn(&mut self, ncn: solana_program::pubkey::Pubkey) -> &mut Self { + self.ncn = Some(ncn); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: solana_program::pubkey::Pubkey) -> &mut Self { + self.payer = Some(payer); + self + } + /// `[optional account, default to '11111111111111111111111111111111']` + #[inline(always)] + pub fn system_program(&mut self, system_program: solana_program::pubkey::Pubkey) -> &mut Self { + self.system_program = Some(system_program); + self + } + #[inline(always)] + pub fn epoch(&mut self, epoch: u64) -> &mut Self { + self.epoch = Some(epoch); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: solana_program::instruction::AccountMeta, + ) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_program::instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_program::instruction::Instruction { + let accounts = ReallocBallotBox { + ncn_config: self.ncn_config.expect("ncn_config is not set"), + ballot_box: self.ballot_box.expect("ballot_box is not set"), + ncn: self.ncn.expect("ncn is not set"), + payer: self.payer.expect("payer is not set"), + system_program: self + .system_program + .unwrap_or(solana_program::pubkey!("11111111111111111111111111111111")), + }; + let args = ReallocBallotBoxInstructionArgs { + epoch: self.epoch.clone().expect("epoch is not set"), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `realloc_ballot_box` CPI accounts. +pub struct ReallocBallotBoxCpiAccounts<'a, 'b> { + pub ncn_config: &'b solana_program::account_info::AccountInfo<'a>, + + pub ballot_box: &'b solana_program::account_info::AccountInfo<'a>, + + pub ncn: &'b solana_program::account_info::AccountInfo<'a>, + + pub payer: &'b solana_program::account_info::AccountInfo<'a>, + + pub system_program: &'b solana_program::account_info::AccountInfo<'a>, +} + +/// `realloc_ballot_box` CPI instruction. +pub struct ReallocBallotBoxCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_program::account_info::AccountInfo<'a>, + + pub ncn_config: &'b solana_program::account_info::AccountInfo<'a>, + + pub ballot_box: &'b solana_program::account_info::AccountInfo<'a>, + + pub ncn: &'b solana_program::account_info::AccountInfo<'a>, + + pub payer: &'b solana_program::account_info::AccountInfo<'a>, + + pub system_program: &'b solana_program::account_info::AccountInfo<'a>, + /// The arguments for the instruction. + pub __args: ReallocBallotBoxInstructionArgs, +} + +impl<'a, 'b> ReallocBallotBoxCpi<'a, 'b> { + pub fn new( + program: &'b solana_program::account_info::AccountInfo<'a>, + accounts: ReallocBallotBoxCpiAccounts<'a, 'b>, + args: ReallocBallotBoxInstructionArgs, + ) -> Self { + Self { + __program: program, + ncn_config: accounts.ncn_config, + ballot_box: accounts.ballot_box, + ncn: accounts.ncn, + payer: accounts.payer, + system_program: accounts.system_program, + __args: args, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )], + ) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed( + &self, + signers_seeds: &[&[&[u8]]], + ) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )], + ) -> solana_program::entrypoint::ProgramResult { + let mut accounts = Vec::with_capacity(5 + remaining_accounts.len()); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.ncn_config.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + *self.ballot_box.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.ncn.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + *self.payer.key, + true, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.system_program.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_program::instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let mut data = ReallocBallotBoxInstructionData::new().try_to_vec().unwrap(); + let mut args = self.__args.try_to_vec().unwrap(); + data.append(&mut args); + + let instruction = solana_program::instruction::Instruction { + program_id: crate::JITO_TIP_ROUTER_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(5 + 1 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.ncn_config.clone()); + account_infos.push(self.ballot_box.clone()); + account_infos.push(self.ncn.clone()); + account_infos.push(self.payer.clone()); + account_infos.push(self.system_program.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_program::program::invoke(&instruction, &account_infos) + } else { + solana_program::program::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `ReallocBallotBox` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[]` ncn_config +/// 1. `[writable]` ballot_box +/// 2. `[]` ncn +/// 3. `[writable, signer]` payer +/// 4. `[]` system_program +#[derive(Clone, Debug)] +pub struct ReallocBallotBoxCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> ReallocBallotBoxCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_program::account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(ReallocBallotBoxCpiBuilderInstruction { + __program: program, + ncn_config: None, + ballot_box: None, + ncn: None, + payer: None, + system_program: None, + epoch: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + #[inline(always)] + pub fn ncn_config( + &mut self, + ncn_config: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.ncn_config = Some(ncn_config); + self + } + #[inline(always)] + pub fn ballot_box( + &mut self, + ballot_box: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.ballot_box = Some(ballot_box); + self + } + #[inline(always)] + pub fn ncn(&mut self, ncn: &'b solana_program::account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.ncn = Some(ncn); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: &'b solana_program::account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.payer = Some(payer); + self + } + #[inline(always)] + pub fn system_program( + &mut self, + system_program: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.system_program = Some(system_program); + self + } + #[inline(always)] + pub fn epoch(&mut self, epoch: u64) -> &mut Self { + self.instruction.epoch = Some(epoch); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_program::account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed( + &self, + signers_seeds: &[&[&[u8]]], + ) -> solana_program::entrypoint::ProgramResult { + let args = ReallocBallotBoxInstructionArgs { + epoch: self.instruction.epoch.clone().expect("epoch is not set"), + }; + let instruction = ReallocBallotBoxCpi { + __program: self.instruction.__program, + + ncn_config: self.instruction.ncn_config.expect("ncn_config is not set"), + + ballot_box: self.instruction.ballot_box.expect("ballot_box is not set"), + + ncn: self.instruction.ncn.expect("ncn is not set"), + + payer: self.instruction.payer.expect("payer is not set"), + + system_program: self + .instruction + .system_program + .expect("system_program is not set"), + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct ReallocBallotBoxCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_program::account_info::AccountInfo<'a>, + ncn_config: Option<&'b solana_program::account_info::AccountInfo<'a>>, + ballot_box: Option<&'b solana_program::account_info::AccountInfo<'a>>, + ncn: Option<&'b solana_program::account_info::AccountInfo<'a>>, + payer: Option<&'b solana_program::account_info::AccountInfo<'a>>, + system_program: Option<&'b solana_program::account_info::AccountInfo<'a>>, + epoch: Option, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )>, +} diff --git a/clients/rust/jito_tip_router/src/generated/instructions/realloc_base_reward_router.rs b/clients/rust/jito_tip_router/src/generated/instructions/realloc_base_reward_router.rs new file mode 100644 index 0000000..648359c --- /dev/null +++ b/clients/rust/jito_tip_router/src/generated/instructions/realloc_base_reward_router.rs @@ -0,0 +1,480 @@ +//! This code was AUTOGENERATED using the kinobi library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun kinobi to update it. +//! +//! + +use borsh::{BorshDeserialize, BorshSerialize}; + +/// Accounts. +pub struct ReallocBaseRewardRouter { + pub ncn_config: solana_program::pubkey::Pubkey, + + pub base_reward_router: solana_program::pubkey::Pubkey, + + pub ncn: solana_program::pubkey::Pubkey, + + pub payer: solana_program::pubkey::Pubkey, + + pub system_program: solana_program::pubkey::Pubkey, +} + +impl ReallocBaseRewardRouter { + pub fn instruction( + &self, + args: ReallocBaseRewardRouterInstructionArgs, + ) -> solana_program::instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: ReallocBaseRewardRouterInstructionArgs, + remaining_accounts: &[solana_program::instruction::AccountMeta], + ) -> solana_program::instruction::Instruction { + let mut accounts = Vec::with_capacity(5 + remaining_accounts.len()); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.ncn_config, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + self.base_reward_router, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.ncn, false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + self.payer, true, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.system_program, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let mut data = ReallocBaseRewardRouterInstructionData::new() + .try_to_vec() + .unwrap(); + let mut args = args.try_to_vec().unwrap(); + data.append(&mut args); + + solana_program::instruction::Instruction { + program_id: crate::JITO_TIP_ROUTER_ID, + accounts, + data, + } + } +} + +#[derive(BorshDeserialize, BorshSerialize)] +pub struct ReallocBaseRewardRouterInstructionData { + discriminator: u8, +} + +impl ReallocBaseRewardRouterInstructionData { + pub fn new() -> Self { + Self { discriminator: 25 } + } +} + +impl Default for ReallocBaseRewardRouterInstructionData { + fn default() -> Self { + Self::new() + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct ReallocBaseRewardRouterInstructionArgs { + pub epoch: u64, +} + +/// Instruction builder for `ReallocBaseRewardRouter`. +/// +/// ### Accounts: +/// +/// 0. `[]` ncn_config +/// 1. `[writable]` base_reward_router +/// 2. `[]` ncn +/// 3. `[writable, signer]` payer +/// 4. `[optional]` system_program (default to `11111111111111111111111111111111`) +#[derive(Clone, Debug, Default)] +pub struct ReallocBaseRewardRouterBuilder { + ncn_config: Option, + base_reward_router: Option, + ncn: Option, + payer: Option, + system_program: Option, + epoch: Option, + __remaining_accounts: Vec, +} + +impl ReallocBaseRewardRouterBuilder { + pub fn new() -> Self { + Self::default() + } + #[inline(always)] + pub fn ncn_config(&mut self, ncn_config: solana_program::pubkey::Pubkey) -> &mut Self { + self.ncn_config = Some(ncn_config); + self + } + #[inline(always)] + pub fn base_reward_router( + &mut self, + base_reward_router: solana_program::pubkey::Pubkey, + ) -> &mut Self { + self.base_reward_router = Some(base_reward_router); + self + } + #[inline(always)] + pub fn ncn(&mut self, ncn: solana_program::pubkey::Pubkey) -> &mut Self { + self.ncn = Some(ncn); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: solana_program::pubkey::Pubkey) -> &mut Self { + self.payer = Some(payer); + self + } + /// `[optional account, default to '11111111111111111111111111111111']` + #[inline(always)] + pub fn system_program(&mut self, system_program: solana_program::pubkey::Pubkey) -> &mut Self { + self.system_program = Some(system_program); + self + } + #[inline(always)] + pub fn epoch(&mut self, epoch: u64) -> &mut Self { + self.epoch = Some(epoch); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: solana_program::instruction::AccountMeta, + ) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_program::instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_program::instruction::Instruction { + let accounts = ReallocBaseRewardRouter { + ncn_config: self.ncn_config.expect("ncn_config is not set"), + base_reward_router: self + .base_reward_router + .expect("base_reward_router is not set"), + ncn: self.ncn.expect("ncn is not set"), + payer: self.payer.expect("payer is not set"), + system_program: self + .system_program + .unwrap_or(solana_program::pubkey!("11111111111111111111111111111111")), + }; + let args = ReallocBaseRewardRouterInstructionArgs { + epoch: self.epoch.clone().expect("epoch is not set"), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `realloc_base_reward_router` CPI accounts. +pub struct ReallocBaseRewardRouterCpiAccounts<'a, 'b> { + pub ncn_config: &'b solana_program::account_info::AccountInfo<'a>, + + pub base_reward_router: &'b solana_program::account_info::AccountInfo<'a>, + + pub ncn: &'b solana_program::account_info::AccountInfo<'a>, + + pub payer: &'b solana_program::account_info::AccountInfo<'a>, + + pub system_program: &'b solana_program::account_info::AccountInfo<'a>, +} + +/// `realloc_base_reward_router` CPI instruction. +pub struct ReallocBaseRewardRouterCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_program::account_info::AccountInfo<'a>, + + pub ncn_config: &'b solana_program::account_info::AccountInfo<'a>, + + pub base_reward_router: &'b solana_program::account_info::AccountInfo<'a>, + + pub ncn: &'b solana_program::account_info::AccountInfo<'a>, + + pub payer: &'b solana_program::account_info::AccountInfo<'a>, + + pub system_program: &'b solana_program::account_info::AccountInfo<'a>, + /// The arguments for the instruction. + pub __args: ReallocBaseRewardRouterInstructionArgs, +} + +impl<'a, 'b> ReallocBaseRewardRouterCpi<'a, 'b> { + pub fn new( + program: &'b solana_program::account_info::AccountInfo<'a>, + accounts: ReallocBaseRewardRouterCpiAccounts<'a, 'b>, + args: ReallocBaseRewardRouterInstructionArgs, + ) -> Self { + Self { + __program: program, + ncn_config: accounts.ncn_config, + base_reward_router: accounts.base_reward_router, + ncn: accounts.ncn, + payer: accounts.payer, + system_program: accounts.system_program, + __args: args, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )], + ) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed( + &self, + signers_seeds: &[&[&[u8]]], + ) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )], + ) -> solana_program::entrypoint::ProgramResult { + let mut accounts = Vec::with_capacity(5 + remaining_accounts.len()); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.ncn_config.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + *self.base_reward_router.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.ncn.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + *self.payer.key, + true, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.system_program.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_program::instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let mut data = ReallocBaseRewardRouterInstructionData::new() + .try_to_vec() + .unwrap(); + let mut args = self.__args.try_to_vec().unwrap(); + data.append(&mut args); + + let instruction = solana_program::instruction::Instruction { + program_id: crate::JITO_TIP_ROUTER_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(5 + 1 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.ncn_config.clone()); + account_infos.push(self.base_reward_router.clone()); + account_infos.push(self.ncn.clone()); + account_infos.push(self.payer.clone()); + account_infos.push(self.system_program.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_program::program::invoke(&instruction, &account_infos) + } else { + solana_program::program::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `ReallocBaseRewardRouter` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[]` ncn_config +/// 1. `[writable]` base_reward_router +/// 2. `[]` ncn +/// 3. `[writable, signer]` payer +/// 4. `[]` system_program +#[derive(Clone, Debug)] +pub struct ReallocBaseRewardRouterCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> ReallocBaseRewardRouterCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_program::account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(ReallocBaseRewardRouterCpiBuilderInstruction { + __program: program, + ncn_config: None, + base_reward_router: None, + ncn: None, + payer: None, + system_program: None, + epoch: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + #[inline(always)] + pub fn ncn_config( + &mut self, + ncn_config: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.ncn_config = Some(ncn_config); + self + } + #[inline(always)] + pub fn base_reward_router( + &mut self, + base_reward_router: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.base_reward_router = Some(base_reward_router); + self + } + #[inline(always)] + pub fn ncn(&mut self, ncn: &'b solana_program::account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.ncn = Some(ncn); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: &'b solana_program::account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.payer = Some(payer); + self + } + #[inline(always)] + pub fn system_program( + &mut self, + system_program: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.system_program = Some(system_program); + self + } + #[inline(always)] + pub fn epoch(&mut self, epoch: u64) -> &mut Self { + self.instruction.epoch = Some(epoch); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_program::account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed( + &self, + signers_seeds: &[&[&[u8]]], + ) -> solana_program::entrypoint::ProgramResult { + let args = ReallocBaseRewardRouterInstructionArgs { + epoch: self.instruction.epoch.clone().expect("epoch is not set"), + }; + let instruction = ReallocBaseRewardRouterCpi { + __program: self.instruction.__program, + + ncn_config: self.instruction.ncn_config.expect("ncn_config is not set"), + + base_reward_router: self + .instruction + .base_reward_router + .expect("base_reward_router is not set"), + + ncn: self.instruction.ncn.expect("ncn is not set"), + + payer: self.instruction.payer.expect("payer is not set"), + + system_program: self + .instruction + .system_program + .expect("system_program is not set"), + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct ReallocBaseRewardRouterCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_program::account_info::AccountInfo<'a>, + ncn_config: Option<&'b solana_program::account_info::AccountInfo<'a>>, + base_reward_router: Option<&'b solana_program::account_info::AccountInfo<'a>>, + ncn: Option<&'b solana_program::account_info::AccountInfo<'a>>, + payer: Option<&'b solana_program::account_info::AccountInfo<'a>>, + system_program: Option<&'b solana_program::account_info::AccountInfo<'a>>, + epoch: Option, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )>, +} diff --git a/clients/rust/jito_tip_router/src/generated/instructions/realloc_operator_snapshot.rs b/clients/rust/jito_tip_router/src/generated/instructions/realloc_operator_snapshot.rs new file mode 100644 index 0000000..719ef4b --- /dev/null +++ b/clients/rust/jito_tip_router/src/generated/instructions/realloc_operator_snapshot.rs @@ -0,0 +1,690 @@ +//! This code was AUTOGENERATED using the kinobi library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun kinobi to update it. +//! +//! + +use borsh::{BorshDeserialize, BorshSerialize}; + +/// Accounts. +pub struct ReallocOperatorSnapshot { + pub ncn_config: solana_program::pubkey::Pubkey, + + pub restaking_config: solana_program::pubkey::Pubkey, + + pub ncn: solana_program::pubkey::Pubkey, + + pub operator: solana_program::pubkey::Pubkey, + + pub ncn_operator_state: solana_program::pubkey::Pubkey, + + pub epoch_snapshot: solana_program::pubkey::Pubkey, + + pub operator_snapshot: solana_program::pubkey::Pubkey, + + pub payer: solana_program::pubkey::Pubkey, + + pub restaking_program: solana_program::pubkey::Pubkey, + + pub system_program: solana_program::pubkey::Pubkey, +} + +impl ReallocOperatorSnapshot { + pub fn instruction( + &self, + args: ReallocOperatorSnapshotInstructionArgs, + ) -> solana_program::instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: ReallocOperatorSnapshotInstructionArgs, + remaining_accounts: &[solana_program::instruction::AccountMeta], + ) -> solana_program::instruction::Instruction { + let mut accounts = Vec::with_capacity(10 + remaining_accounts.len()); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.ncn_config, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.restaking_config, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.ncn, false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.operator, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.ncn_operator_state, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + self.epoch_snapshot, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + self.operator_snapshot, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + self.payer, true, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.restaking_program, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.system_program, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let mut data = ReallocOperatorSnapshotInstructionData::new() + .try_to_vec() + .unwrap(); + let mut args = args.try_to_vec().unwrap(); + data.append(&mut args); + + solana_program::instruction::Instruction { + program_id: crate::JITO_TIP_ROUTER_ID, + accounts, + data, + } + } +} + +#[derive(BorshDeserialize, BorshSerialize)] +pub struct ReallocOperatorSnapshotInstructionData { + discriminator: u8, +} + +impl ReallocOperatorSnapshotInstructionData { + pub fn new() -> Self { + Self { discriminator: 24 } + } +} + +impl Default for ReallocOperatorSnapshotInstructionData { + fn default() -> Self { + Self::new() + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct ReallocOperatorSnapshotInstructionArgs { + pub epoch: u64, +} + +/// Instruction builder for `ReallocOperatorSnapshot`. +/// +/// ### Accounts: +/// +/// 0. `[]` ncn_config +/// 1. `[]` restaking_config +/// 2. `[]` ncn +/// 3. `[]` operator +/// 4. `[]` ncn_operator_state +/// 5. `[writable]` epoch_snapshot +/// 6. `[writable]` operator_snapshot +/// 7. `[writable, signer]` payer +/// 8. `[]` restaking_program +/// 9. `[optional]` system_program (default to `11111111111111111111111111111111`) +#[derive(Clone, Debug, Default)] +pub struct ReallocOperatorSnapshotBuilder { + ncn_config: Option, + restaking_config: Option, + ncn: Option, + operator: Option, + ncn_operator_state: Option, + epoch_snapshot: Option, + operator_snapshot: Option, + payer: Option, + restaking_program: Option, + system_program: Option, + epoch: Option, + __remaining_accounts: Vec, +} + +impl ReallocOperatorSnapshotBuilder { + pub fn new() -> Self { + Self::default() + } + #[inline(always)] + pub fn ncn_config(&mut self, ncn_config: solana_program::pubkey::Pubkey) -> &mut Self { + self.ncn_config = Some(ncn_config); + self + } + #[inline(always)] + pub fn restaking_config( + &mut self, + restaking_config: solana_program::pubkey::Pubkey, + ) -> &mut Self { + self.restaking_config = Some(restaking_config); + self + } + #[inline(always)] + pub fn ncn(&mut self, ncn: solana_program::pubkey::Pubkey) -> &mut Self { + self.ncn = Some(ncn); + self + } + #[inline(always)] + pub fn operator(&mut self, operator: solana_program::pubkey::Pubkey) -> &mut Self { + self.operator = Some(operator); + self + } + #[inline(always)] + pub fn ncn_operator_state( + &mut self, + ncn_operator_state: solana_program::pubkey::Pubkey, + ) -> &mut Self { + self.ncn_operator_state = Some(ncn_operator_state); + self + } + #[inline(always)] + pub fn epoch_snapshot(&mut self, epoch_snapshot: solana_program::pubkey::Pubkey) -> &mut Self { + self.epoch_snapshot = Some(epoch_snapshot); + self + } + #[inline(always)] + pub fn operator_snapshot( + &mut self, + operator_snapshot: solana_program::pubkey::Pubkey, + ) -> &mut Self { + self.operator_snapshot = Some(operator_snapshot); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: solana_program::pubkey::Pubkey) -> &mut Self { + self.payer = Some(payer); + self + } + #[inline(always)] + pub fn restaking_program( + &mut self, + restaking_program: solana_program::pubkey::Pubkey, + ) -> &mut Self { + self.restaking_program = Some(restaking_program); + self + } + /// `[optional account, default to '11111111111111111111111111111111']` + #[inline(always)] + pub fn system_program(&mut self, system_program: solana_program::pubkey::Pubkey) -> &mut Self { + self.system_program = Some(system_program); + self + } + #[inline(always)] + pub fn epoch(&mut self, epoch: u64) -> &mut Self { + self.epoch = Some(epoch); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: solana_program::instruction::AccountMeta, + ) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_program::instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_program::instruction::Instruction { + let accounts = ReallocOperatorSnapshot { + ncn_config: self.ncn_config.expect("ncn_config is not set"), + restaking_config: self.restaking_config.expect("restaking_config is not set"), + ncn: self.ncn.expect("ncn is not set"), + operator: self.operator.expect("operator is not set"), + ncn_operator_state: self + .ncn_operator_state + .expect("ncn_operator_state is not set"), + epoch_snapshot: self.epoch_snapshot.expect("epoch_snapshot is not set"), + operator_snapshot: self + .operator_snapshot + .expect("operator_snapshot is not set"), + payer: self.payer.expect("payer is not set"), + restaking_program: self + .restaking_program + .expect("restaking_program is not set"), + system_program: self + .system_program + .unwrap_or(solana_program::pubkey!("11111111111111111111111111111111")), + }; + let args = ReallocOperatorSnapshotInstructionArgs { + epoch: self.epoch.clone().expect("epoch is not set"), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `realloc_operator_snapshot` CPI accounts. +pub struct ReallocOperatorSnapshotCpiAccounts<'a, 'b> { + pub ncn_config: &'b solana_program::account_info::AccountInfo<'a>, + + pub restaking_config: &'b solana_program::account_info::AccountInfo<'a>, + + pub ncn: &'b solana_program::account_info::AccountInfo<'a>, + + pub operator: &'b solana_program::account_info::AccountInfo<'a>, + + pub ncn_operator_state: &'b solana_program::account_info::AccountInfo<'a>, + + pub epoch_snapshot: &'b solana_program::account_info::AccountInfo<'a>, + + pub operator_snapshot: &'b solana_program::account_info::AccountInfo<'a>, + + pub payer: &'b solana_program::account_info::AccountInfo<'a>, + + pub restaking_program: &'b solana_program::account_info::AccountInfo<'a>, + + pub system_program: &'b solana_program::account_info::AccountInfo<'a>, +} + +/// `realloc_operator_snapshot` CPI instruction. +pub struct ReallocOperatorSnapshotCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_program::account_info::AccountInfo<'a>, + + pub ncn_config: &'b solana_program::account_info::AccountInfo<'a>, + + pub restaking_config: &'b solana_program::account_info::AccountInfo<'a>, + + pub ncn: &'b solana_program::account_info::AccountInfo<'a>, + + pub operator: &'b solana_program::account_info::AccountInfo<'a>, + + pub ncn_operator_state: &'b solana_program::account_info::AccountInfo<'a>, + + pub epoch_snapshot: &'b solana_program::account_info::AccountInfo<'a>, + + pub operator_snapshot: &'b solana_program::account_info::AccountInfo<'a>, + + pub payer: &'b solana_program::account_info::AccountInfo<'a>, + + pub restaking_program: &'b solana_program::account_info::AccountInfo<'a>, + + pub system_program: &'b solana_program::account_info::AccountInfo<'a>, + /// The arguments for the instruction. + pub __args: ReallocOperatorSnapshotInstructionArgs, +} + +impl<'a, 'b> ReallocOperatorSnapshotCpi<'a, 'b> { + pub fn new( + program: &'b solana_program::account_info::AccountInfo<'a>, + accounts: ReallocOperatorSnapshotCpiAccounts<'a, 'b>, + args: ReallocOperatorSnapshotInstructionArgs, + ) -> Self { + Self { + __program: program, + ncn_config: accounts.ncn_config, + restaking_config: accounts.restaking_config, + ncn: accounts.ncn, + operator: accounts.operator, + ncn_operator_state: accounts.ncn_operator_state, + epoch_snapshot: accounts.epoch_snapshot, + operator_snapshot: accounts.operator_snapshot, + payer: accounts.payer, + restaking_program: accounts.restaking_program, + system_program: accounts.system_program, + __args: args, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )], + ) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed( + &self, + signers_seeds: &[&[&[u8]]], + ) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )], + ) -> solana_program::entrypoint::ProgramResult { + let mut accounts = Vec::with_capacity(10 + remaining_accounts.len()); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.ncn_config.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.restaking_config.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.ncn.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.operator.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.ncn_operator_state.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + *self.epoch_snapshot.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + *self.operator_snapshot.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + *self.payer.key, + true, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.restaking_program.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.system_program.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_program::instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let mut data = ReallocOperatorSnapshotInstructionData::new() + .try_to_vec() + .unwrap(); + let mut args = self.__args.try_to_vec().unwrap(); + data.append(&mut args); + + let instruction = solana_program::instruction::Instruction { + program_id: crate::JITO_TIP_ROUTER_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(10 + 1 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.ncn_config.clone()); + account_infos.push(self.restaking_config.clone()); + account_infos.push(self.ncn.clone()); + account_infos.push(self.operator.clone()); + account_infos.push(self.ncn_operator_state.clone()); + account_infos.push(self.epoch_snapshot.clone()); + account_infos.push(self.operator_snapshot.clone()); + account_infos.push(self.payer.clone()); + account_infos.push(self.restaking_program.clone()); + account_infos.push(self.system_program.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_program::program::invoke(&instruction, &account_infos) + } else { + solana_program::program::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `ReallocOperatorSnapshot` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[]` ncn_config +/// 1. `[]` restaking_config +/// 2. `[]` ncn +/// 3. `[]` operator +/// 4. `[]` ncn_operator_state +/// 5. `[writable]` epoch_snapshot +/// 6. `[writable]` operator_snapshot +/// 7. `[writable, signer]` payer +/// 8. `[]` restaking_program +/// 9. `[]` system_program +#[derive(Clone, Debug)] +pub struct ReallocOperatorSnapshotCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> ReallocOperatorSnapshotCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_program::account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(ReallocOperatorSnapshotCpiBuilderInstruction { + __program: program, + ncn_config: None, + restaking_config: None, + ncn: None, + operator: None, + ncn_operator_state: None, + epoch_snapshot: None, + operator_snapshot: None, + payer: None, + restaking_program: None, + system_program: None, + epoch: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + #[inline(always)] + pub fn ncn_config( + &mut self, + ncn_config: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.ncn_config = Some(ncn_config); + self + } + #[inline(always)] + pub fn restaking_config( + &mut self, + restaking_config: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.restaking_config = Some(restaking_config); + self + } + #[inline(always)] + pub fn ncn(&mut self, ncn: &'b solana_program::account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.ncn = Some(ncn); + self + } + #[inline(always)] + pub fn operator( + &mut self, + operator: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.operator = Some(operator); + self + } + #[inline(always)] + pub fn ncn_operator_state( + &mut self, + ncn_operator_state: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.ncn_operator_state = Some(ncn_operator_state); + self + } + #[inline(always)] + pub fn epoch_snapshot( + &mut self, + epoch_snapshot: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.epoch_snapshot = Some(epoch_snapshot); + self + } + #[inline(always)] + pub fn operator_snapshot( + &mut self, + operator_snapshot: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.operator_snapshot = Some(operator_snapshot); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: &'b solana_program::account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.payer = Some(payer); + self + } + #[inline(always)] + pub fn restaking_program( + &mut self, + restaking_program: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.restaking_program = Some(restaking_program); + self + } + #[inline(always)] + pub fn system_program( + &mut self, + system_program: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.system_program = Some(system_program); + self + } + #[inline(always)] + pub fn epoch(&mut self, epoch: u64) -> &mut Self { + self.instruction.epoch = Some(epoch); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_program::account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed( + &self, + signers_seeds: &[&[&[u8]]], + ) -> solana_program::entrypoint::ProgramResult { + let args = ReallocOperatorSnapshotInstructionArgs { + epoch: self.instruction.epoch.clone().expect("epoch is not set"), + }; + let instruction = ReallocOperatorSnapshotCpi { + __program: self.instruction.__program, + + ncn_config: self.instruction.ncn_config.expect("ncn_config is not set"), + + restaking_config: self + .instruction + .restaking_config + .expect("restaking_config is not set"), + + ncn: self.instruction.ncn.expect("ncn is not set"), + + operator: self.instruction.operator.expect("operator is not set"), + + ncn_operator_state: self + .instruction + .ncn_operator_state + .expect("ncn_operator_state is not set"), + + epoch_snapshot: self + .instruction + .epoch_snapshot + .expect("epoch_snapshot is not set"), + + operator_snapshot: self + .instruction + .operator_snapshot + .expect("operator_snapshot is not set"), + + payer: self.instruction.payer.expect("payer is not set"), + + restaking_program: self + .instruction + .restaking_program + .expect("restaking_program is not set"), + + system_program: self + .instruction + .system_program + .expect("system_program is not set"), + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct ReallocOperatorSnapshotCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_program::account_info::AccountInfo<'a>, + ncn_config: Option<&'b solana_program::account_info::AccountInfo<'a>>, + restaking_config: Option<&'b solana_program::account_info::AccountInfo<'a>>, + ncn: Option<&'b solana_program::account_info::AccountInfo<'a>>, + operator: Option<&'b solana_program::account_info::AccountInfo<'a>>, + ncn_operator_state: Option<&'b solana_program::account_info::AccountInfo<'a>>, + epoch_snapshot: Option<&'b solana_program::account_info::AccountInfo<'a>>, + operator_snapshot: Option<&'b solana_program::account_info::AccountInfo<'a>>, + payer: Option<&'b solana_program::account_info::AccountInfo<'a>>, + restaking_program: Option<&'b solana_program::account_info::AccountInfo<'a>>, + system_program: Option<&'b solana_program::account_info::AccountInfo<'a>>, + epoch: Option, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )>, +} diff --git a/clients/rust/jito_tip_router/src/generated/instructions/realloc_weight_table.rs b/clients/rust/jito_tip_router/src/generated/instructions/realloc_weight_table.rs new file mode 100644 index 0000000..6811988 --- /dev/null +++ b/clients/rust/jito_tip_router/src/generated/instructions/realloc_weight_table.rs @@ -0,0 +1,515 @@ +//! This code was AUTOGENERATED using the kinobi library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun kinobi to update it. +//! +//! + +use borsh::{BorshDeserialize, BorshSerialize}; + +/// Accounts. +pub struct ReallocWeightTable { + pub ncn_config: solana_program::pubkey::Pubkey, + + pub weight_table: solana_program::pubkey::Pubkey, + + pub ncn: solana_program::pubkey::Pubkey, + + pub tracked_mints: solana_program::pubkey::Pubkey, + + pub payer: solana_program::pubkey::Pubkey, + + pub system_program: solana_program::pubkey::Pubkey, +} + +impl ReallocWeightTable { + pub fn instruction( + &self, + args: ReallocWeightTableInstructionArgs, + ) -> solana_program::instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: ReallocWeightTableInstructionArgs, + remaining_accounts: &[solana_program::instruction::AccountMeta], + ) -> solana_program::instruction::Instruction { + let mut accounts = Vec::with_capacity(6 + remaining_accounts.len()); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.ncn_config, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + self.weight_table, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.ncn, false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.tracked_mints, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + self.payer, true, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.system_program, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let mut data = ReallocWeightTableInstructionData::new() + .try_to_vec() + .unwrap(); + let mut args = args.try_to_vec().unwrap(); + data.append(&mut args); + + solana_program::instruction::Instruction { + program_id: crate::JITO_TIP_ROUTER_ID, + accounts, + data, + } + } +} + +#[derive(BorshDeserialize, BorshSerialize)] +pub struct ReallocWeightTableInstructionData { + discriminator: u8, +} + +impl ReallocWeightTableInstructionData { + pub fn new() -> Self { + Self { discriminator: 26 } + } +} + +impl Default for ReallocWeightTableInstructionData { + fn default() -> Self { + Self::new() + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct ReallocWeightTableInstructionArgs { + pub epoch: u64, +} + +/// Instruction builder for `ReallocWeightTable`. +/// +/// ### Accounts: +/// +/// 0. `[]` ncn_config +/// 1. `[writable]` weight_table +/// 2. `[]` ncn +/// 3. `[]` tracked_mints +/// 4. `[writable, signer]` payer +/// 5. `[optional]` system_program (default to `11111111111111111111111111111111`) +#[derive(Clone, Debug, Default)] +pub struct ReallocWeightTableBuilder { + ncn_config: Option, + weight_table: Option, + ncn: Option, + tracked_mints: Option, + payer: Option, + system_program: Option, + epoch: Option, + __remaining_accounts: Vec, +} + +impl ReallocWeightTableBuilder { + pub fn new() -> Self { + Self::default() + } + #[inline(always)] + pub fn ncn_config(&mut self, ncn_config: solana_program::pubkey::Pubkey) -> &mut Self { + self.ncn_config = Some(ncn_config); + self + } + #[inline(always)] + pub fn weight_table(&mut self, weight_table: solana_program::pubkey::Pubkey) -> &mut Self { + self.weight_table = Some(weight_table); + self + } + #[inline(always)] + pub fn ncn(&mut self, ncn: solana_program::pubkey::Pubkey) -> &mut Self { + self.ncn = Some(ncn); + self + } + #[inline(always)] + pub fn tracked_mints(&mut self, tracked_mints: solana_program::pubkey::Pubkey) -> &mut Self { + self.tracked_mints = Some(tracked_mints); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: solana_program::pubkey::Pubkey) -> &mut Self { + self.payer = Some(payer); + self + } + /// `[optional account, default to '11111111111111111111111111111111']` + #[inline(always)] + pub fn system_program(&mut self, system_program: solana_program::pubkey::Pubkey) -> &mut Self { + self.system_program = Some(system_program); + self + } + #[inline(always)] + pub fn epoch(&mut self, epoch: u64) -> &mut Self { + self.epoch = Some(epoch); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: solana_program::instruction::AccountMeta, + ) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_program::instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_program::instruction::Instruction { + let accounts = ReallocWeightTable { + ncn_config: self.ncn_config.expect("ncn_config is not set"), + weight_table: self.weight_table.expect("weight_table is not set"), + ncn: self.ncn.expect("ncn is not set"), + tracked_mints: self.tracked_mints.expect("tracked_mints is not set"), + payer: self.payer.expect("payer is not set"), + system_program: self + .system_program + .unwrap_or(solana_program::pubkey!("11111111111111111111111111111111")), + }; + let args = ReallocWeightTableInstructionArgs { + epoch: self.epoch.clone().expect("epoch is not set"), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `realloc_weight_table` CPI accounts. +pub struct ReallocWeightTableCpiAccounts<'a, 'b> { + pub ncn_config: &'b solana_program::account_info::AccountInfo<'a>, + + pub weight_table: &'b solana_program::account_info::AccountInfo<'a>, + + pub ncn: &'b solana_program::account_info::AccountInfo<'a>, + + pub tracked_mints: &'b solana_program::account_info::AccountInfo<'a>, + + pub payer: &'b solana_program::account_info::AccountInfo<'a>, + + pub system_program: &'b solana_program::account_info::AccountInfo<'a>, +} + +/// `realloc_weight_table` CPI instruction. +pub struct ReallocWeightTableCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_program::account_info::AccountInfo<'a>, + + pub ncn_config: &'b solana_program::account_info::AccountInfo<'a>, + + pub weight_table: &'b solana_program::account_info::AccountInfo<'a>, + + pub ncn: &'b solana_program::account_info::AccountInfo<'a>, + + pub tracked_mints: &'b solana_program::account_info::AccountInfo<'a>, + + pub payer: &'b solana_program::account_info::AccountInfo<'a>, + + pub system_program: &'b solana_program::account_info::AccountInfo<'a>, + /// The arguments for the instruction. + pub __args: ReallocWeightTableInstructionArgs, +} + +impl<'a, 'b> ReallocWeightTableCpi<'a, 'b> { + pub fn new( + program: &'b solana_program::account_info::AccountInfo<'a>, + accounts: ReallocWeightTableCpiAccounts<'a, 'b>, + args: ReallocWeightTableInstructionArgs, + ) -> Self { + Self { + __program: program, + ncn_config: accounts.ncn_config, + weight_table: accounts.weight_table, + ncn: accounts.ncn, + tracked_mints: accounts.tracked_mints, + payer: accounts.payer, + system_program: accounts.system_program, + __args: args, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )], + ) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed( + &self, + signers_seeds: &[&[&[u8]]], + ) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )], + ) -> solana_program::entrypoint::ProgramResult { + let mut accounts = Vec::with_capacity(6 + remaining_accounts.len()); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.ncn_config.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + *self.weight_table.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.ncn.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.tracked_mints.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + *self.payer.key, + true, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.system_program.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_program::instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let mut data = ReallocWeightTableInstructionData::new() + .try_to_vec() + .unwrap(); + let mut args = self.__args.try_to_vec().unwrap(); + data.append(&mut args); + + let instruction = solana_program::instruction::Instruction { + program_id: crate::JITO_TIP_ROUTER_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(6 + 1 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.ncn_config.clone()); + account_infos.push(self.weight_table.clone()); + account_infos.push(self.ncn.clone()); + account_infos.push(self.tracked_mints.clone()); + account_infos.push(self.payer.clone()); + account_infos.push(self.system_program.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_program::program::invoke(&instruction, &account_infos) + } else { + solana_program::program::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `ReallocWeightTable` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[]` ncn_config +/// 1. `[writable]` weight_table +/// 2. `[]` ncn +/// 3. `[]` tracked_mints +/// 4. `[writable, signer]` payer +/// 5. `[]` system_program +#[derive(Clone, Debug)] +pub struct ReallocWeightTableCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> ReallocWeightTableCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_program::account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(ReallocWeightTableCpiBuilderInstruction { + __program: program, + ncn_config: None, + weight_table: None, + ncn: None, + tracked_mints: None, + payer: None, + system_program: None, + epoch: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + #[inline(always)] + pub fn ncn_config( + &mut self, + ncn_config: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.ncn_config = Some(ncn_config); + self + } + #[inline(always)] + pub fn weight_table( + &mut self, + weight_table: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.weight_table = Some(weight_table); + self + } + #[inline(always)] + pub fn ncn(&mut self, ncn: &'b solana_program::account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.ncn = Some(ncn); + self + } + #[inline(always)] + pub fn tracked_mints( + &mut self, + tracked_mints: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.tracked_mints = Some(tracked_mints); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: &'b solana_program::account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.payer = Some(payer); + self + } + #[inline(always)] + pub fn system_program( + &mut self, + system_program: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.system_program = Some(system_program); + self + } + #[inline(always)] + pub fn epoch(&mut self, epoch: u64) -> &mut Self { + self.instruction.epoch = Some(epoch); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_program::account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed( + &self, + signers_seeds: &[&[&[u8]]], + ) -> solana_program::entrypoint::ProgramResult { + let args = ReallocWeightTableInstructionArgs { + epoch: self.instruction.epoch.clone().expect("epoch is not set"), + }; + let instruction = ReallocWeightTableCpi { + __program: self.instruction.__program, + + ncn_config: self.instruction.ncn_config.expect("ncn_config is not set"), + + weight_table: self + .instruction + .weight_table + .expect("weight_table is not set"), + + ncn: self.instruction.ncn.expect("ncn is not set"), + + tracked_mints: self + .instruction + .tracked_mints + .expect("tracked_mints is not set"), + + payer: self.instruction.payer.expect("payer is not set"), + + system_program: self + .instruction + .system_program + .expect("system_program is not set"), + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct ReallocWeightTableCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_program::account_info::AccountInfo<'a>, + ncn_config: Option<&'b solana_program::account_info::AccountInfo<'a>>, + weight_table: Option<&'b solana_program::account_info::AccountInfo<'a>>, + ncn: Option<&'b solana_program::account_info::AccountInfo<'a>>, + tracked_mints: Option<&'b solana_program::account_info::AccountInfo<'a>>, + payer: Option<&'b solana_program::account_info::AccountInfo<'a>>, + system_program: Option<&'b solana_program::account_info::AccountInfo<'a>>, + epoch: Option, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )>, +} diff --git a/clients/rust/jito_tip_router/src/generated/instructions/route_base_rewards.rs b/clients/rust/jito_tip_router/src/generated/instructions/route_base_rewards.rs index 77e8e24..6360733 100644 --- a/clients/rust/jito_tip_router/src/generated/instructions/route_base_rewards.rs +++ b/clients/rust/jito_tip_router/src/generated/instructions/route_base_rewards.rs @@ -91,7 +91,7 @@ impl Default for RouteBaseRewardsInstructionData { #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct RouteBaseRewardsInstructionArgs { - pub first_slot_of_ncn_epoch: Option, + pub epoch: u64, } /// Instruction builder for `RouteBaseRewards`. @@ -112,7 +112,7 @@ pub struct RouteBaseRewardsBuilder { ballot_box: Option, base_reward_router: Option, restaking_program: Option, - first_slot_of_ncn_epoch: Option, + epoch: Option, __remaining_accounts: Vec, } @@ -159,10 +159,9 @@ impl RouteBaseRewardsBuilder { self.restaking_program = Some(restaking_program); self } - /// `[optional argument]` #[inline(always)] - pub fn first_slot_of_ncn_epoch(&mut self, first_slot_of_ncn_epoch: u64) -> &mut Self { - self.first_slot_of_ncn_epoch = Some(first_slot_of_ncn_epoch); + pub fn epoch(&mut self, epoch: u64) -> &mut Self { + self.epoch = Some(epoch); self } /// Add an additional account to the instruction. @@ -198,7 +197,7 @@ impl RouteBaseRewardsBuilder { .expect("restaking_program is not set"), }; let args = RouteBaseRewardsInstructionArgs { - first_slot_of_ncn_epoch: self.first_slot_of_ncn_epoch.clone(), + epoch: self.epoch.clone().expect("epoch is not set"), }; accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) @@ -376,7 +375,7 @@ impl<'a, 'b> RouteBaseRewardsCpiBuilder<'a, 'b> { ballot_box: None, base_reward_router: None, restaking_program: None, - first_slot_of_ncn_epoch: None, + epoch: None, __remaining_accounts: Vec::new(), }); Self { instruction } @@ -426,10 +425,9 @@ impl<'a, 'b> RouteBaseRewardsCpiBuilder<'a, 'b> { self.instruction.restaking_program = Some(restaking_program); self } - /// `[optional argument]` #[inline(always)] - pub fn first_slot_of_ncn_epoch(&mut self, first_slot_of_ncn_epoch: u64) -> &mut Self { - self.instruction.first_slot_of_ncn_epoch = Some(first_slot_of_ncn_epoch); + pub fn epoch(&mut self, epoch: u64) -> &mut Self { + self.instruction.epoch = Some(epoch); self } /// Add an additional account to the instruction. @@ -474,7 +472,7 @@ impl<'a, 'b> RouteBaseRewardsCpiBuilder<'a, 'b> { signers_seeds: &[&[&[u8]]], ) -> solana_program::entrypoint::ProgramResult { let args = RouteBaseRewardsInstructionArgs { - first_slot_of_ncn_epoch: self.instruction.first_slot_of_ncn_epoch.clone(), + epoch: self.instruction.epoch.clone().expect("epoch is not set"), }; let instruction = RouteBaseRewardsCpi { __program: self.instruction.__program, @@ -520,7 +518,7 @@ struct RouteBaseRewardsCpiBuilderInstruction<'a, 'b> { ballot_box: Option<&'b solana_program::account_info::AccountInfo<'a>>, base_reward_router: Option<&'b solana_program::account_info::AccountInfo<'a>>, restaking_program: Option<&'b solana_program::account_info::AccountInfo<'a>>, - first_slot_of_ncn_epoch: Option, + epoch: Option, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<( &'b solana_program::account_info::AccountInfo<'a>, diff --git a/clients/rust/jito_tip_router/src/generated/instructions/route_ncn_rewards.rs b/clients/rust/jito_tip_router/src/generated/instructions/route_ncn_rewards.rs index a7c892d..8cc2f06 100644 --- a/clients/rust/jito_tip_router/src/generated/instructions/route_ncn_rewards.rs +++ b/clients/rust/jito_tip_router/src/generated/instructions/route_ncn_rewards.rs @@ -92,7 +92,7 @@ impl Default for RouteNcnRewardsInstructionData { #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct RouteNcnRewardsInstructionArgs { pub ncn_fee_group: u8, - pub first_slot_of_ncn_epoch: Option, + pub epoch: u64, } /// Instruction builder for `RouteNcnRewards`. @@ -114,7 +114,7 @@ pub struct RouteNcnRewardsBuilder { ncn_reward_router: Option, restaking_program: Option, ncn_fee_group: Option, - first_slot_of_ncn_epoch: Option, + epoch: Option, __remaining_accounts: Vec, } @@ -169,10 +169,9 @@ impl RouteNcnRewardsBuilder { self.ncn_fee_group = Some(ncn_fee_group); self } - /// `[optional argument]` #[inline(always)] - pub fn first_slot_of_ncn_epoch(&mut self, first_slot_of_ncn_epoch: u64) -> &mut Self { - self.first_slot_of_ncn_epoch = Some(first_slot_of_ncn_epoch); + pub fn epoch(&mut self, epoch: u64) -> &mut Self { + self.epoch = Some(epoch); self } /// Add an additional account to the instruction. @@ -214,7 +213,7 @@ impl RouteNcnRewardsBuilder { .ncn_fee_group .clone() .expect("ncn_fee_group is not set"), - first_slot_of_ncn_epoch: self.first_slot_of_ncn_epoch.clone(), + epoch: self.epoch.clone().expect("epoch is not set"), }; accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) @@ -393,7 +392,7 @@ impl<'a, 'b> RouteNcnRewardsCpiBuilder<'a, 'b> { ncn_reward_router: None, restaking_program: None, ncn_fee_group: None, - first_slot_of_ncn_epoch: None, + epoch: None, __remaining_accounts: Vec::new(), }); Self { instruction } @@ -448,10 +447,9 @@ impl<'a, 'b> RouteNcnRewardsCpiBuilder<'a, 'b> { self.instruction.ncn_fee_group = Some(ncn_fee_group); self } - /// `[optional argument]` #[inline(always)] - pub fn first_slot_of_ncn_epoch(&mut self, first_slot_of_ncn_epoch: u64) -> &mut Self { - self.instruction.first_slot_of_ncn_epoch = Some(first_slot_of_ncn_epoch); + pub fn epoch(&mut self, epoch: u64) -> &mut Self { + self.instruction.epoch = Some(epoch); self } /// Add an additional account to the instruction. @@ -501,7 +499,7 @@ impl<'a, 'b> RouteNcnRewardsCpiBuilder<'a, 'b> { .ncn_fee_group .clone() .expect("ncn_fee_group is not set"), - first_slot_of_ncn_epoch: self.instruction.first_slot_of_ncn_epoch.clone(), + epoch: self.instruction.epoch.clone().expect("epoch is not set"), }; let instruction = RouteNcnRewardsCpi { __program: self.instruction.__program, @@ -548,7 +546,7 @@ struct RouteNcnRewardsCpiBuilderInstruction<'a, 'b> { ncn_reward_router: Option<&'b solana_program::account_info::AccountInfo<'a>>, restaking_program: Option<&'b solana_program::account_info::AccountInfo<'a>>, ncn_fee_group: Option, - first_slot_of_ncn_epoch: Option, + epoch: Option, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<( &'b solana_program::account_info::AccountInfo<'a>, diff --git a/clients/rust/jito_tip_router/src/generated/instructions/snapshot_vault_operator_delegation.rs b/clients/rust/jito_tip_router/src/generated/instructions/snapshot_vault_operator_delegation.rs index d1f5f09..ba8c3f6 100644 --- a/clients/rust/jito_tip_router/src/generated/instructions/snapshot_vault_operator_delegation.rs +++ b/clients/rust/jito_tip_router/src/generated/instructions/snapshot_vault_operator_delegation.rs @@ -140,7 +140,7 @@ impl Default for SnapshotVaultOperatorDelegationInstructionData { #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct SnapshotVaultOperatorDelegationInstructionArgs { - pub first_slot_of_ncn_epoch: Option, + pub epoch: u64, } /// Instruction builder for `SnapshotVaultOperatorDelegation`. @@ -177,7 +177,7 @@ pub struct SnapshotVaultOperatorDelegationBuilder { operator_snapshot: Option, vault_program: Option, restaking_program: Option, - first_slot_of_ncn_epoch: Option, + epoch: Option, __remaining_accounts: Vec, } @@ -273,10 +273,9 @@ impl SnapshotVaultOperatorDelegationBuilder { self.restaking_program = Some(restaking_program); self } - /// `[optional argument]` #[inline(always)] - pub fn first_slot_of_ncn_epoch(&mut self, first_slot_of_ncn_epoch: u64) -> &mut Self { - self.first_slot_of_ncn_epoch = Some(first_slot_of_ncn_epoch); + pub fn epoch(&mut self, epoch: u64) -> &mut Self { + self.epoch = Some(epoch); self } /// Add an additional account to the instruction. @@ -322,7 +321,7 @@ impl SnapshotVaultOperatorDelegationBuilder { .expect("restaking_program is not set"), }; let args = SnapshotVaultOperatorDelegationInstructionArgs { - first_slot_of_ncn_epoch: self.first_slot_of_ncn_epoch.clone(), + epoch: self.epoch.clone().expect("epoch is not set"), }; accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) @@ -598,7 +597,7 @@ impl<'a, 'b> SnapshotVaultOperatorDelegationCpiBuilder<'a, 'b> { operator_snapshot: None, vault_program: None, restaking_program: None, - first_slot_of_ncn_epoch: None, + epoch: None, __remaining_accounts: Vec::new(), }); Self { instruction } @@ -709,10 +708,9 @@ impl<'a, 'b> SnapshotVaultOperatorDelegationCpiBuilder<'a, 'b> { self.instruction.restaking_program = Some(restaking_program); self } - /// `[optional argument]` #[inline(always)] - pub fn first_slot_of_ncn_epoch(&mut self, first_slot_of_ncn_epoch: u64) -> &mut Self { - self.instruction.first_slot_of_ncn_epoch = Some(first_slot_of_ncn_epoch); + pub fn epoch(&mut self, epoch: u64) -> &mut Self { + self.instruction.epoch = Some(epoch); self } /// Add an additional account to the instruction. @@ -757,7 +755,7 @@ impl<'a, 'b> SnapshotVaultOperatorDelegationCpiBuilder<'a, 'b> { signers_seeds: &[&[&[u8]]], ) -> solana_program::entrypoint::ProgramResult { let args = SnapshotVaultOperatorDelegationInstructionArgs { - first_slot_of_ncn_epoch: self.instruction.first_slot_of_ncn_epoch.clone(), + epoch: self.instruction.epoch.clone().expect("epoch is not set"), }; let instruction = SnapshotVaultOperatorDelegationCpi { __program: self.instruction.__program, @@ -845,7 +843,7 @@ struct SnapshotVaultOperatorDelegationCpiBuilderInstruction<'a, 'b> { operator_snapshot: Option<&'b solana_program::account_info::AccountInfo<'a>>, vault_program: Option<&'b solana_program::account_info::AccountInfo<'a>>, restaking_program: Option<&'b solana_program::account_info::AccountInfo<'a>>, - first_slot_of_ncn_epoch: Option, + epoch: Option, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<( &'b solana_program::account_info::AccountInfo<'a>, diff --git a/core/src/ballot_box.rs b/core/src/ballot_box.rs index 5df3e4c..518e28c 100644 --- a/core/src/ballot_box.rs +++ b/core/src/ballot_box.rs @@ -1,3 +1,5 @@ +use std::mem::size_of; + use bytemuck::{Pod, Zeroable}; use jito_bytemuck::{ types::{PodBool, PodU16, PodU64}, @@ -221,6 +223,8 @@ impl Discriminator for BallotBox { } impl BallotBox { + pub const SIZE: usize = 8 + size_of::(); + pub fn new(ncn: Pubkey, epoch: u64, bump: u8, current_slot: u64) -> Self { Self { ncn, @@ -238,7 +242,18 @@ impl BallotBox { } pub fn initialize(&mut self, ncn: Pubkey, epoch: u64, bump: u8, current_slot: u64) { - *self = Self::new(ncn, epoch, bump, current_slot); + // Avoids overflowing stack + self.ncn = ncn; + self.epoch = PodU64::from(epoch); + self.bump = bump; + self.slot_created = PodU64::from(current_slot); + self.slot_consensus_reached = PodU64::from(DEFAULT_CONSENSUS_REACHED_SLOT); + self.operators_voted = PodU64::from(0); + self.unique_ballots = PodU64::from(0); + self.winning_ballot = Ballot::default(); + self.operator_votes = [OperatorVote::default(); MAX_OPERATORS]; + self.ballot_tallies = [BallotTally::default(); MAX_OPERATORS]; + self.reserved = [0; 128]; } pub fn seeds(ncn: &Pubkey, epoch: u64) -> Vec> { @@ -746,13 +761,13 @@ mod tests { assert_eq!(ballot_box.ballot_tallies[1].ballot(), ballot2); // Test error when ballot tallies are full - for i in 3..=16 { - let ballot = Ballot::new([i as u8; 32]); + for _ in 3..=ballot_box.ballot_tallies.len() { + let ballot = Ballot::new(Pubkey::new_unique().to_bytes()); ballot_box .increment_or_create_ballot_tally(&ballot, &stake_weights) .unwrap(); } - let ballot_full = Ballot::new([33u8; 32]); + let ballot_full = Ballot::new(Pubkey::new_unique().to_bytes()); let result = ballot_box.increment_or_create_ballot_tally(&ballot_full, &stake_weights); assert!(matches!(result, Err(TipRouterError::BallotTallyFull))); } diff --git a/core/src/base_reward_router.rs b/core/src/base_reward_router.rs index 6ab8be5..7031f07 100644 --- a/core/src/base_reward_router.rs +++ b/core/src/base_reward_router.rs @@ -44,6 +44,8 @@ impl Discriminator for BaseRewardRouter { } impl BaseRewardRouter { + pub const SIZE: usize = 8 + size_of::(); + pub fn new(ncn: Pubkey, ncn_epoch: u64, bump: u8, slot_created: u64) -> Self { Self { ncn, @@ -62,6 +64,23 @@ impl BaseRewardRouter { } } + pub fn initialize(&mut self, ncn: Pubkey, ncn_epoch: u64, bump: u8, current_slot: u64) { + // Initializes field by field to avoid overflowing stack + self.ncn = ncn; + self.ncn_epoch = PodU64::from(ncn_epoch); + self.bump = bump; + self.slot_created = PodU64::from(current_slot); + self.total_rewards = PodU64::from(0); + self.reward_pool = PodU64::from(0); + self.rewards_processed = PodU64::from(0); + self.reserved = [0; 128]; + self.base_fee_group_rewards = + [BaseRewardRouterRewards::default(); NcnFeeGroup::FEE_GROUP_COUNT]; + self.ncn_fee_group_rewards = + [BaseRewardRouterRewards::default(); NcnFeeGroup::FEE_GROUP_COUNT]; + self.ncn_fee_group_reward_routes = [NcnRewardRoute::default(); MAX_OPERATORS]; + } + pub fn seeds(ncn: &Pubkey, ncn_epoch: u64) -> Vec> { Vec::from_iter( [ @@ -79,7 +98,7 @@ impl BaseRewardRouter { ncn: &Pubkey, ncn_epoch: u64, ) -> (Pubkey, u8, Vec>) { - let seeds = Self::seeds(ncn, ncn_epoch); + let seeds: Vec> = Self::seeds(ncn, ncn_epoch); let seeds_iter: Vec<_> = seeds.iter().map(|s| s.as_slice()).collect(); let (pda, bump) = Pubkey::find_program_address(&seeds_iter, program_id); (pda, bump, seeds) diff --git a/core/src/constants.rs b/core/src/constants.rs index d25c003..9b55280 100644 --- a/core/src/constants.rs +++ b/core/src/constants.rs @@ -1,3 +1,4 @@ +use solana_program::entrypoint::MAX_PERMITTED_DATA_INCREASE; use spl_math::precise_number::PreciseNumber; use crate::error::TipRouterError; @@ -18,3 +19,4 @@ pub fn precise_consensus() -> Result { } pub const DEFAULT_CONSENSUS_REACHED_SLOT: u64 = u64::MAX; +pub const MAX_REALLOC_BYTES: u64 = MAX_PERMITTED_DATA_INCREASE as u64; // TODO just use this? diff --git a/core/src/epoch_snapshot.rs b/core/src/epoch_snapshot.rs index 2978cf4..cfe56b9 100644 --- a/core/src/epoch_snapshot.rs +++ b/core/src/epoch_snapshot.rs @@ -1,3 +1,5 @@ +use std::mem::size_of; + use bytemuck::{Pod, Zeroable}; use jito_bytemuck::{ types::{PodBool, PodU16, PodU64}, @@ -50,6 +52,8 @@ impl Discriminator for EpochSnapshot { } impl EpochSnapshot { + pub const SIZE: usize = 8 + size_of::(); + pub fn new( ncn: Pubkey, ncn_epoch: u64, @@ -222,7 +226,7 @@ impl Discriminator for OperatorSnapshot { } impl OperatorSnapshot { - pub const MAX_VAULT_OPERATOR_STAKE_WEIGHT: usize = 64; + pub const SIZE: usize = 8 + size_of::(); #[allow(clippy::too_many_arguments)] pub fn new( @@ -237,7 +241,7 @@ impl OperatorSnapshot { operator_fee_bps: u16, vault_operator_delegation_count: u64, ) -> Result { - if vault_operator_delegation_count > Self::MAX_VAULT_OPERATOR_STAKE_WEIGHT as u64 { + if vault_operator_delegation_count > MAX_VAULT_OPERATOR_DELEGATIONS as u64 { return Err(TipRouterError::TooManyVaultOperatorDelegations); } @@ -314,6 +318,53 @@ impl OperatorSnapshot { Ok(snapshot) } + #[allow(clippy::too_many_arguments)] + pub fn initialize( + &mut self, + operator: Pubkey, + ncn: Pubkey, + ncn_epoch: u64, + bump: u8, + current_slot: u64, + is_active: bool, + ncn_operator_index: u64, + operator_index: u64, + operator_fee_bps: u16, + vault_operator_delegation_count: u64, + ) -> Result<(), TipRouterError> { + if vault_operator_delegation_count > MAX_VAULT_OPERATOR_DELEGATIONS as u64 { + return Err(TipRouterError::TooManyVaultOperatorDelegations); + } + let slot_finalized = if !is_active { current_slot } else { 0 }; + let operator_fee_bps_val = if is_active { operator_fee_bps } else { 0 }; + let vault_operator_delegation_count_val = if is_active { + vault_operator_delegation_count + } else { + 0 + }; + + // Initializes field by field to avoid overflowing stack + self.operator = operator; + self.ncn = ncn; + self.ncn_epoch = PodU64::from(ncn_epoch); + self.bump = bump; + self.slot_created = PodU64::from(current_slot); + self.slot_finalized = PodU64::from(slot_finalized); + self.is_active = PodBool::from(is_active); + self.ncn_operator_index = PodU64::from(ncn_operator_index); + self.operator_index = PodU64::from(operator_index); + self.operator_fee_bps = PodU16::from(operator_fee_bps_val); + self.vault_operator_delegation_count = PodU64::from(vault_operator_delegation_count_val); + self.vault_operator_delegations_registered = PodU64::from(0); + self.valid_operator_vault_delegations = PodU64::from(0); + self.stake_weights = StakeWeights::default(); + self.reserved = [0; 256]; + self.vault_operator_stake_weight = + [VaultOperatorStakeWeight::default(); MAX_VAULT_OPERATOR_DELEGATIONS]; + + Ok(()) + } + pub fn seeds(operator: &Pubkey, ncn: &Pubkey, ncn_epoch: u64) -> Vec> { Vec::from_iter( [ @@ -373,6 +424,14 @@ impl OperatorSnapshot { Ok(()) } + pub const fn operator(&self) -> Pubkey { + self.operator + } + + pub const fn ncn(&self) -> Pubkey { + self.ncn + } + pub fn operator_fee_bps(&self) -> u16 { self.operator_fee_bps.into() } @@ -414,9 +473,7 @@ impl OperatorSnapshot { ncn_fee_group: NcnFeeGroup, stake_weights: &StakeWeights, ) -> Result<(), TipRouterError> { - if self.vault_operator_delegations_registered() - > Self::MAX_VAULT_OPERATOR_STAKE_WEIGHT as u64 - { + if self.vault_operator_delegations_registered() > MAX_VAULT_OPERATOR_DELEGATIONS as u64 { return Err(TipRouterError::TooManyVaultOperatorDelegations); } @@ -578,7 +635,5 @@ mod tests { + size_of::() * MAX_VAULT_OPERATOR_DELEGATIONS; // vault_operator_stake_weight assert_eq!(size_of::(), expected_total); - println!("expected_total: {}", expected_total); - assert!(false); } } diff --git a/core/src/instruction.rs b/core/src/instruction.rs index 8931c51..5095ffa 100644 --- a/core/src/instruction.rs +++ b/core/src/instruction.rs @@ -70,7 +70,7 @@ pub enum TipRouterInstruction { #[account(5, name = "restaking_program")] #[account(6, name = "system_program")] InitializeWeightTable{ - first_slot_of_ncn_epoch: Option, + epoch: u64, }, /// Updates the weight table @@ -95,7 +95,7 @@ pub enum TipRouterInstruction { #[account(7, name = "restaking_program")] #[account(8, name = "system_program")] InitializeEpochSnapshot{ - first_slot_of_ncn_epoch: Option, + epoch: u64, }, /// Initializes the Operator Snapshot @@ -110,7 +110,7 @@ pub enum TipRouterInstruction { #[account(8, name = "restaking_program")] #[account(9, name = "system_program")] InitializeOperatorSnapshot{ - first_slot_of_ncn_epoch: Option, + epoch: u64, }, /// Initializes the Vault Operator Delegation Snapshot @@ -129,7 +129,7 @@ pub enum TipRouterInstruction { #[account(12, name = "vault_program")] #[account(13, name = "restaking_program")] SnapshotVaultOperatorDelegation{ - first_slot_of_ncn_epoch: Option, + epoch: u64, }, /// Registers a mint with the NCN config #[account(0, name = "restaking_config")] @@ -152,7 +152,7 @@ pub enum TipRouterInstruction { #[account(4, name = "restaking_program")] #[account(5, name = "system_program")] InitializeBaseRewardRouter{ - first_slot_of_ncn_epoch: Option, + epoch: u64, }, /// Initializes the ncn reward router @@ -165,7 +165,7 @@ pub enum TipRouterInstruction { #[account(6, name = "system_program")] InitializeNcnRewardRouter{ ncn_fee_group: u8, - first_slot_of_ncn_epoch: Option, + epoch: u64, }, @@ -177,7 +177,7 @@ pub enum TipRouterInstruction { #[account(4, writable, name = "base_reward_router")] #[account(5, name = "restaking_program")] RouteBaseRewards{ - first_slot_of_ncn_epoch: Option, + epoch: u64, }, /// Routes ncn reward router @@ -189,7 +189,7 @@ pub enum TipRouterInstruction { #[account(5, name = "restaking_program")] RouteNcnRewards{ ncn_fee_group: u8, - first_slot_of_ncn_epoch: Option, + epoch: u64, }, /// Distributes base rewards @@ -201,7 +201,7 @@ pub enum TipRouterInstruction { #[account(5, name = "restaking_program")] DistributeBaseRewards{ base_fee_group: u8, - first_slot_of_ncn_epoch: Option, + epoch: u64, }, /// Distributes base ncn reward routes @@ -214,7 +214,7 @@ pub enum TipRouterInstruction { #[account(6, name = "restaking_program")] DistributeBaseNcnRewardRoute{ ncn_fee_group: u8, - first_slot_of_ncn_epoch: Option, + epoch: u64, }, /// Distributes ncn operator rewards @@ -226,7 +226,7 @@ pub enum TipRouterInstruction { #[account(5, name = "restaking_program")] DistributeNcnOperatorRewards{ ncn_fee_group: u8, - first_slot_of_ncn_epoch: Option, + epoch: u64, }, /// Distributes ncn vault rewards @@ -238,7 +238,7 @@ pub enum TipRouterInstruction { #[account(5, writable, name = "ncn_reward_router")] DistributeNcnVaultRewards{ ncn_fee_group: u8, - first_slot_of_ncn_epoch: Option, + epoch: u64, }, /// Sets the NCN fee group for a mint @@ -304,5 +304,51 @@ pub enum TipRouterInstruction { SetTieBreaker { meta_merkle_root: [u8; 32], epoch: u64, - } + }, + + /// Resizes the ballot box account + #[account(0, name = "ncn_config")] + #[account(1, writable, name = "ballot_box")] + #[account(2, name = "ncn")] + #[account(3, writable, signer, name = "payer")] + #[account(4, name = "system_program")] + ReallocBallotBox { + epoch: u64, + }, + + /// Resizes the operator snapshot account + #[account(0, name = "ncn_config")] + #[account(1, name = "restaking_config")] + #[account(2, name = "ncn")] + #[account(3, name = "operator")] + #[account(4, name = "ncn_operator_state")] + #[account(5, writable, name = "epoch_snapshot")] + #[account(6, writable, name = "operator_snapshot")] + #[account(7, writable, signer, name = "payer")] + #[account(8, name = "restaking_program")] + #[account(9, name = "system_program")] + ReallocOperatorSnapshot { + epoch: u64, + }, + + /// Resizes the base reward router account + #[account(0, name = "ncn_config")] + #[account(1, writable, name = "base_reward_router")] + #[account(2, name = "ncn")] + #[account(3, writable, signer, name = "payer")] + #[account(4, name = "system_program")] + ReallocBaseRewardRouter { + epoch: u64, + }, + + /// Resizes the weight table account + #[account(0, name = "ncn_config")] + #[account(1, writable, name = "weight_table")] + #[account(2, name = "ncn")] + #[account(3, name = "tracked_mints")] + #[account(4, writable, signer, name = "payer")] + #[account(5, name = "system_program")] + ReallocWeightTable { + epoch: u64, + }, } diff --git a/core/src/lib.rs b/core/src/lib.rs index e5633be..7ef1bae 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -13,5 +13,6 @@ pub mod ncn_fee_group; pub mod ncn_reward_router; pub mod stake_weight; pub mod tracked_mints; +pub mod utils; pub mod weight_entry; pub mod weight_table; diff --git a/core/src/ncn_config.rs b/core/src/ncn_config.rs index 670a362..da5d2ff 100644 --- a/core/src/ncn_config.rs +++ b/core/src/ncn_config.rs @@ -1,3 +1,5 @@ +use std::mem::size_of; + use bytemuck::{Pod, Zeroable}; use jito_bytemuck::{types::PodU64, AccountDeserialize, Discriminator}; use shank::{ShankAccount, ShankType}; @@ -34,6 +36,8 @@ impl Discriminator for NcnConfig { } impl NcnConfig { + pub const SIZE: usize = 8 + size_of::(); + pub fn new( ncn: Pubkey, tie_breaker_admin: Pubkey, diff --git a/core/src/ncn_reward_router.rs b/core/src/ncn_reward_router.rs index a2b8388..573cc80 100644 --- a/core/src/ncn_reward_router.rs +++ b/core/src/ncn_reward_router.rs @@ -48,6 +48,8 @@ impl Discriminator for NcnRewardRouter { } impl NcnRewardRouter { + pub const SIZE: usize = 8 + size_of::(); + pub fn new( ncn_fee_group: NcnFeeGroup, operator: Pubkey, diff --git a/core/src/tracked_mints.rs b/core/src/tracked_mints.rs index 82cc25a..8307a15 100644 --- a/core/src/tracked_mints.rs +++ b/core/src/tracked_mints.rs @@ -1,4 +1,4 @@ -use std::collections::HashSet; +use std::{collections::HashSet, mem::size_of}; use bytemuck::{Pod, Zeroable}; use jito_bytemuck::{types::PodU64, AccountDeserialize, Discriminator}; @@ -66,6 +66,8 @@ impl Discriminator for TrackedMints { } impl TrackedMints { + pub const SIZE: usize = 8 + size_of::(); + pub fn new(ncn: Pubkey, bump: u8) -> Self { Self { ncn, @@ -75,6 +77,14 @@ impl TrackedMints { } } + pub fn initialize(&mut self, ncn: Pubkey, bump: u8) { + // Initializes field by field to avoid overflowing stack + self.ncn = ncn; + self.bump = bump; + self.reserved = [0; 127]; + self.st_mint_list = [MintEntry::default(); MAX_VAULT_OPERATOR_DELEGATIONS]; + } + pub fn seeds(ncn: &Pubkey) -> Vec> { Vec::from_iter( [b"tracked_mints".to_vec(), ncn.to_bytes().to_vec()] diff --git a/core/src/utils.rs b/core/src/utils.rs new file mode 100644 index 0000000..caa39ea --- /dev/null +++ b/core/src/utils.rs @@ -0,0 +1,12 @@ +use solana_program::program_error::ProgramError; + +use crate::constants::MAX_REALLOC_BYTES; + +/// Calculate new size for reallocation, capped at target size +/// Returns the minimum of (current_size + MAX_REALLOC_BYTES) and target_size +pub fn get_new_size(current_size: usize, target_size: usize) -> Result { + Ok(current_size + .checked_add(MAX_REALLOC_BYTES as usize) + .ok_or(ProgramError::ArithmeticOverflow)? + .min(target_size)) +} diff --git a/core/src/weight_table.rs b/core/src/weight_table.rs index 13d5d9e..8e5a0c8 100644 --- a/core/src/weight_table.rs +++ b/core/src/weight_table.rs @@ -1,4 +1,4 @@ -use std::collections::HashSet; +use std::{collections::HashSet, mem::size_of}; use bytemuck::{Pod, Zeroable}; use jito_bytemuck::{types::PodU64, AccountDeserialize, Discriminator}; @@ -6,7 +6,10 @@ use shank::{ShankAccount, ShankType}; use solana_program::{account_info::AccountInfo, msg, program_error::ProgramError, pubkey::Pubkey}; use spl_math::precise_number::PreciseNumber; -use crate::{discriminators::Discriminators, error::TipRouterError, weight_entry::WeightEntry}; +use crate::{ + constants::MAX_VAULT_OPERATOR_DELEGATIONS, discriminators::Discriminators, + error::TipRouterError, weight_entry::WeightEntry, +}; // PDA'd ["WEIGHT_TABLE", NCN, NCN_EPOCH_SLOT] #[derive(Debug, Clone, Copy, Zeroable, ShankType, Pod, AccountDeserialize, ShankAccount)] @@ -29,7 +32,7 @@ pub struct WeightTable { reserved: [u8; 128], /// The weight table - table: [WeightEntry; 32], + table: [WeightEntry; 64], } impl Discriminator for WeightTable { @@ -37,7 +40,7 @@ impl Discriminator for WeightTable { } impl WeightTable { - pub const MAX_TABLE_ENTRIES: usize = 32; + pub const SIZE: usize = 8 + size_of::(); pub fn new(ncn: Pubkey, ncn_epoch: u64, slot_created: u64, bump: u8) -> Self { Self { @@ -46,7 +49,7 @@ impl WeightTable { slot_created: PodU64::from(slot_created), bump, reserved: [0; 128], - table: [WeightEntry::default(); Self::MAX_TABLE_ENTRIES], + table: [WeightEntry::default(); MAX_VAULT_OPERATOR_DELEGATIONS], } } @@ -73,7 +76,26 @@ impl WeightTable { (pda, bump, seeds) } - pub fn initalize_weight_table( + pub fn initialize( + &mut self, + ncn: Pubkey, + ncn_epoch: u64, + slot_created: u64, + bump: u8, + config_supported_mints: &[Pubkey], + ) -> Result<(), TipRouterError> { + // Initializes field by field to avoid overflowing stack + self.ncn = ncn; + self.ncn_epoch = PodU64::from(ncn_epoch); + self.slot_created = PodU64::from(slot_created); + self.bump = bump; + self.reserved = [0; 128]; + self.table = [WeightEntry::default(); MAX_VAULT_OPERATOR_DELEGATIONS]; + self.set_supported_mints(config_supported_mints)?; + Ok(()) + } + + fn set_supported_mints( &mut self, config_supported_mints: &[Pubkey], ) -> Result<(), TipRouterError> { @@ -87,7 +109,7 @@ impl WeightTable { } // Check if vector exceeds maximum allowed entries - if config_supported_mints.len() > Self::MAX_TABLE_ENTRIES { + if config_supported_mints.len() > MAX_VAULT_OPERATOR_DELEGATIONS { return Err(TipRouterError::TooManyMintsForTable); } @@ -217,6 +239,8 @@ impl WeightTable { #[cfg(test)] mod tests { + use std::mem::size_of; + use solana_program::pubkey::Pubkey; use super::*; @@ -225,6 +249,18 @@ mod tests { (0..count).map(|_| Pubkey::new_unique()).collect() } + #[test] + fn test_len() { + let expected_total = size_of::() // ncn + + size_of::() // ncn_epoch + + size_of::() // slot_created + + 1 // bump + + 128 // reserved + + size_of::<[WeightEntry; MAX_VAULT_OPERATOR_DELEGATIONS]>(); // weight table + + assert_eq!(size_of::(), expected_total); + } + #[test] fn test_initialize_table_success() { let ncn = Pubkey::new_unique(); @@ -232,7 +268,7 @@ mod tests { assert_eq!(table.mint_count(), 0); let mints = get_test_pubkeys(2); - table.initalize_weight_table(&mints).unwrap(); + table.set_supported_mints(&mints).unwrap(); assert_eq!(table.mint_count(), 2); } @@ -240,9 +276,9 @@ mod tests { fn test_initialize_table_too_many() { let ncn = Pubkey::new_unique(); let mut table = WeightTable::new(ncn, 0, 0, 0); - let many_mints = get_test_pubkeys(WeightTable::MAX_TABLE_ENTRIES + 1); + let many_mints = get_test_pubkeys(MAX_VAULT_OPERATOR_DELEGATIONS + 1); assert_eq!( - table.initalize_weight_table(&many_mints), + table.set_supported_mints(&many_mints), Err(TipRouterError::TooManyMintsForTable) ); } @@ -251,9 +287,9 @@ mod tests { fn test_initialize_table_max() { let ncn = Pubkey::new_unique(); let mut table = WeightTable::new(ncn, 0, 0, 0); - let max_mints = get_test_pubkeys(WeightTable::MAX_TABLE_ENTRIES); - table.initalize_weight_table(&max_mints).unwrap(); - assert_eq!(table.mint_count(), WeightTable::MAX_TABLE_ENTRIES); + let max_mints = get_test_pubkeys(MAX_VAULT_OPERATOR_DELEGATIONS); + table.set_supported_mints(&max_mints).unwrap(); + assert_eq!(table.mint_count(), MAX_VAULT_OPERATOR_DELEGATIONS); } #[test] @@ -261,11 +297,11 @@ mod tests { let ncn = Pubkey::new_unique(); let mut table = WeightTable::new(ncn, 0, 0, 0); let first_mints = get_test_pubkeys(2); - table.initalize_weight_table(&first_mints).unwrap(); + table.set_supported_mints(&first_mints).unwrap(); let second_mints = get_test_pubkeys(3); assert_eq!( - table.initalize_weight_table(&second_mints), + table.set_supported_mints(&second_mints), Err(TipRouterError::WeightTableAlreadyInitialized) ); } @@ -277,7 +313,7 @@ mod tests { let mints = get_test_pubkeys(2); let mint = mints[0]; - table.initalize_weight_table(&mints).unwrap(); + table.set_supported_mints(&mints).unwrap(); table.set_weight(&mint, 100, 1).unwrap(); assert_eq!(table.get_weight(&mint).unwrap(), 100); @@ -289,7 +325,7 @@ mod tests { let mut table = WeightTable::new(ncn, 0, 0, 0); let mints = get_test_pubkeys(2); - table.initalize_weight_table(&mints).unwrap(); + table.set_supported_mints(&mints).unwrap(); let invalid_mint = Pubkey::new_unique(); assert_eq!( @@ -305,7 +341,7 @@ mod tests { let mints = get_test_pubkeys(2); let mint = mints[0]; - table.initalize_weight_table(&mints).unwrap(); + table.set_supported_mints(&mints).unwrap(); table.set_weight(&mint, 100, 1).unwrap(); assert_eq!(table.get_weight(&mint).unwrap(), 100); @@ -322,7 +358,7 @@ mod tests { let mint1 = mints[0]; let mint2 = mints[1]; - table.initalize_weight_table(&mints).unwrap(); + table.set_supported_mints(&mints).unwrap(); table.set_weight(&mint1, 100, 1).unwrap(); table.set_weight(&mint2, 200, 1).unwrap(); @@ -338,7 +374,7 @@ mod tests { let mints = get_test_pubkeys(2); let mint = mints[0]; - table.initalize_weight_table(&mints).unwrap(); + table.set_supported_mints(&mints).unwrap(); table.set_weight(&mint, 100, 1).unwrap(); assert_eq!(table.get_weight(&mint).unwrap(), 100); diff --git a/idl/jito_tip_router.json b/idl/jito_tip_router.json index 78bce84..a4ecb2a 100644 --- a/idl/jito_tip_router.json +++ b/idl/jito_tip_router.json @@ -255,10 +255,8 @@ ], "args": [ { - "name": "firstSlotOfNcnEpoch", - "type": { - "option": "u64" - } + "name": "epoch", + "type": "u64" } ], "discriminant": { @@ -361,10 +359,8 @@ ], "args": [ { - "name": "firstSlotOfNcnEpoch", - "type": { - "option": "u64" - } + "name": "epoch", + "type": "u64" } ], "discriminant": { @@ -428,10 +424,8 @@ ], "args": [ { - "name": "firstSlotOfNcnEpoch", - "type": { - "option": "u64" - } + "name": "epoch", + "type": "u64" } ], "discriminant": { @@ -515,10 +509,8 @@ ], "args": [ { - "name": "firstSlotOfNcnEpoch", - "type": { - "option": "u64" - } + "name": "epoch", + "type": "u64" } ], "discriminant": { @@ -617,10 +609,8 @@ ], "args": [ { - "name": "firstSlotOfNcnEpoch", - "type": { - "option": "u64" - } + "name": "epoch", + "type": "u64" } ], "discriminant": { @@ -673,10 +663,8 @@ "type": "u8" }, { - "name": "firstSlotOfNcnEpoch", - "type": { - "option": "u64" - } + "name": "epoch", + "type": "u64" } ], "discriminant": { @@ -720,10 +708,8 @@ ], "args": [ { - "name": "firstSlotOfNcnEpoch", - "type": { - "option": "u64" - } + "name": "epoch", + "type": "u64" } ], "discriminant": { @@ -771,10 +757,8 @@ "type": "u8" }, { - "name": "firstSlotOfNcnEpoch", - "type": { - "option": "u64" - } + "name": "epoch", + "type": "u64" } ], "discriminant": { @@ -822,10 +806,8 @@ "type": "u8" }, { - "name": "firstSlotOfNcnEpoch", - "type": { - "option": "u64" - } + "name": "epoch", + "type": "u64" } ], "discriminant": { @@ -878,10 +860,8 @@ "type": "u8" }, { - "name": "firstSlotOfNcnEpoch", - "type": { - "option": "u64" - } + "name": "epoch", + "type": "u64" } ], "discriminant": { @@ -929,10 +909,8 @@ "type": "u8" }, { - "name": "firstSlotOfNcnEpoch", - "type": { - "option": "u64" - } + "name": "epoch", + "type": "u64" } ], "discriminant": { @@ -980,10 +958,8 @@ "type": "u8" }, { - "name": "firstSlotOfNcnEpoch", - "type": { - "option": "u64" - } + "name": "epoch", + "type": "u64" } ], "discriminant": { @@ -1280,6 +1256,196 @@ "type": "u8", "value": 22 } + }, + { + "name": "ReallocBallotBox", + "accounts": [ + { + "name": "ncnConfig", + "isMut": false, + "isSigner": false + }, + { + "name": "ballotBox", + "isMut": true, + "isSigner": false + }, + { + "name": "ncn", + "isMut": false, + "isSigner": false + }, + { + "name": "payer", + "isMut": true, + "isSigner": true + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "epoch", + "type": "u64" + } + ], + "discriminant": { + "type": "u8", + "value": 23 + } + }, + { + "name": "ReallocOperatorSnapshot", + "accounts": [ + { + "name": "ncnConfig", + "isMut": false, + "isSigner": false + }, + { + "name": "restakingConfig", + "isMut": false, + "isSigner": false + }, + { + "name": "ncn", + "isMut": false, + "isSigner": false + }, + { + "name": "operator", + "isMut": false, + "isSigner": false + }, + { + "name": "ncnOperatorState", + "isMut": false, + "isSigner": false + }, + { + "name": "epochSnapshot", + "isMut": true, + "isSigner": false + }, + { + "name": "operatorSnapshot", + "isMut": true, + "isSigner": false + }, + { + "name": "payer", + "isMut": true, + "isSigner": true + }, + { + "name": "restakingProgram", + "isMut": false, + "isSigner": false + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "epoch", + "type": "u64" + } + ], + "discriminant": { + "type": "u8", + "value": 24 + } + }, + { + "name": "ReallocBaseRewardRouter", + "accounts": [ + { + "name": "ncnConfig", + "isMut": false, + "isSigner": false + }, + { + "name": "baseRewardRouter", + "isMut": true, + "isSigner": false + }, + { + "name": "ncn", + "isMut": false, + "isSigner": false + }, + { + "name": "payer", + "isMut": true, + "isSigner": true + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "epoch", + "type": "u64" + } + ], + "discriminant": { + "type": "u8", + "value": 25 + } + }, + { + "name": "ReallocWeightTable", + "accounts": [ + { + "name": "ncnConfig", + "isMut": false, + "isSigner": false + }, + { + "name": "weightTable", + "isMut": true, + "isSigner": false + }, + { + "name": "ncn", + "isMut": false, + "isSigner": false + }, + { + "name": "trackedMints", + "isMut": false, + "isSigner": false + }, + { + "name": "payer", + "isMut": true, + "isSigner": true + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "epoch", + "type": "u64" + } + ], + "discriminant": { + "type": "u8", + "value": 26 + } } ], "accounts": [ @@ -1849,7 +2015,7 @@ { "defined": "WeightEntry" }, - 32 + 64 ] } } diff --git a/integration_tests/tests/fixtures/jito_tip_router_program-keypair.json b/integration_tests/tests/fixtures/jito_tip_router_program-keypair.json new file mode 100644 index 0000000..44bd7c4 --- /dev/null +++ b/integration_tests/tests/fixtures/jito_tip_router_program-keypair.json @@ -0,0 +1 @@ +[165,11,30,77,191,210,41,183,26,163,99,7,95,182,36,159,153,122,235,90,176,179,26,20,120,197,213,118,186,223,78,241,132,57,56,184,252,97,61,211,46,207,84,250,171,50,205,240,68,77,96,245,177,133,183,26,32,242,50,128,251,144,168,67] \ No newline at end of file diff --git a/integration_tests/tests/fixtures/jito_tip_router_program.so b/integration_tests/tests/fixtures/jito_tip_router_program.so deleted file mode 100755 index c1c1d1c..0000000 Binary files a/integration_tests/tests/fixtures/jito_tip_router_program.so and /dev/null differ diff --git a/integration_tests/tests/fixtures/mod.rs b/integration_tests/tests/fixtures/mod.rs index 7103bbd..7aa8d15 100644 --- a/integration_tests/tests/fixtures/mod.rs +++ b/integration_tests/tests/fixtures/mod.rs @@ -31,12 +31,12 @@ pub enum TestError { impl TestError { pub fn to_transaction_error(&self) -> Option { match self { - TestError::BanksClientError(e) => match e { + Self::BanksClientError(e) => match e { BanksClientError::TransactionError(e) => Some(e.clone()), BanksClientError::SimulationError { err, .. } => Some(err.clone()), _ => None, }, - TestError::ProgramError(_) => None, + Self::ProgramError(_) => None, _ => None, } } diff --git a/integration_tests/tests/fixtures/restaking_client.rs b/integration_tests/tests/fixtures/restaking_client.rs index fa50a83..4b1d7a0 100644 --- a/integration_tests/tests/fixtures/restaking_client.rs +++ b/integration_tests/tests/fixtures/restaking_client.rs @@ -89,13 +89,6 @@ impl RestakingProgramClient { Ok(*Config::try_from_slice_unchecked(account.data.as_slice())?) } - pub async fn get_ncn_epoch(&mut self, slot: u64) -> TestResult { - let restaking_config_address = - Config::find_program_address(&jito_restaking_program::id()).0; - let config = self.get_config(&restaking_config_address).await.unwrap(); - Ok(config.get_epoch_from_slot(slot).unwrap()) - } - #[allow(dead_code)] pub async fn get_ncn_vault_ticket( &mut self, diff --git a/integration_tests/tests/fixtures/test_builder.rs b/integration_tests/tests/fixtures/test_builder.rs index dd31360..8785b08 100644 --- a/integration_tests/tests/fixtures/test_builder.rs +++ b/integration_tests/tests/fixtures/test_builder.rs @@ -14,8 +14,13 @@ use solana_program::{ }; use solana_program_test::{processor, BanksClientError, ProgramTest, ProgramTestContext}; use solana_sdk::{ - account::Account, commitment_config::CommitmentLevel, epoch_schedule::EpochSchedule, - native_token::lamports_to_sol, signature::Signer, transaction::Transaction, + account::Account, + commitment_config::CommitmentLevel, + epoch_schedule::EpochSchedule, + native_token::{lamports_to_sol, LAMPORTS_PER_SOL}, + signature::{Keypair, Signer}, + system_instruction, + transaction::Transaction, }; use super::{ @@ -57,11 +62,21 @@ impl Debug for TestBuilder { } } +pub const fn system_account(lamports: u64) -> Account { + Account { + lamports, + owner: solana_program::system_program::ID, + executable: false, + rent_epoch: 0, + data: vec![], + } +} + impl TestBuilder { pub async fn new() -> Self { let run_as_bpf = std::env::vars().any(|(key, _)| key.eq("SBF_OUT_DIR")); - let program_test = if run_as_bpf { + let mut program_test = if run_as_bpf { let mut program_test = ProgramTest::new( "jito_tip_router_program", jito_tip_router_program::id(), @@ -95,13 +110,39 @@ impl TestBuilder { program_test }; - Self { - context: program_test.start_with_context().await, - } + // Pre-fund payer with 1M SOL + let whale = Keypair::new(); + program_test.add_account(whale.pubkey(), system_account(1_000_000 * LAMPORTS_PER_SOL)); + let mut context = program_test.start_with_context().await; + let transaction = Transaction::new_signed_with_payer( + &[system_instruction::transfer( + &whale.pubkey(), + &context.payer.pubkey(), + 999_999 * LAMPORTS_PER_SOL, + )], + Some(&whale.pubkey()), + &[&whale], + context.last_blockhash, + ); + + context + .banks_client + .process_transaction(transaction) + .await + .expect("failed to pre-fund payer"); + + Self { context } } pub async fn get_balance(&mut self, pubkey: &Pubkey) -> Result { - Ok(self.context.banks_client.get_balance(*pubkey).await?) + self.context.banks_client.get_balance(*pubkey).await + } + + pub async fn get_account( + &mut self, + address: &Pubkey, + ) -> Result, BanksClientError> { + self.context.banks_client.get_account(*address).await } pub async fn warp_slot_incremental( @@ -307,11 +348,11 @@ impl TestBuilder { for operator_root in test_ncn.operators.iter() { // vault <> operator restaking_program_client - .do_initialize_operator_vault_ticket(&operator_root, &vault_root.vault_pubkey) + .do_initialize_operator_vault_ticket(operator_root, &vault_root.vault_pubkey) .await?; self.warp_slot_incremental(1).await.unwrap(); restaking_program_client - .do_warmup_operator_vault_ticket(&operator_root, &vault_root.vault_pubkey) + .do_warmup_operator_vault_ticket(operator_root, &vault_root.vault_pubkey) .await?; vault_program_client .do_initialize_vault_operator_delegation( @@ -349,7 +390,7 @@ impl TestBuilder { for operator_root in test_ncn.operators.iter() { vault_program_client .do_add_delegation( - &vault_root, + vault_root, &operator_root.operator_pubkey, delegation_amount as u64, ) @@ -433,9 +474,10 @@ impl TestBuilder { // Not sure if this is needed self.warp_slot_incremental(1000).await?; - let slot = self.clock().await.slot; + let clock = self.clock().await; + let epoch = clock.epoch; tip_router_client - .do_initialize_weight_table(test_ncn.ncn_root.ncn_pubkey, slot) + .do_full_initialize_weight_table(test_ncn.ncn_root.ncn_pubkey, epoch) .await?; for vault_root in test_ncn.vaults.iter() { @@ -444,7 +486,7 @@ impl TestBuilder { let mint = vault.supported_mint; tip_router_client - .do_admin_update_weight_table(test_ncn.ncn_root.ncn_pubkey, slot, mint, WEIGHT) + .do_admin_update_weight_table(test_ncn.ncn_root.ncn_pubkey, epoch, mint, WEIGHT) .await?; } @@ -455,10 +497,11 @@ impl TestBuilder { pub async fn add_epoch_snapshot_to_test_ncn(&mut self, test_ncn: &TestNcn) -> TestResult<()> { let mut tip_router_client = self.tip_router_client(); - let slot = self.clock().await.slot; + let clock = self.clock().await; + let epoch = clock.epoch; tip_router_client - .do_initialize_epoch_snapshot(test_ncn.ncn_root.ncn_pubkey, slot) + .do_initialize_epoch_snapshot(test_ncn.ncn_root.ncn_pubkey, epoch) .await?; Ok(()) @@ -471,14 +514,16 @@ impl TestBuilder { ) -> TestResult<()> { let mut tip_router_client = self.tip_router_client(); - let slot = self.clock().await.slot; + let clock = self.clock().await; + let epoch = clock.epoch; + let ncn = test_ncn.ncn_root.ncn_pubkey; for operator_root in test_ncn.operators.iter() { let operator = operator_root.operator_pubkey; tip_router_client - .do_initialize_operator_snapshot(operator, ncn, slot) + .do_full_initialize_operator_snapshot(operator, ncn, epoch) .await?; } @@ -492,7 +537,8 @@ impl TestBuilder { ) -> TestResult<()> { let mut tip_router_client = self.tip_router_client(); - let slot = self.clock().await.slot; + let clock = self.clock().await; + let epoch = clock.epoch; let ncn = test_ncn.ncn_root.ncn_pubkey; for operator_root in test_ncn.operators.iter() { @@ -501,7 +547,7 @@ impl TestBuilder { let vault = vault_root.vault_pubkey; tip_router_client - .do_snapshot_vault_operator_delegation(vault, operator, ncn, slot) + .do_snapshot_vault_operator_delegation(vault, operator, ncn, epoch) .await?; } } @@ -511,10 +557,10 @@ impl TestBuilder { // Intermission 2 - all snapshots are taken pub async fn snapshot_test_ncn(&mut self, test_ncn: &TestNcn) -> TestResult<()> { - self.add_weights_for_test_ncn(&test_ncn).await?; - self.add_epoch_snapshot_to_test_ncn(&test_ncn).await?; - self.add_operator_snapshots_to_test_ncn(&test_ncn).await?; - self.add_vault_operator_delegation_snapshots_to_test_ncn(&test_ncn) + self.add_weights_for_test_ncn(test_ncn).await?; + self.add_epoch_snapshot_to_test_ncn(test_ncn).await?; + self.add_operator_snapshots_to_test_ncn(test_ncn).await?; + self.add_vault_operator_delegation_snapshots_to_test_ncn(test_ncn) .await?; Ok(()) @@ -523,15 +569,13 @@ impl TestBuilder { // 10 - Initialize Ballot Box pub async fn add_ballot_box_to_test_ncn(&mut self, test_ncn: &TestNcn) -> TestResult<()> { let mut tip_router_client = self.tip_router_client(); - let mut restaking_program_client = self.restaking_program_client(); - let slot = self.clock().await.slot; + let clock = self.clock().await; + let epoch = clock.epoch; let ncn = test_ncn.ncn_root.ncn_pubkey; - let ncn_epoch = restaking_program_client.get_ncn_epoch(slot).await?; - tip_router_client - .do_initialize_ballot_box(ncn, ncn_epoch) + .do_full_initialize_ballot_box(ncn, epoch) .await?; Ok(()) @@ -540,13 +584,11 @@ impl TestBuilder { // 11 - Cast all votes pub async fn cast_votes_for_test_ncn(&mut self, test_ncn: &TestNcn) -> TestResult<()> { let mut tip_router_client = self.tip_router_client(); - let mut restaking_program_client = self.restaking_program_client(); - let slot = self.clock().await.slot; + let clock = self.clock().await; + let epoch = clock.epoch; let ncn = test_ncn.ncn_root.ncn_pubkey; - let ncn_epoch = restaking_program_client.get_ncn_epoch(slot).await?; - let meta_merkle_root = [1u8; 32]; for operator_root in test_ncn.operators.iter() { @@ -558,7 +600,7 @@ impl TestBuilder { operator, &operator_root.operator_admin, meta_merkle_root, - ncn_epoch, + epoch, ) .await?; } @@ -568,8 +610,8 @@ impl TestBuilder { // Intermission 3 - come to consensus pub async fn vote_test_ncn(&mut self, test_ncn: &TestNcn) -> TestResult<()> { - self.add_ballot_box_to_test_ncn(&test_ncn).await?; - self.cast_votes_for_test_ncn(&test_ncn).await?; + self.add_ballot_box_to_test_ncn(test_ncn).await?; + self.cast_votes_for_test_ncn(test_ncn).await?; Ok(()) } @@ -579,10 +621,11 @@ impl TestBuilder { let mut tip_router_client = self.tip_router_client(); let ncn: Pubkey = test_ncn.ncn_root.ncn_pubkey; - let slot = self.clock().await.slot; + let clock = self.clock().await; + let epoch = clock.epoch; tip_router_client - .do_initialize_base_reward_router(ncn, slot) + .do_full_initialize_base_reward_router(ncn, epoch) .await?; for operator_root in test_ncn.operators.iter() { @@ -590,7 +633,7 @@ impl TestBuilder { for group in NcnFeeGroup::all_groups().iter() { tip_router_client - .do_initialize_ncn_reward_router(*group, ncn, operator, slot) + .do_initialize_ncn_reward_router(*group, ncn, operator, epoch) .await?; } } @@ -605,14 +648,12 @@ impl TestBuilder { rewards: u64, ) -> TestResult<()> { let mut tip_router_client = self.tip_router_client(); - let mut restaking_program_client = self.restaking_program_client(); let ncn = test_ncn.ncn_root.ncn_pubkey; - let slot = self.clock().await.slot; - let ncn_epoch = restaking_program_client.get_ncn_epoch(slot).await?; + let epoch = self.clock().await.epoch; let (base_reward_router, _, _) = - BaseRewardRouter::find_program_address(&jito_tip_router_program::id(), &ncn, ncn_epoch); + BaseRewardRouter::find_program_address(&jito_tip_router_program::id(), &ncn, epoch); let sol_rewards = lamports_to_sol(rewards); @@ -622,11 +663,9 @@ impl TestBuilder { .await?; // route rewards - tip_router_client.do_route_base_rewards(ncn, slot).await?; + tip_router_client.do_route_base_rewards(ncn, epoch).await?; - let base_reward_router = tip_router_client - .get_base_reward_router(ncn, ncn_epoch) - .await?; + let base_reward_router = tip_router_client.get_base_reward_router(ncn, epoch).await?; // Base Rewards for group in BaseFeeGroup::all_groups().iter() { @@ -637,7 +676,7 @@ impl TestBuilder { } tip_router_client - .do_distribute_base_rewards(*group, ncn, slot) + .do_distribute_base_rewards(*group, ncn, epoch) .await?; } @@ -656,7 +695,7 @@ impl TestBuilder { } tip_router_client - .do_distribute_base_ncn_reward_route(*group, operator, ncn, slot) + .do_distribute_base_ncn_reward_route(*group, operator, ncn, epoch) .await?; } } @@ -671,29 +710,27 @@ impl TestBuilder { test_ncn: &TestNcn, ) -> TestResult<()> { let mut tip_router_client = self.tip_router_client(); - let mut restaking_program_client = self.restaking_program_client(); let ncn = test_ncn.ncn_root.ncn_pubkey; - let slot = self.clock().await.slot; - let ncn_epoch = restaking_program_client.get_ncn_epoch(slot).await?; + let epoch = self.clock().await.epoch; for operator_root in test_ncn.operators.iter() { let operator = operator_root.operator_pubkey; for group in NcnFeeGroup::all_groups().iter() { tip_router_client - .do_route_ncn_rewards(*group, ncn, operator, slot) + .do_route_ncn_rewards(*group, ncn, operator, epoch) .await?; let ncn_reward_router = tip_router_client - .get_ncn_reward_router(*group, operator, ncn, ncn_epoch) + .get_ncn_reward_router(*group, operator, ncn, epoch) .await?; let operator_rewards = ncn_reward_router.operator_rewards(); if operator_rewards > 0 { tip_router_client - .do_distribute_ncn_operator_rewards(*group, operator, ncn, slot) + .do_distribute_ncn_operator_rewards(*group, operator, ncn, epoch) .await?; } @@ -707,7 +744,9 @@ impl TestBuilder { if vault_rewards > 0 { tip_router_client - .do_distribute_ncn_vault_rewards(*group, vault, operator, ncn, slot) + .do_distribute_ncn_vault_rewards( + *group, vault, operator, ncn, epoch, + ) .await?; } } diff --git a/integration_tests/tests/fixtures/tip_distribution_client.rs b/integration_tests/tests/fixtures/tip_distribution_client.rs index eae7c8a..055866b 100644 --- a/integration_tests/tests/fixtures/tip_distribution_client.rs +++ b/integration_tests/tests/fixtures/tip_distribution_client.rs @@ -96,7 +96,7 @@ impl TipDistributionClient { &self.payer.pubkey(), &vote_keypair.pubkey(), &vote_init, - 1 * LAMPORTS_PER_SOL, + LAMPORTS_PER_SOL, CreateVoteAccountConfig { space: VoteStateVersions::vote_state_size_of(true) as u64, with_seed: None, diff --git a/integration_tests/tests/fixtures/tip_router_client.rs b/integration_tests/tests/fixtures/tip_router_client.rs index d5a6f95..e6e3e37 100644 --- a/integration_tests/tests/fixtures/tip_router_client.rs +++ b/integration_tests/tests/fixtures/tip_router_client.rs @@ -11,10 +11,11 @@ use jito_tip_router_client::{ InitializeBaseRewardRouterBuilder, InitializeEpochSnapshotBuilder, InitializeNCNConfigBuilder, InitializeNcnRewardRouterBuilder, InitializeOperatorSnapshotBuilder, InitializeTrackedMintsBuilder, - InitializeWeightTableBuilder, RegisterMintBuilder, RouteBaseRewardsBuilder, - RouteNcnRewardsBuilder, SetConfigFeesBuilder, SetMerkleRootBuilder, SetNewAdminBuilder, - SetTieBreakerBuilder, SetTrackedMintNcnFeeGroupBuilder, - SnapshotVaultOperatorDelegationBuilder, + InitializeWeightTableBuilder, ReallocBallotBoxBuilder, ReallocBaseRewardRouterBuilder, + ReallocOperatorSnapshotBuilder, ReallocWeightTableBuilder, RegisterMintBuilder, + RouteBaseRewardsBuilder, RouteNcnRewardsBuilder, SetConfigFeesBuilder, + SetMerkleRootBuilder, SetNewAdminBuilder, SetTieBreakerBuilder, + SetTrackedMintNcnFeeGroupBuilder, SnapshotVaultOperatorDelegationBuilder, }, types::ConfigAdminRole, }; @@ -22,6 +23,7 @@ use jito_tip_router_core::{ ballot_box::BallotBox, base_fee_group::BaseFeeGroup, base_reward_router::BaseRewardRouter, + constants::MAX_REALLOC_BYTES, epoch_snapshot::{EpochSnapshot, OperatorSnapshot}, error::TipRouterError, ncn_config::NcnConfig, @@ -41,6 +43,7 @@ use solana_program_test::{BanksClient, ProgramTestBanksClientExt}; use solana_sdk::{ clock::Clock, commitment_config::CommitmentLevel, + compute_budget::ComputeBudgetInstruction, signature::{Keypair, Signer}, system_program, transaction::{Transaction, TransactionError}, @@ -307,7 +310,7 @@ impl TipRouterClient { new_base_fee_bps, ncn_fee_group, new_ncn_fee_bps, - &ncn_root, + ncn_root, ) .await } @@ -410,28 +413,28 @@ impl TipRouterClient { .await } - pub async fn do_initialize_weight_table( + pub async fn do_full_initialize_weight_table( &mut self, ncn: Pubkey, - current_slot: u64, + epoch: u64, ) -> TestResult<()> { - self.initialize_weight_table(ncn, current_slot).await + self.do_initialize_weight_table(ncn, epoch).await?; + let num_reallocs = (WeightTable::SIZE as f64 / MAX_REALLOC_BYTES as f64).ceil() as u64 - 1; + self.do_realloc_weight_table(ncn, epoch, num_reallocs) + .await?; + Ok(()) } - pub async fn initialize_weight_table( - &mut self, - ncn: Pubkey, - current_slot: u64, - ) -> TestResult<()> { - let restaking_config = Config::find_program_address(&jito_restaking_program::id()).0; - - let restaking_config_account = self.get_restaking_config().await?; - let ncn_epoch = current_slot / restaking_config_account.epoch_length(); + pub async fn do_initialize_weight_table(&mut self, ncn: Pubkey, epoch: u64) -> TestResult<()> { + self.initialize_weight_table(ncn, epoch).await + } + pub async fn initialize_weight_table(&mut self, ncn: Pubkey, epoch: u64) -> TestResult<()> { + let restaking_config = Config::find_program_address(&jito_restaking_program::id()).0; let tracked_mints_pda = TrackedMints::find_program_address(&jito_tip_router_program::id(), &ncn).0; let weight_table = - WeightTable::find_program_address(&jito_tip_router_program::id(), &ncn, ncn_epoch).0; + WeightTable::find_program_address(&jito_tip_router_program::id(), &ncn, epoch).0; let ix = InitializeWeightTableBuilder::new() .restaking_config(restaking_config) @@ -441,6 +444,7 @@ impl TipRouterClient { .payer(self.payer.pubkey()) .restaking_program(jito_restaking_program::id()) .system_program(system_program::id()) + .epoch(epoch) .instruction(); let blockhash = self.banks_client.get_latest_blockhash().await?; @@ -456,26 +460,23 @@ impl TipRouterClient { pub async fn do_admin_update_weight_table( &mut self, ncn: Pubkey, - current_slot: u64, + epoch: u64, mint: Pubkey, weight: u128, ) -> TestResult<()> { - self.admin_update_weight_table(ncn, current_slot, mint, weight) + self.admin_update_weight_table(ncn, epoch, mint, weight) .await } pub async fn admin_update_weight_table( &mut self, ncn: Pubkey, - current_slot: u64, + epoch: u64, mint: Pubkey, weight: u128, ) -> TestResult<()> { - let restaking_config_account = self.get_restaking_config().await?; - let ncn_epoch = current_slot / restaking_config_account.epoch_length(); - let weight_table = - WeightTable::find_program_address(&jito_tip_router_program::id(), &ncn, ncn_epoch).0; + WeightTable::find_program_address(&jito_tip_router_program::id(), &ncn, epoch).0; let ix = AdminUpdateWeightTableBuilder::new() .ncn(ncn) @@ -484,7 +485,7 @@ impl TipRouterClient { .mint(mint) .restaking_program(jito_restaking_program::id()) .weight(weight) - .ncn_epoch(ncn_epoch) + .ncn_epoch(epoch) .instruction(); let blockhash = self.banks_client.get_latest_blockhash().await?; @@ -542,11 +543,9 @@ impl TipRouterClient { let tracked_mints = TrackedMints::find_program_address(&jito_tip_router_program::id(), &ncn).0; - let restaking_config = self.get_restaking_config().await?; - let current_slot = self.banks_client.get_sysvar::().await?.slot; - let ncn_epoch = current_slot / restaking_config.epoch_length(); + let epoch = self.banks_client.get_sysvar::().await?.epoch; let weight_table = - WeightTable::find_program_address(&jito_tip_router_program::id(), &ncn, ncn_epoch).0; + WeightTable::find_program_address(&jito_tip_router_program::id(), &ncn, epoch).0; self.register_mint( restaking_config_address, @@ -597,9 +596,9 @@ impl TipRouterClient { ncn: Pubkey, vault_index: u64, ncn_fee_group: NcnFeeGroup, - slot: u64, + epoch: u64, ) -> TestResult<()> { - self.set_tracked_mint_ncn_fee_group(ncn, vault_index, ncn_fee_group, slot) + self.set_tracked_mint_ncn_fee_group(ncn, vault_index, ncn_fee_group, epoch) .await } @@ -608,18 +607,15 @@ impl TipRouterClient { ncn: Pubkey, vault_index: u64, ncn_fee_group: NcnFeeGroup, - slot: u64, + epoch: u64, ) -> TestResult<()> { let restaking_config = Config::find_program_address(&jito_restaking_program::id()).0; - let restaking_config_account = self.get_restaking_config().await?; - let ncn_epoch = slot / restaking_config_account.epoch_length(); - let tracked_mints = TrackedMints::find_program_address(&jito_tip_router_program::id(), &ncn).0; let weight_table = - WeightTable::find_program_address(&jito_tip_router_program::id(), &ncn, ncn_epoch).0; + WeightTable::find_program_address(&jito_tip_router_program::id(), &ncn, epoch).0; let (ncn_config, _, _) = NcnConfig::find_program_address(&jito_tip_router_program::id(), &ncn); @@ -649,24 +645,23 @@ impl TipRouterClient { .await } - pub async fn do_initialize_epoch_snapshot(&mut self, ncn: Pubkey, slot: u64) -> TestResult<()> { - self.initialize_epoch_snapshot(ncn, slot).await + pub async fn do_initialize_epoch_snapshot( + &mut self, + ncn: Pubkey, + epoch: u64, + ) -> TestResult<()> { + self.initialize_epoch_snapshot(ncn, epoch).await } - pub async fn initialize_epoch_snapshot(&mut self, ncn: Pubkey, slot: u64) -> TestResult<()> { + pub async fn initialize_epoch_snapshot(&mut self, ncn: Pubkey, epoch: u64) -> TestResult<()> { let restaking_config = Config::find_program_address(&jito_restaking_program::id()).0; - - let restaking_config_account = self.get_restaking_config().await?; - let ncn_epoch = slot / restaking_config_account.epoch_length(); - let config_pda = NcnConfig::find_program_address(&jito_tip_router_program::id(), &ncn).0; let tracked_mints = TrackedMints::find_program_address(&jito_tip_router_program::id(), &ncn).0; let weight_table = - WeightTable::find_program_address(&jito_tip_router_program::id(), &ncn, ncn_epoch).0; - + WeightTable::find_program_address(&jito_tip_router_program::id(), &ncn, epoch).0; let epoch_snapshot = - EpochSnapshot::find_program_address(&jito_tip_router_program::id(), &ncn, ncn_epoch).0; + EpochSnapshot::find_program_address(&jito_tip_router_program::id(), &ncn, epoch).0; let ix = InitializeEpochSnapshotBuilder::new() .ncn_config(config_pda) @@ -678,7 +673,7 @@ impl TipRouterClient { .payer(self.payer.pubkey()) .restaking_program(jito_restaking_program::id()) .system_program(system_program::id()) - .first_slot_of_ncn_epoch(slot) + .epoch(epoch) .instruction(); let blockhash = self.banks_client.get_latest_blockhash().await?; @@ -691,40 +686,49 @@ impl TipRouterClient { .await } + pub async fn do_full_initialize_operator_snapshot( + &mut self, + operator: Pubkey, + ncn: Pubkey, + epoch: u64, + ) -> TestResult<()> { + self.do_initialize_operator_snapshot(operator, ncn, epoch) + .await?; + let num_reallocs = + (OperatorSnapshot::SIZE as f64 / MAX_REALLOC_BYTES as f64).ceil() as u64 - 1; + self.do_realloc_operator_snapshot(operator, ncn, epoch, num_reallocs) + .await?; + Ok(()) + } + pub async fn do_initialize_operator_snapshot( &mut self, operator: Pubkey, ncn: Pubkey, - slot: u64, + epoch: u64, ) -> TestResult<()> { - self.initialize_operator_snapshot(operator, ncn, slot).await + self.initialize_operator_snapshot(operator, ncn, epoch) + .await } pub async fn initialize_operator_snapshot( &mut self, operator: Pubkey, ncn: Pubkey, - slot: u64, + epoch: u64, ) -> TestResult<()> { let restaking_config = Config::find_program_address(&jito_restaking_program::id()).0; - - let restaking_config_account = self.get_restaking_config().await?; - let ncn_epoch = slot / restaking_config_account.epoch_length(); - let config_pda = NcnConfig::find_program_address(&jito_tip_router_program::id(), &ncn).0; - let ncn_operator_state = NcnOperatorState::find_program_address(&jito_restaking_program::id(), &ncn, &operator) .0; - let epoch_snapshot = - EpochSnapshot::find_program_address(&jito_tip_router_program::id(), &ncn, ncn_epoch).0; - + EpochSnapshot::find_program_address(&jito_tip_router_program::id(), &ncn, epoch).0; let operator_snapshot = OperatorSnapshot::find_program_address( &jito_tip_router_program::id(), &operator, &ncn, - ncn_epoch, + epoch, ) .0; @@ -739,7 +743,7 @@ impl TipRouterClient { .payer(self.payer.pubkey()) .restaking_program(jito_restaking_program::id()) .system_program(system_program::id()) - .first_slot_of_ncn_epoch(slot) + .epoch(epoch) .instruction(); let blockhash = self.banks_client.get_latest_blockhash().await?; @@ -757,9 +761,9 @@ impl TipRouterClient { vault: Pubkey, operator: Pubkey, ncn: Pubkey, - slot: u64, + epoch: u64, ) -> TestResult<()> { - self.snapshot_vault_operator_delegation(vault, operator, ncn, slot) + self.snapshot_vault_operator_delegation(vault, operator, ncn, epoch) .await } @@ -768,23 +772,19 @@ impl TipRouterClient { vault: Pubkey, operator: Pubkey, ncn: Pubkey, - slot: u64, + epoch: u64, ) -> TestResult<()> { let restaking_config = Config::find_program_address(&jito_restaking_program::id()).0; - let restaking_config_account = self.get_restaking_config().await?; - let ncn_epoch = slot / restaking_config_account.epoch_length(); - let config_pda = NcnConfig::find_program_address(&jito_tip_router_program::id(), &ncn).0; let epoch_snapshot = - EpochSnapshot::find_program_address(&jito_tip_router_program::id(), &ncn, ncn_epoch).0; - + EpochSnapshot::find_program_address(&jito_tip_router_program::id(), &ncn, epoch).0; let operator_snapshot = OperatorSnapshot::find_program_address( &jito_tip_router_program::id(), &operator, &ncn, - ncn_epoch, + epoch, ) .0; @@ -802,7 +802,7 @@ impl TipRouterClient { .0; let weight_table = - WeightTable::find_program_address(&jito_tip_router_program::id(), &ncn, ncn_epoch).0; + WeightTable::find_program_address(&jito_tip_router_program::id(), &ncn, epoch).0; let tracked_mints = TrackedMints::find_program_address(&jito_tip_router_program::id(), &ncn).0; @@ -822,7 +822,7 @@ impl TipRouterClient { .operator_snapshot(operator_snapshot) .vault_program(jito_vault_program::id()) .restaking_program(jito_restaking_program::id()) - .first_slot_of_ncn_epoch(slot) + .epoch(epoch) .instruction(); let blockhash = self.banks_client.get_latest_blockhash().await?; @@ -835,10 +835,21 @@ impl TipRouterClient { .await } + pub async fn do_full_initialize_ballot_box( + &mut self, + ncn: Pubkey, + epoch: u64, + ) -> TestResult<()> { + self.do_initialize_ballot_box(ncn, epoch).await?; + let num_reallocs = (BallotBox::SIZE as f64 / MAX_REALLOC_BYTES as f64).ceil() as u64 - 1; + self.do_realloc_ballot_box(ncn, epoch, num_reallocs).await?; + Ok(()) + } + pub async fn do_initialize_ballot_box( &mut self, ncn: Pubkey, - ncn_epoch: u64, + epoch: u64, ) -> Result<(), TestError> { let ncn_config = jito_tip_router_core::ncn_config::NcnConfig::find_program_address( &jito_tip_router_program::id(), @@ -849,11 +860,11 @@ impl TipRouterClient { let ballot_box = jito_tip_router_core::ballot_box::BallotBox::find_program_address( &jito_tip_router_program::id(), &ncn, - ncn_epoch, + epoch, ) .0; - self.initialize_ballot_box(ncn_config, ballot_box, ncn, ncn_epoch) + self.initialize_ballot_box(ncn_config, ballot_box, ncn, epoch) .await } @@ -882,13 +893,64 @@ impl TipRouterClient { .await } + pub async fn do_realloc_ballot_box( + &mut self, + ncn: Pubkey, + epoch: u64, + num_reallocations: u64, + ) -> Result<(), TestError> { + let ncn_config = jito_tip_router_core::ncn_config::NcnConfig::find_program_address( + &jito_tip_router_program::id(), + &ncn, + ) + .0; + + let ballot_box = jito_tip_router_core::ballot_box::BallotBox::find_program_address( + &jito_tip_router_program::id(), + &ncn, + epoch, + ) + .0; + + self.realloc_ballot_box(ncn_config, ballot_box, ncn, epoch, num_reallocations) + .await + } + + pub async fn realloc_ballot_box( + &mut self, + ncn_config: Pubkey, + ballot_box: Pubkey, + ncn: Pubkey, + epoch: u64, + num_reallocations: u64, + ) -> Result<(), TestError> { + let ix = ReallocBallotBoxBuilder::new() + .ncn_config(ncn_config) + .ballot_box(ballot_box) + .ncn(ncn) + .epoch(epoch) + .payer(self.payer.pubkey()) + .instruction(); + + let ixs = vec![ix; num_reallocations as usize]; + + let blockhash = self.banks_client.get_latest_blockhash().await?; + self.process_transaction(&Transaction::new_signed_with_payer( + &ixs, + Some(&self.payer.pubkey()), + &[&self.payer], + blockhash, + )) + .await + } + pub async fn do_cast_vote( &mut self, ncn: Pubkey, operator: Pubkey, operator_admin: &Keypair, meta_merkle_root: [u8; 32], - ncn_epoch: u64, + epoch: u64, ) -> Result<(), TestError> { let ncn_config = jito_tip_router_core::ncn_config::NcnConfig::find_program_address( &jito_tip_router_program::id(), @@ -899,7 +961,7 @@ impl TipRouterClient { let ballot_box = jito_tip_router_core::ballot_box::BallotBox::find_program_address( &jito_tip_router_program::id(), &ncn, - ncn_epoch, + epoch, ) .0; @@ -907,7 +969,7 @@ impl TipRouterClient { jito_tip_router_core::epoch_snapshot::EpochSnapshot::find_program_address( &jito_tip_router_program::id(), &ncn, - ncn_epoch, + epoch, ) .0; @@ -916,7 +978,7 @@ impl TipRouterClient { &jito_tip_router_program::id(), &operator, &ncn, - ncn_epoch, + epoch, ) .0; @@ -929,7 +991,7 @@ impl TipRouterClient { operator, operator_admin, meta_merkle_root, - ncn_epoch, + epoch, ) .await } @@ -1119,20 +1181,30 @@ impl TipRouterClient { .await } + pub async fn do_full_initialize_base_reward_router( + &mut self, + ncn: Pubkey, + epoch: u64, + ) -> TestResult<()> { + self.do_initialize_base_reward_router(ncn, epoch).await?; + let num_reallocs = + (BaseRewardRouter::SIZE as f64 / MAX_REALLOC_BYTES as f64).ceil() as u64 - 1; + self.do_realloc_base_reward_router(ncn, epoch, num_reallocs) + .await?; + Ok(()) + } + pub async fn do_initialize_base_reward_router( &mut self, ncn: Pubkey, - slot: u64, + epoch: u64, ) -> TestResult<()> { let restaking_config = Config::find_program_address(&jito_restaking_program::id()).0; - let restaking_config_account = self.get_restaking_config().await?; - let ncn_epoch = slot / restaking_config_account.epoch_length(); - let (base_reward_router, _, _) = - BaseRewardRouter::find_program_address(&jito_tip_router_program::id(), &ncn, ncn_epoch); + BaseRewardRouter::find_program_address(&jito_tip_router_program::id(), &ncn, epoch); - self.initialize_base_reward_router(restaking_config, ncn, base_reward_router) + self.initialize_base_reward_router(restaking_config, ncn, base_reward_router, epoch) .await } @@ -1141,6 +1213,7 @@ impl TipRouterClient { restaking_config: Pubkey, ncn: Pubkey, base_reward_router: Pubkey, + epoch: u64, ) -> TestResult<()> { let ix = InitializeBaseRewardRouterBuilder::new() .restaking_config(restaking_config) @@ -1149,6 +1222,7 @@ impl TipRouterClient { .payer(self.payer.pubkey()) .restaking_program(jito_restaking_program::id()) .system_program(system_program::id()) + .epoch(epoch) .instruction(); let blockhash = self.banks_client.get_latest_blockhash().await?; @@ -1166,19 +1240,16 @@ impl TipRouterClient { ncn_fee_group: NcnFeeGroup, ncn: Pubkey, operator: Pubkey, - slot: u64, + epoch: u64, ) -> TestResult<()> { let restaking_config = Config::find_program_address(&jito_restaking_program::id()).0; - let restaking_config_account = self.get_restaking_config().await?; - let ncn_epoch = slot / restaking_config_account.epoch_length(); - let (ncn_reward_router, _, _) = NcnRewardRouter::find_program_address( &jito_tip_router_program::id(), ncn_fee_group, &operator, &ncn, - ncn_epoch, + epoch, ); self.initialize_ncn_reward_router( @@ -1187,6 +1258,7 @@ impl TipRouterClient { operator, restaking_config, ncn_reward_router, + epoch, ) .await } @@ -1198,6 +1270,7 @@ impl TipRouterClient { operator: Pubkey, restaking_config: Pubkey, ncn_reward_router: Pubkey, + epoch: u64, ) -> TestResult<()> { let ix = InitializeNcnRewardRouterBuilder::new() .restaking_config(restaking_config) @@ -1208,6 +1281,7 @@ impl TipRouterClient { .restaking_program(jito_restaking_program::id()) .system_program(system_program::id()) .ncn_fee_group(ncn_fee_group.group) + .epoch(epoch) .instruction(); let blockhash = self.banks_client.get_latest_blockhash().await?; @@ -1220,20 +1294,17 @@ impl TipRouterClient { .await } - pub async fn do_route_base_rewards(&mut self, ncn: Pubkey, slot: u64) -> TestResult<()> { + pub async fn do_route_base_rewards(&mut self, ncn: Pubkey, epoch: u64) -> TestResult<()> { let restaking_config = Config::find_program_address(&jito_restaking_program::id()).0; - let restaking_config_account = self.get_restaking_config().await?; - let ncn_epoch = slot / restaking_config_account.epoch_length(); - let (epoch_snapshot, _, _) = - EpochSnapshot::find_program_address(&jito_tip_router_program::id(), &ncn, ncn_epoch); + EpochSnapshot::find_program_address(&jito_tip_router_program::id(), &ncn, epoch); let (ballot_box, _, _) = - BallotBox::find_program_address(&jito_tip_router_program::id(), &ncn, ncn_epoch); + BallotBox::find_program_address(&jito_tip_router_program::id(), &ncn, epoch); let (base_reward_router, _, _) = - BaseRewardRouter::find_program_address(&jito_tip_router_program::id(), &ncn, ncn_epoch); + BaseRewardRouter::find_program_address(&jito_tip_router_program::id(), &ncn, epoch); self.route_base_rewards( ncn, @@ -1241,6 +1312,7 @@ impl TipRouterClient { epoch_snapshot, ballot_box, base_reward_router, + epoch, ) .await } @@ -1252,6 +1324,7 @@ impl TipRouterClient { epoch_snapshot: Pubkey, ballot_box: Pubkey, base_reward_router: Pubkey, + epoch: u64, ) -> TestResult<()> { let ix = RouteBaseRewardsBuilder::new() .restaking_config(restaking_config) @@ -1260,11 +1333,15 @@ impl TipRouterClient { .ballot_box(ballot_box) .base_reward_router(base_reward_router) .restaking_program(jito_restaking_program::id()) + .epoch(epoch) .instruction(); let blockhash = self.banks_client.get_latest_blockhash().await?; self.process_transaction(&Transaction::new_signed_with_payer( - &[ix], + &[ + ComputeBudgetInstruction::set_compute_unit_limit(1_400_000), + ix, + ], Some(&self.payer.pubkey()), &[&self.payer], blockhash, @@ -1277,18 +1354,15 @@ impl TipRouterClient { ncn_fee_group: NcnFeeGroup, ncn: Pubkey, operator: Pubkey, - slot: u64, + epoch: u64, ) -> TestResult<()> { let restaking_config = Config::find_program_address(&jito_restaking_program::id()).0; - let restaking_config_account = self.get_restaking_config().await?; - let ncn_epoch = slot / restaking_config_account.epoch_length(); - let (operator_snapshot, _, _) = OperatorSnapshot::find_program_address( &jito_tip_router_program::id(), &operator, &ncn, - ncn_epoch, + epoch, ); let (ncn_reward_router, _, _) = NcnRewardRouter::find_program_address( @@ -1296,7 +1370,7 @@ impl TipRouterClient { ncn_fee_group, &operator, &ncn, - ncn_epoch, + epoch, ); self.route_ncn_rewards( @@ -1306,6 +1380,7 @@ impl TipRouterClient { restaking_config, operator_snapshot, ncn_reward_router, + epoch, ) .await } @@ -1318,6 +1393,7 @@ impl TipRouterClient { restaking_config: Pubkey, operator_snapshot: Pubkey, ncn_reward_router: Pubkey, + epoch: u64, ) -> TestResult<()> { let ix = RouteNcnRewardsBuilder::new() .restaking_config(restaking_config) @@ -1327,11 +1403,16 @@ impl TipRouterClient { .ncn_reward_router(ncn_reward_router) .restaking_program(jito_restaking_program::id()) .ncn_fee_group(ncn_fee_group.group) + .epoch(epoch) .instruction(); let blockhash = self.banks_client.get_latest_blockhash().await?; self.process_transaction(&Transaction::new_signed_with_payer( - &[ix], + &[ + // TODO: should make this instruction much more efficient + ComputeBudgetInstruction::set_compute_unit_limit(1_400_000), + ix, + ], Some(&self.payer.pubkey()), &[&self.payer], blockhash, @@ -1343,18 +1424,15 @@ impl TipRouterClient { &mut self, base_fee_group: BaseFeeGroup, ncn: Pubkey, - slot: u64, + epoch: u64, ) -> TestResult<()> { let restaking_config = Config::find_program_address(&jito_restaking_program::id()).0; - let restaking_config_account = self.get_restaking_config().await?; - let ncn_epoch = slot / restaking_config_account.epoch_length(); - let (ncn_config, _, _) = NcnConfig::find_program_address(&jito_tip_router_program::id(), &ncn); let (base_reward_router, _, _) = - BaseRewardRouter::find_program_address(&jito_tip_router_program::id(), &ncn, ncn_epoch); + BaseRewardRouter::find_program_address(&jito_tip_router_program::id(), &ncn, epoch); let ncn_config_account = self.get_ncn_config(ncn).await?; let base_fee_wallet = ncn_config_account @@ -1369,6 +1447,7 @@ impl TipRouterClient { ncn_config, base_reward_router, base_fee_wallet, + epoch, ) .await } @@ -1381,6 +1460,7 @@ impl TipRouterClient { ncn_config: Pubkey, base_reward_router: Pubkey, base_fee_wallet: Pubkey, + epoch: u64, ) -> TestResult<()> { let ix = DistributeBaseRewardsBuilder::new() .restaking_config(restaking_config) @@ -1390,6 +1470,7 @@ impl TipRouterClient { .base_fee_wallet(base_fee_wallet) .restaking_program(jito_restaking_program::id()) .base_fee_group(base_fee_group.group) + .epoch(epoch) .instruction(); let blockhash = self.banks_client.get_latest_blockhash().await?; @@ -1407,25 +1488,22 @@ impl TipRouterClient { ncn_fee_group: NcnFeeGroup, operator: Pubkey, ncn: Pubkey, - slot: u64, + epoch: u64, ) -> TestResult<()> { let restaking_config = Config::find_program_address(&jito_restaking_program::id()).0; - let restaking_config_account = self.get_restaking_config().await?; - let ncn_epoch = slot / restaking_config_account.epoch_length(); - let (ncn_config, _, _) = NcnConfig::find_program_address(&jito_tip_router_program::id(), &ncn); let (base_reward_router, _, _) = - BaseRewardRouter::find_program_address(&jito_tip_router_program::id(), &ncn, ncn_epoch); + BaseRewardRouter::find_program_address(&jito_tip_router_program::id(), &ncn, epoch); let (ncn_reward_router, _, _) = NcnRewardRouter::find_program_address( &jito_tip_router_program::id(), ncn_fee_group, &operator, &ncn, - ncn_epoch, + epoch, ); self.distribute_base_ncn_reward_route( @@ -1436,6 +1514,7 @@ impl TipRouterClient { ncn_config, base_reward_router, ncn_reward_router, + epoch, ) .await } @@ -1449,6 +1528,7 @@ impl TipRouterClient { ncn_config: Pubkey, base_reward_router: Pubkey, ncn_reward_router: Pubkey, + epoch: u64, ) -> TestResult<()> { let ix = DistributeBaseNcnRewardRouteBuilder::new() .restaking_config(restaking_config) @@ -1459,6 +1539,7 @@ impl TipRouterClient { .ncn_reward_router(ncn_reward_router) .restaking_program(jito_restaking_program::id()) .ncn_fee_group(ncn_fee_group.group) + .epoch(epoch) .instruction(); let blockhash = self.banks_client.get_latest_blockhash().await?; @@ -1476,13 +1557,10 @@ impl TipRouterClient { ncn_fee_group: NcnFeeGroup, operator: Pubkey, ncn: Pubkey, - slot: u64, + epoch: u64, ) -> TestResult<()> { let restaking_config = Config::find_program_address(&jito_restaking_program::id()).0; - let restaking_config_account = self.get_restaking_config().await?; - let ncn_epoch = slot / restaking_config_account.epoch_length(); - let (ncn_config, _, _) = NcnConfig::find_program_address(&jito_tip_router_program::id(), &ncn); @@ -1491,7 +1569,7 @@ impl TipRouterClient { ncn_fee_group, &operator, &ncn, - ncn_epoch, + epoch, ); self.distribute_ncn_operator_rewards( @@ -1501,6 +1579,7 @@ impl TipRouterClient { restaking_config, ncn_config, ncn_reward_router, + epoch, ) .await } @@ -1513,6 +1592,7 @@ impl TipRouterClient { restaking_config: Pubkey, ncn_config: Pubkey, ncn_reward_router: Pubkey, + epoch: u64, ) -> TestResult<()> { let ix = DistributeNcnOperatorRewardsBuilder::new() .restaking_config(restaking_config) @@ -1522,6 +1602,7 @@ impl TipRouterClient { .ncn_reward_router(ncn_reward_router) .restaking_program(jito_restaking_program::id()) .ncn_fee_group(ncn_fee_group.group) + .epoch(epoch) .instruction(); let blockhash = self.banks_client.get_latest_blockhash().await?; @@ -1540,13 +1621,10 @@ impl TipRouterClient { vault: Pubkey, operator: Pubkey, ncn: Pubkey, - slot: u64, + epoch: u64, ) -> TestResult<()> { let restaking_config = Config::find_program_address(&jito_restaking_program::id()).0; - let restaking_config_account = self.get_restaking_config().await?; - let ncn_epoch = slot / restaking_config_account.epoch_length(); - let (ncn_config, _, _) = NcnConfig::find_program_address(&jito_tip_router_program::id(), &ncn); @@ -1555,7 +1633,7 @@ impl TipRouterClient { ncn_fee_group, &operator, &ncn, - ncn_epoch, + epoch, ); self.distribute_ncn_vault_rewards( @@ -1566,6 +1644,7 @@ impl TipRouterClient { restaking_config, ncn_config, ncn_reward_router, + epoch, ) .await } @@ -1579,6 +1658,7 @@ impl TipRouterClient { restaking_config: Pubkey, ncn_config: Pubkey, ncn_reward_router: Pubkey, + epoch: u64, ) -> TestResult<()> { let ix = DistributeNcnVaultRewardsBuilder::new() .restaking_config(restaking_config) @@ -1588,6 +1668,7 @@ impl TipRouterClient { .vault(vault) .ncn_reward_router(ncn_reward_router) .ncn_fee_group(ncn_fee_group.group) + .epoch(epoch) .instruction(); let blockhash = self.banks_client.get_latest_blockhash().await?; @@ -1599,6 +1680,182 @@ impl TipRouterClient { )) .await } + pub async fn do_realloc_operator_snapshot( + &mut self, + operator: Pubkey, + ncn: Pubkey, + epoch: u64, + num_reallocations: u64, + ) -> Result<(), TestError> { + let ncn_config = NcnConfig::find_program_address(&jito_tip_router_program::id(), &ncn).0; + let restaking_config = Config::find_program_address(&jito_restaking_program::id()).0; + let ncn_operator_state = + NcnOperatorState::find_program_address(&jito_restaking_program::id(), &ncn, &operator) + .0; + let epoch_snapshot = + EpochSnapshot::find_program_address(&jito_tip_router_program::id(), &ncn, epoch).0; + let operator_snapshot = OperatorSnapshot::find_program_address( + &jito_tip_router_program::id(), + &operator, + &ncn, + epoch, + ) + .0; + + self.realloc_operator_snapshot( + ncn_config, + restaking_config, + ncn, + operator, + ncn_operator_state, + epoch_snapshot, + operator_snapshot, + epoch, + num_reallocations, + ) + .await + } + + pub async fn realloc_operator_snapshot( + &mut self, + ncn_config: Pubkey, + restaking_config: Pubkey, + ncn: Pubkey, + operator: Pubkey, + ncn_operator_state: Pubkey, + epoch_snapshot: Pubkey, + operator_snapshot: Pubkey, + epoch: u64, + num_reallocations: u64, + ) -> Result<(), TestError> { + let ix = ReallocOperatorSnapshotBuilder::new() + .ncn_config(ncn_config) + .restaking_config(restaking_config) + .ncn(ncn) + .operator(operator) + .ncn_operator_state(ncn_operator_state) + .epoch_snapshot(epoch_snapshot) + .operator_snapshot(operator_snapshot) + .payer(self.payer.pubkey()) + .restaking_program(jito_restaking_program::id()) + .system_program(system_program::id()) + .epoch(epoch) + .instruction(); + + let ixs = vec![ix; num_reallocations as usize]; + + let blockhash = self.banks_client.get_latest_blockhash().await?; + self.process_transaction(&Transaction::new_signed_with_payer( + &ixs, + Some(&self.payer.pubkey()), + &[&self.payer], + blockhash, + )) + .await + } + + pub async fn do_realloc_base_reward_router( + &mut self, + ncn: Pubkey, + epoch: u64, + num_reallocations: u64, + ) -> Result<(), TestError> { + let ncn_config = NcnConfig::find_program_address(&jito_tip_router_program::id(), &ncn).0; + let base_reward_router = + BaseRewardRouter::find_program_address(&jito_tip_router_program::id(), &ncn, epoch).0; + + self.realloc_base_reward_router( + ncn_config, + base_reward_router, + ncn, + epoch, + num_reallocations, + ) + .await + } + + pub async fn realloc_base_reward_router( + &mut self, + ncn_config: Pubkey, + base_reward_router: Pubkey, + ncn: Pubkey, + epoch: u64, + num_reallocations: u64, + ) -> Result<(), TestError> { + let ix = ReallocBaseRewardRouterBuilder::new() + .ncn_config(ncn_config) + .base_reward_router(base_reward_router) + .ncn(ncn) + .epoch(epoch) + .payer(self.payer.pubkey()) + .system_program(system_program::id()) + .instruction(); + + let ixs = vec![ix; num_reallocations as usize]; + + let blockhash = self.banks_client.get_latest_blockhash().await?; + self.process_transaction(&Transaction::new_signed_with_payer( + &ixs, + Some(&self.payer.pubkey()), + &[&self.payer], + blockhash, + )) + .await + } + + pub async fn do_realloc_weight_table( + &mut self, + ncn: Pubkey, + epoch: u64, + num_reallocations: u64, + ) -> Result<(), TestError> { + let ncn_config = NcnConfig::find_program_address(&jito_tip_router_program::id(), &ncn).0; + let weight_table = + WeightTable::find_program_address(&jito_tip_router_program::id(), &ncn, epoch).0; + let tracked_mints = + TrackedMints::find_program_address(&jito_tip_router_program::id(), &ncn).0; + + self.realloc_weight_table( + ncn_config, + weight_table, + ncn, + tracked_mints, + epoch, + num_reallocations, + ) + .await + } + + pub async fn realloc_weight_table( + &mut self, + ncn_config: Pubkey, + weight_table: Pubkey, + ncn: Pubkey, + tracked_mints: Pubkey, + epoch: u64, + num_reallocations: u64, + ) -> Result<(), TestError> { + let ix = ReallocWeightTableBuilder::new() + .ncn_config(ncn_config) + .weight_table(weight_table) + .ncn(ncn) + .tracked_mints(tracked_mints) + .epoch(epoch) + .payer(self.payer.pubkey()) + .system_program(system_program::id()) + .instruction(); + + let ixs = vec![ix; num_reallocations as usize]; + + let blockhash = self.banks_client.get_latest_blockhash().await?; + self.process_transaction(&Transaction::new_signed_with_payer( + &ixs, + Some(&self.payer.pubkey()), + &[&self.payer], + blockhash, + )) + .await + } } #[inline(always)] diff --git a/integration_tests/tests/helpers/ballot_box.rs b/integration_tests/tests/helpers/ballot_box.rs index 38b8474..ff8ab31 100644 --- a/integration_tests/tests/helpers/ballot_box.rs +++ b/integration_tests/tests/helpers/ballot_box.rs @@ -8,13 +8,11 @@ pub fn serialized_ballot_box_account(ballot_box: &BallotBox) -> Account { data.extend_from_slice(&[0; 7]); data.extend_from_slice(bytemuck::bytes_of(ballot_box)); - let account = Account { + Account { lamports: LAMPORTS_PER_SOL * 5, data, owner: jito_tip_router_program::id(), executable: false, rent_epoch: 0, - }; - - account + } } diff --git a/integration_tests/tests/tip_router/admin_update_weight_table.rs b/integration_tests/tests/tip_router/admin_update_weight_table.rs index b3c472c..b7bf0b9 100644 --- a/integration_tests/tests/tip_router/admin_update_weight_table.rs +++ b/integration_tests/tests/tip_router/admin_update_weight_table.rs @@ -13,10 +13,11 @@ mod tests { fixture.warp_slot_incremental(1000).await?; - let slot = fixture.clock().await.slot; + let clock = fixture.clock().await; + let epoch = clock.epoch; tip_router_client - .do_initialize_weight_table(test_ncn.ncn_root.ncn_pubkey, slot) + .do_full_initialize_weight_table(test_ncn.ncn_root.ncn_pubkey, epoch) .await?; let vault_root = test_ncn.vaults[0].clone(); @@ -26,7 +27,7 @@ mod tests { let weight = 100; tip_router_client - .do_admin_update_weight_table(test_ncn.ncn_root.ncn_pubkey, slot, mint, weight) + .do_admin_update_weight_table(test_ncn.ncn_root.ncn_pubkey, epoch, mint, weight) .await?; Ok(()) diff --git a/integration_tests/tests/tip_router/bpf/set_merkle_root.rs b/integration_tests/tests/tip_router/bpf/set_merkle_root.rs index dbb5ed5..ad6a707 100644 --- a/integration_tests/tests/tip_router/bpf/set_merkle_root.rs +++ b/integration_tests/tests/tip_router/bpf/set_merkle_root.rs @@ -283,10 +283,8 @@ mod set_merkle_root { Ok(()) } - // TODO update to use this test once snapshot instructions work with BPF - #[ignore] #[tokio::test] - async fn _test_set_merkle_root_no_fixture() -> TestResult<()> { + async fn test_set_merkle_root_no_fixture() -> TestResult<()> { let mut fixture = TestBuilder::new().await; let mut tip_router_client = fixture.tip_router_client(); let mut tip_distribution_client = fixture.tip_distribution_client(); @@ -298,15 +296,12 @@ mod set_merkle_root { fixture.snapshot_test_ncn(&test_ncn).await?; let clock = fixture.clock().await; - let slot = clock.slot; - let restaking_config_account = tip_router_client.get_restaking_config().await?; - let ncn_epoch = slot / restaking_config_account.epoch_length(); + let epoch = clock.epoch; let ncn = test_ncn.ncn_root.ncn_pubkey; let ncn_config_address = NcnConfig::find_program_address(&jito_tip_router_program::id(), &ncn).0; - let epoch: u64 = 0; tip_distribution_client .do_initialize(ncn_config_address) .await?; @@ -314,12 +309,12 @@ mod set_merkle_root { let vote_account = vote_keypair.pubkey(); tip_distribution_client - .do_initialize_tip_distribution_account( - ncn_config_address, - vote_keypair, - ncn_epoch, - 100, - ) + .do_initialize_tip_distribution_account(ncn_config_address, vote_keypair, epoch, 100) + .await?; + + // Initialize ballot box + tip_router_client + .do_full_initialize_ballot_box(ncn, epoch) .await?; let meta_merkle_tree_fixture = @@ -330,7 +325,7 @@ mod set_merkle_root { let operator_admin = &test_ncn.operators[0].operator_admin; tip_router_client - .do_cast_vote(ncn, operator, operator_admin, winning_root, ncn_epoch) + .do_cast_vote(ncn, operator, operator_admin, winning_root, epoch) .await?; let tip_distribution_address = derive_tip_distribution_account_address( &jito_tip_distribution::ID, @@ -357,6 +352,12 @@ mod set_merkle_root { ) .unwrap(); + // Wait 1 slot before set merkle root + let epoch_schedule: EpochSchedule = fixture.epoch_schedule().await; + fixture + .warp_slot_incremental(epoch_schedule.get_slots_in_epoch(epoch)) + .await?; + // Invoke set_merkle_root tip_router_client .do_set_merkle_root( @@ -431,7 +432,7 @@ mod set_merkle_root { // Initialize ballot box tip_router_client - .do_initialize_ballot_box(ncn, ncn_epoch) + .do_full_initialize_ballot_box(ncn, ncn_epoch) .await?; // Try setting merkle root before consensus diff --git a/integration_tests/tests/tip_router/cast_vote.rs b/integration_tests/tests/tip_router/cast_vote.rs index a1c4eb4..327c7e9 100644 --- a/integration_tests/tests/tip_router/cast_vote.rs +++ b/integration_tests/tests/tip_router/cast_vote.rs @@ -21,11 +21,10 @@ mod tests { let slot = clock.slot; let ncn = test_ncn.ncn_root.ncn_pubkey; let operator = test_ncn.operators[0].operator_pubkey; - let restaking_config_account = tip_router_client.get_restaking_config().await?; - let ncn_epoch = slot / restaking_config_account.epoch_length(); + let epoch = clock.epoch; tip_router_client - .do_initialize_ballot_box(ncn, ncn_epoch) + .do_full_initialize_ballot_box(ncn, epoch) .await?; let meta_merkle_root = [1u8; 32]; @@ -33,10 +32,10 @@ mod tests { let operator_admin = &test_ncn.operators[0].operator_admin; tip_router_client - .do_cast_vote(ncn, operator, operator_admin, meta_merkle_root, ncn_epoch) + .do_cast_vote(ncn, operator, operator_admin, meta_merkle_root, epoch) .await?; - let ballot_box = tip_router_client.get_ballot_box(ncn, ncn_epoch).await?; + let ballot_box = tip_router_client.get_ballot_box(ncn, epoch).await?; assert!(ballot_box.has_ballot(&Ballot::new(meta_merkle_root))); assert_eq!(ballot_box.slot_consensus_reached(), slot); diff --git a/integration_tests/tests/tip_router/distribute_rewards.rs b/integration_tests/tests/tip_router/distribute_rewards.rs index 5e221dc..e575df9 100644 --- a/integration_tests/tests/tip_router/distribute_rewards.rs +++ b/integration_tests/tests/tip_router/distribute_rewards.rs @@ -55,13 +55,13 @@ mod tests { .await?; // Set tracked mint NCN fee group - let slot = fixture.clock().await.slot; + let epoch = fixture.clock().await.epoch; tip_router_client .do_set_tracked_mint_ncn_fee_group( test_ncn.ncn_root.ncn_pubkey, 1, NcnFeeGroup::new(NcnFeeGroupType::JTO), - slot, + epoch, ) .await?; @@ -73,16 +73,14 @@ mod tests { fixture.vote_test_ncn(&test_ncn).await?; ////// - let slot = fixture.clock().await.slot; let ncn = test_ncn.ncn_root.ncn_pubkey; // Initialize the routers fixture.add_routers_for_tests_ncn(&test_ncn).await?; // Get initial balances - let restaking_config_account = tip_router_client.get_restaking_config().await?; - let ncn_epoch = slot / restaking_config_account.epoch_length(); let ncn_config = tip_router_client.get_ncn_config(ncn).await?; + let epoch = fixture.clock().await.epoch; let dao_initial_balance = fixture .get_balance( @@ -111,7 +109,7 @@ mod tests { // Route in 3_000 lamports let (base_reward_router, _, _) = - BaseRewardRouter::find_program_address(&jito_tip_router_program::id(), &ncn, ncn_epoch); + BaseRewardRouter::find_program_address(&jito_tip_router_program::id(), &ncn, epoch); // Send rewards to base reward router let sol_rewards = lamports_to_sol(3_000); @@ -121,12 +119,11 @@ mod tests { .await?; // Route rewards - tip_router_client.do_route_base_rewards(ncn, slot).await?; + tip_router_client.do_route_base_rewards(ncn, epoch).await?; // Check Rewards - let base_reward_router_account = tip_router_client - .get_base_reward_router(ncn, ncn_epoch) - .await?; + let base_reward_router_account = + tip_router_client.get_base_reward_router(ncn, epoch).await?; let dao_rewards = base_reward_router_account .base_fee_group_reward(BaseFeeGroup::default()) @@ -161,7 +158,7 @@ mod tests { // Distribute base rewards (DAO fee) tip_router_client - .do_distribute_base_rewards(BaseFeeGroup::default(), ncn, slot) + .do_distribute_base_rewards(BaseFeeGroup::default(), ncn, epoch) .await?; // Distribute base NCN rewards (operator rewards) @@ -170,7 +167,7 @@ mod tests { for group in NcnFeeGroup::all_groups().iter() { tip_router_client - .do_distribute_base_ncn_reward_route(*group, operator, ncn, slot) + .do_distribute_base_ncn_reward_route(*group, operator, ncn, epoch) .await?; } } @@ -194,12 +191,12 @@ mod tests { let mut total_rewards = 0; for group in NcnFeeGroup::all_groups().iter() { tip_router_client - .do_route_ncn_rewards(*group, ncn, operator, slot) + .do_route_ncn_rewards(*group, ncn, operator, epoch) .await?; // Distribute to operators tip_router_client - .do_distribute_ncn_operator_rewards(*group, operator, ncn, slot) + .do_distribute_ncn_operator_rewards(*group, operator, ncn, epoch) .await?; // Distribute to vaults @@ -208,7 +205,7 @@ mod tests { { let ncn_reward_router = tip_router_client - .get_ncn_reward_router(*group, operator, ncn, ncn_epoch) + .get_ncn_reward_router(*group, operator, ncn, epoch) .await?; // Skip if the vault is not in the reward route @@ -217,16 +214,17 @@ mod tests { } tip_router_client - .do_distribute_ncn_vault_rewards(*group, vault, operator, ncn, slot) + .do_distribute_ncn_vault_rewards( + *group, vault, operator, ncn, epoch, + ) .await?; } } let ncn_router = tip_router_client - .get_ncn_reward_router(*group, operator, ncn, ncn_epoch) + .get_ncn_reward_router(*group, operator, ncn, epoch) .await?; - println!("\nTotal Rewards: {}", ncn_router.total_rewards()); total_rewards += ncn_router.total_rewards(); } @@ -246,7 +244,7 @@ mod tests { assert_eq!(dao_reward, 2_700); // NCN Reward Routes - assert_eq!(*operator_total_rewards.get(0).unwrap(), 150); + assert_eq!(*operator_total_rewards.first().unwrap(), 150); assert_eq!(*operator_total_rewards.get(1).unwrap(), 150); // Operator 1 Rewards diff --git a/integration_tests/tests/tip_router/initialize_ballot_box.rs b/integration_tests/tests/tip_router/initialize_ballot_box.rs index b6c06c6..1aa265f 100644 --- a/integration_tests/tests/tip_router/initialize_ballot_box.rs +++ b/integration_tests/tests/tip_router/initialize_ballot_box.rs @@ -1,7 +1,10 @@ #[cfg(test)] mod tests { - use jito_tip_router_core::constants::DEFAULT_CONSENSUS_REACHED_SLOT; + use jito_tip_router_core::{ + ballot_box::BallotBox, + constants::{DEFAULT_CONSENSUS_REACHED_SLOT, MAX_REALLOC_BYTES}, + }; use crate::fixtures::{test_builder::TestBuilder, TestResult}; @@ -18,10 +21,26 @@ mod tests { let ncn = test_ncn.ncn_root.ncn_pubkey; + let num_reallocs = (jito_tip_router_core::ballot_box::BallotBox::SIZE as f64 + / jito_tip_router_core::constants::MAX_REALLOC_BYTES as f64) + .ceil() as u64 + - 1; + tip_router_client .do_initialize_ballot_box(ncn, epoch) .await?; + let address = + BallotBox::find_program_address(&jito_tip_router_program::id(), &ncn, epoch).0; + let raw_account = fixture.get_account(&address).await?.unwrap(); + assert_eq!(raw_account.data.len(), MAX_REALLOC_BYTES as usize); + assert_eq!(raw_account.owner, jito_tip_router_program::id()); + assert_eq!(raw_account.data[0], 0); + + tip_router_client + .do_realloc_ballot_box(ncn, epoch, num_reallocs) + .await?; + let ballot_box = tip_router_client.get_ballot_box(ncn, epoch).await?; assert_eq!(ballot_box.epoch(), epoch); diff --git a/integration_tests/tests/tip_router/initialize_base_reward_router.rs b/integration_tests/tests/tip_router/initialize_base_reward_router.rs index 8806585..836b4b4 100644 --- a/integration_tests/tests/tip_router/initialize_base_reward_router.rs +++ b/integration_tests/tests/tip_router/initialize_base_reward_router.rs @@ -1,6 +1,10 @@ #[cfg(test)] mod tests { + use jito_tip_router_core::{ + base_reward_router::BaseRewardRouter, constants::MAX_REALLOC_BYTES, + }; + use crate::fixtures::{test_builder::TestBuilder, TestResult}; #[tokio::test] @@ -17,27 +21,41 @@ mod tests { fixture.vote_test_ncn(&test_ncn).await?; ////// - let slot = fixture.clock().await.slot; + let clock = fixture.clock().await; + let epoch = clock.epoch; + let slot = clock.slot; let ncn = test_ncn.ncn_root.ncn_pubkey; // Initialize base reward router tip_router_client - .do_initialize_base_reward_router(ncn, slot) + .do_initialize_base_reward_router(ncn, epoch) .await?; - // Get base reward router and verify it was initialized correctly - let restaking_config_account = tip_router_client.get_restaking_config().await?; - let ncn_epoch = slot / restaking_config_account.epoch_length(); - let base_reward_router = tip_router_client - .get_base_reward_router(ncn, ncn_epoch) + // Check initial size is MAX_REALLOC_BYTES + let address = + BaseRewardRouter::find_program_address(&jito_tip_router_program::id(), &ncn, epoch).0; + let raw_account = fixture.get_account(&address).await?.unwrap(); + assert_eq!(raw_account.data.len(), MAX_REALLOC_BYTES as usize); + assert_eq!(raw_account.owner, jito_tip_router_program::id()); + assert_eq!(raw_account.data[0], 0); + + // Calculate number of reallocs needed + let num_reallocs = + (BaseRewardRouter::SIZE as f64 / MAX_REALLOC_BYTES as f64).ceil() as u64 - 1; + + // Realloc to full size + tip_router_client + .do_realloc_base_reward_router(ncn, epoch, num_reallocs) .await?; + // Get base reward router and verify it was initialized correctly + let base_reward_router = tip_router_client.get_base_reward_router(ncn, epoch).await?; + // Verify initial state assert_eq!(base_reward_router.reward_pool(), 0); assert_eq!(base_reward_router.rewards_processed(), 0); assert_eq!(base_reward_router.total_rewards(), 0); assert_eq!(base_reward_router.ncn(), &ncn); - assert_eq!(base_reward_router.ncn_epoch(), ncn_epoch); assert_eq!(base_reward_router.slot_created(), slot); Ok(()) diff --git a/integration_tests/tests/tip_router/initialize_epoch_snapshot.rs b/integration_tests/tests/tip_router/initialize_epoch_snapshot.rs index 2a417c6..1d6e977 100644 --- a/integration_tests/tests/tip_router/initialize_epoch_snapshot.rs +++ b/integration_tests/tests/tip_router/initialize_epoch_snapshot.rs @@ -16,7 +16,7 @@ mod tests { let slot = fixture.clock().await.slot; tip_router_client - .do_initialize_weight_table(test_ncn.ncn_root.ncn_pubkey, slot) + .do_full_initialize_weight_table(test_ncn.ncn_root.ncn_pubkey, slot) .await?; let vault_root = test_ncn.vaults[0].clone(); diff --git a/integration_tests/tests/tip_router/initialize_ncn_reward_router.rs b/integration_tests/tests/tip_router/initialize_ncn_reward_router.rs index 828355b..9c057a5 100644 --- a/integration_tests/tests/tip_router/initialize_ncn_reward_router.rs +++ b/integration_tests/tests/tip_router/initialize_ncn_reward_router.rs @@ -20,27 +20,27 @@ mod tests { fixture.vote_test_ncn(&test_ncn).await?; ////// - let slot = fixture.clock().await.slot; + let clock = fixture.clock().await; + let slot = clock.slot; + let epoch = clock.epoch; let ncn = test_ncn.ncn_root.ncn_pubkey; let operator = test_ncn.operators[0].operator_pubkey; let ncn_fee_group = NcnFeeGroup::default(); // Initialize NCN reward router tip_router_client - .do_initialize_ncn_reward_router(ncn_fee_group, ncn, operator, slot) + .do_initialize_ncn_reward_router(ncn_fee_group, ncn, operator, epoch) .await?; // Get NCN reward router and verify initialization - let restaking_config_account = tip_router_client.get_restaking_config().await?; - let ncn_epoch = slot / restaking_config_account.epoch_length(); let ncn_reward_router = tip_router_client - .get_ncn_reward_router(ncn_fee_group, operator, ncn, ncn_epoch) + .get_ncn_reward_router(ncn_fee_group, operator, ncn, epoch) .await?; // Verify initial state assert_eq!(ncn_reward_router.ncn(), ncn); assert_eq!(ncn_reward_router.operator(), operator); - assert_eq!(ncn_reward_router.ncn_epoch(), ncn_epoch); + assert_eq!(ncn_reward_router.ncn_epoch(), epoch); assert_eq!(ncn_reward_router.slot_created(), slot); assert_eq!(ncn_reward_router.reward_pool(), 0); assert_eq!(ncn_reward_router.rewards_processed(), 0); diff --git a/integration_tests/tests/tip_router/initialize_operator_snapshot.rs b/integration_tests/tests/tip_router/initialize_operator_snapshot.rs index 989db81..8197953 100644 --- a/integration_tests/tests/tip_router/initialize_operator_snapshot.rs +++ b/integration_tests/tests/tip_router/initialize_operator_snapshot.rs @@ -1,46 +1,63 @@ #[cfg(test)] mod tests { + use jito_tip_router_core::{constants::MAX_REALLOC_BYTES, epoch_snapshot::OperatorSnapshot}; + use crate::fixtures::{test_builder::TestBuilder, TestResult}; #[tokio::test] async fn test_initialize_operator_snapshot() -> TestResult<()> { let mut fixture = TestBuilder::new().await; - let mut vault_client = fixture.vault_program_client(); let mut tip_router_client = fixture.tip_router_client(); let test_ncn = fixture.create_initial_test_ncn(1, 1, None).await?; fixture.warp_slot_incremental(1000).await?; - let slot = fixture.clock().await.slot; - - tip_router_client - .do_initialize_weight_table(test_ncn.ncn_root.ncn_pubkey, slot) - .await?; + fixture.add_weights_for_test_ncn(&test_ncn).await?; + fixture.add_epoch_snapshot_to_test_ncn(&test_ncn).await?; + let clock = fixture.clock().await; + let epoch = clock.epoch; let ncn = test_ncn.ncn_root.ncn_pubkey; + let operator = test_ncn.operators[0].operator_pubkey; - let vault_root = test_ncn.vaults[0].clone(); - let vault = vault_client.get_vault(&vault_root.vault_pubkey).await?; - - let mint = vault.supported_mint; - let weight = 100; - + // Initialize operator snapshot tip_router_client - .do_admin_update_weight_table(ncn, slot, mint, weight) + .do_initialize_operator_snapshot(operator, ncn, epoch) .await?; + // Check initial size is MAX_REALLOC_BYTES + let address = OperatorSnapshot::find_program_address( + &jito_tip_router_program::id(), + &operator, + &ncn, + epoch, + ) + .0; + let raw_account = fixture.get_account(&address).await?.unwrap(); + assert_eq!(raw_account.data.len(), MAX_REALLOC_BYTES as usize); + assert_eq!(raw_account.owner, jito_tip_router_program::id()); + assert_eq!(raw_account.data[0], 0); + + // Calculate number of reallocs needed + let num_reallocs = + (OperatorSnapshot::SIZE as f64 / MAX_REALLOC_BYTES as f64).ceil() as u64 - 1; + + // Realloc to full size tip_router_client - .do_initialize_epoch_snapshot(ncn, slot) + .do_realloc_operator_snapshot(operator, ncn, epoch, num_reallocs) .await?; - let operator = test_ncn.operators[0].operator_pubkey; - - tip_router_client - .do_initialize_operator_snapshot(operator, ncn, slot) + // Get operator snapshot and verify it was initialized correctly + let operator_snapshot = tip_router_client + .get_operator_snapshot(operator, ncn, epoch) .await?; + // Verify initial state + assert_eq!(operator_snapshot.operator(), operator); + assert_eq!(operator_snapshot.ncn(), ncn); + Ok(()) } } diff --git a/integration_tests/tests/tip_router/initialize_weight_table.rs b/integration_tests/tests/tip_router/initialize_weight_table.rs index 18a0e36..a5a09cf 100644 --- a/integration_tests/tests/tip_router/initialize_weight_table.rs +++ b/integration_tests/tests/tip_router/initialize_weight_table.rs @@ -1,5 +1,7 @@ #[cfg(test)] mod tests { + use jito_bytemuck::Discriminator; + use jito_tip_router_core::{constants::MAX_REALLOC_BYTES, weight_table::WeightTable}; use crate::fixtures::{test_builder::TestBuilder, TestResult}; @@ -12,12 +14,37 @@ mod tests { fixture.warp_slot_incremental(1000).await?; - let slot = fixture.clock().await.slot; + let clock = fixture.clock().await; + let epoch = clock.epoch; + let ncn = test_ncn.ncn_root.ncn_pubkey; tip_router_client - .do_initialize_weight_table(test_ncn.ncn_root.ncn_pubkey, slot) + .do_initialize_weight_table(ncn, epoch) .await?; + let address = + WeightTable::find_program_address(&jito_tip_router_program::id(), &ncn, epoch).0; + let raw_account = fixture.get_account(&address).await?.unwrap(); + assert_eq!(raw_account.data.len(), MAX_REALLOC_BYTES as usize); + assert_eq!(raw_account.owner, jito_tip_router_program::id()); + assert_eq!(raw_account.data[0], 0); + + let num_reallocs = (WeightTable::SIZE as f64 / MAX_REALLOC_BYTES as f64).ceil() as u64 - 1; + + tip_router_client + .do_realloc_weight_table(ncn, epoch, num_reallocs) + .await?; + + let raw_account = fixture.get_account(&address).await?.unwrap(); + assert_eq!(raw_account.data.len(), { WeightTable::SIZE }); + assert_eq!(raw_account.owner, jito_tip_router_program::id()); + assert_eq!(raw_account.data[0], WeightTable::DISCRIMINATOR); + + let weight_table = tip_router_client.get_weight_table(ncn, epoch).await?; + + assert_eq!(weight_table.ncn(), ncn); + assert_eq!(weight_table.ncn_epoch(), epoch); + Ok(()) } } diff --git a/integration_tests/tests/tip_router/meta_tests.rs b/integration_tests/tests/tip_router/meta_tests.rs index 2c2874c..0c1b3f9 100644 --- a/integration_tests/tests/tip_router/meta_tests.rs +++ b/integration_tests/tests/tip_router/meta_tests.rs @@ -42,7 +42,6 @@ mod tests { async fn test_intermission_test_ncn_functions() -> TestResult<()> { let mut fixture = TestBuilder::new().await; let mut tip_router_client = fixture.tip_router_client(); - let mut restaking_client = fixture.restaking_program_client(); const OPERATOR_COUNT: usize = 1; const VAULT_COUNT: usize = 1; @@ -52,11 +51,11 @@ mod tests { .await?; fixture.snapshot_test_ncn(&test_ncn).await?; - let slot = fixture.clock().await.slot; - let ncn_epoch = restaking_client.get_ncn_epoch(slot).await?; + let clock = fixture.clock().await; + let epoch = clock.epoch; let epoch_snapshot = tip_router_client - .get_epoch_snapshot(test_ncn.ncn_root.ncn_pubkey, ncn_epoch) + .get_epoch_snapshot(test_ncn.ncn_root.ncn_pubkey, epoch) .await?; assert!(epoch_snapshot.finalized()); @@ -64,7 +63,7 @@ mod tests { fixture.vote_test_ncn(&test_ncn).await?; let ballot_box = tip_router_client - .get_ballot_box(test_ncn.ncn_root.ncn_pubkey, ncn_epoch) + .get_ballot_box(test_ncn.ncn_root.ncn_pubkey, epoch) .await?; assert!(ballot_box.has_winning_ballot()); @@ -78,7 +77,6 @@ mod tests { async fn test_multiple_operators() -> TestResult<()> { let mut fixture = TestBuilder::new().await; let mut tip_router_client = fixture.tip_router_client(); - let mut restaking_client = fixture.restaking_program_client(); const OPERATOR_COUNT: usize = 10; const VAULT_COUNT: usize = 1; @@ -88,11 +86,11 @@ mod tests { .await?; fixture.snapshot_test_ncn(&test_ncn).await?; - let slot = fixture.clock().await.slot; - let ncn_epoch = restaking_client.get_ncn_epoch(slot).await?; + let clock = fixture.clock().await; + let epoch = clock.epoch; let epoch_snapshot = tip_router_client - .get_epoch_snapshot(test_ncn.ncn_root.ncn_pubkey, ncn_epoch) + .get_epoch_snapshot(test_ncn.ncn_root.ncn_pubkey, epoch) .await?; assert!(epoch_snapshot.finalized()); @@ -100,7 +98,7 @@ mod tests { fixture.vote_test_ncn(&test_ncn).await?; let ballot_box = tip_router_client - .get_ballot_box(test_ncn.ncn_root.ncn_pubkey, ncn_epoch) + .get_ballot_box(test_ncn.ncn_root.ncn_pubkey, epoch) .await?; assert!(ballot_box.has_winning_ballot()); @@ -114,7 +112,6 @@ mod tests { async fn test_multiple_vaults() -> TestResult<()> { let mut fixture = TestBuilder::new().await; let mut tip_router_client = fixture.tip_router_client(); - let mut restaking_client = fixture.restaking_program_client(); const OPERATOR_COUNT: usize = 1; const VAULT_COUNT: usize = 10; @@ -124,11 +121,11 @@ mod tests { .await?; fixture.snapshot_test_ncn(&test_ncn).await?; - let slot = fixture.clock().await.slot; - let ncn_epoch = restaking_client.get_ncn_epoch(slot).await?; + let clock = fixture.clock().await; + let epoch = clock.epoch; let epoch_snapshot = tip_router_client - .get_epoch_snapshot(test_ncn.ncn_root.ncn_pubkey, ncn_epoch) + .get_epoch_snapshot(test_ncn.ncn_root.ncn_pubkey, epoch) .await?; assert!(epoch_snapshot.finalized()); @@ -136,7 +133,7 @@ mod tests { fixture.vote_test_ncn(&test_ncn).await?; let ballot_box = tip_router_client - .get_ballot_box(test_ncn.ncn_root.ncn_pubkey, ncn_epoch) + .get_ballot_box(test_ncn.ncn_root.ncn_pubkey, epoch) .await?; assert!(ballot_box.has_winning_ballot()); @@ -150,7 +147,6 @@ mod tests { async fn test_multiple_operators_and_vaults() -> TestResult<()> { let mut fixture = TestBuilder::new().await; let mut tip_router_client = fixture.tip_router_client(); - let mut restaking_client = fixture.restaking_program_client(); const OPERATOR_COUNT: usize = 10; const VAULT_COUNT: usize = 10; @@ -160,11 +156,11 @@ mod tests { .await?; fixture.snapshot_test_ncn(&test_ncn).await?; - let slot = fixture.clock().await.slot; - let ncn_epoch = restaking_client.get_ncn_epoch(slot).await?; + let clock = fixture.clock().await; + let epoch = clock.epoch; let epoch_snapshot = tip_router_client - .get_epoch_snapshot(test_ncn.ncn_root.ncn_pubkey, ncn_epoch) + .get_epoch_snapshot(test_ncn.ncn_root.ncn_pubkey, epoch) .await?; assert!(epoch_snapshot.finalized()); @@ -172,7 +168,7 @@ mod tests { fixture.vote_test_ncn(&test_ncn).await?; let ballot_box = tip_router_client - .get_ballot_box(test_ncn.ncn_root.ncn_pubkey, ncn_epoch) + .get_ballot_box(test_ncn.ncn_root.ncn_pubkey, epoch) .await?; assert!(ballot_box.has_winning_ballot()); diff --git a/integration_tests/tests/tip_router/register_mint.rs b/integration_tests/tests/tip_router/register_mint.rs index 7f47ae0..f011e33 100644 --- a/integration_tests/tests/tip_router/register_mint.rs +++ b/integration_tests/tests/tip_router/register_mint.rs @@ -240,8 +240,9 @@ mod tests { ) .await?; + let epoch = fixture.clock().await.epoch; tip_router_client - .initialize_weight_table(ncn_root.ncn_pubkey, fixture.clock().await.slot) + .initialize_weight_table(ncn_root.ncn_pubkey, epoch) .await?; let result = tip_router_client diff --git a/integration_tests/tests/tip_router/set_tie_breaker.rs b/integration_tests/tests/tip_router/set_tie_breaker.rs index dde9af5..9e6fbef 100644 --- a/integration_tests/tests/tip_router/set_tie_breaker.rs +++ b/integration_tests/tests/tip_router/set_tie_breaker.rs @@ -17,13 +17,11 @@ mod tests { fixture.snapshot_test_ncn(&test_ncn).await?; let clock = fixture.clock().await; - let slot = clock.slot; - let restaking_config_account = tip_router_client.get_restaking_config().await?; - let ncn_epoch = slot / restaking_config_account.epoch_length(); + let epoch = clock.epoch; let ncn = test_ncn.ncn_root.ncn_pubkey; tip_router_client - .do_initialize_ballot_box(ncn, ncn_epoch) + .do_full_initialize_ballot_box(ncn, epoch) .await?; let meta_merkle_root = [1; 32]; @@ -34,10 +32,10 @@ mod tests { // Cast a vote so that this vote is one of the valid options // Gets to 50% consensus weight tip_router_client - .do_cast_vote(ncn, operator, operator_admin, meta_merkle_root, ncn_epoch) + .do_cast_vote(ncn, operator, operator_admin, meta_merkle_root, epoch) .await?; - let ballot_box = tip_router_client.get_ballot_box(ncn, ncn_epoch).await?; + let ballot_box = tip_router_client.get_ballot_box(ncn, epoch).await?; assert!(ballot_box.has_ballot(&Ballot::new(meta_merkle_root))); assert_eq!( ballot_box.slot_consensus_reached(), @@ -49,10 +47,10 @@ mod tests { fixture.warp_slot_incremental(1000000).await?; tip_router_client - .do_set_tie_breaker(ncn, meta_merkle_root, ncn_epoch) + .do_set_tie_breaker(ncn, meta_merkle_root, epoch) .await?; - let ballot_box = tip_router_client.get_ballot_box(ncn, ncn_epoch).await?; + let ballot_box = tip_router_client.get_ballot_box(ncn, epoch).await?; let ballot = Ballot::new(meta_merkle_root); assert!(ballot_box.has_ballot(&ballot)); diff --git a/integration_tests/tests/tip_router/set_tracked_mint_ncn_fee_group.rs b/integration_tests/tests/tip_router/set_tracked_mint_ncn_fee_group.rs index ec789ce..dd1341e 100644 --- a/integration_tests/tests/tip_router/set_tracked_mint_ncn_fee_group.rs +++ b/integration_tests/tests/tip_router/set_tracked_mint_ncn_fee_group.rs @@ -71,17 +71,12 @@ mod tests { .get_tracked_mints(ncn_root.ncn_pubkey) .await?; assert_eq!(tracked_mints.mint_count(), 1); - let current_slot = fixture.clock().await.slot; + let epoch = fixture.clock().await.epoch; let new_ncn_fee_group = NcnFeeGroup::new(NcnFeeGroupType::Reserved7); tip_router_client - .do_set_tracked_mint_ncn_fee_group( - ncn_root.ncn_pubkey, - 0, - new_ncn_fee_group, - current_slot, - ) + .do_set_tracked_mint_ncn_fee_group(ncn_root.ncn_pubkey, 0, new_ncn_fee_group, epoch) .await?; let tracked_mints = tip_router_client @@ -155,19 +150,13 @@ mod tests { ) .await?; + let epoch = fixture.clock().await.epoch; // Is Okay { - let current_slot = fixture.clock().await.slot; - let new_ncn_fee_group = NcnFeeGroup::new(NcnFeeGroupType::Reserved7); tip_router_client - .do_set_tracked_mint_ncn_fee_group( - ncn_root.ncn_pubkey, - 0, - new_ncn_fee_group, - current_slot, - ) + .do_set_tracked_mint_ncn_fee_group(ncn_root.ncn_pubkey, 0, new_ncn_fee_group, epoch) .await?; let tracked_mints = tip_router_client @@ -182,22 +171,15 @@ mod tests { } tip_router_client - .initialize_weight_table(ncn_root.ncn_pubkey, fixture.clock().await.slot) + .do_full_initialize_weight_table(ncn_root.ncn_pubkey, epoch) .await?; // Should fail { - let current_slot = fixture.clock().await.slot; - let new_ncn_fee_group = NcnFeeGroup::new(NcnFeeGroupType::Reserved5); let result = tip_router_client - .do_set_tracked_mint_ncn_fee_group( - ncn_root.ncn_pubkey, - 0, - new_ncn_fee_group, - current_slot, - ) + .do_set_tracked_mint_ncn_fee_group(ncn_root.ncn_pubkey, 0, new_ncn_fee_group, epoch) .await; assert!(result.is_err()); diff --git a/integration_tests/tests/tip_router/snapshot_vault_operator_delegation.rs b/integration_tests/tests/tip_router/snapshot_vault_operator_delegation.rs index b85083f..0f23d56 100644 --- a/integration_tests/tests/tip_router/snapshot_vault_operator_delegation.rs +++ b/integration_tests/tests/tip_router/snapshot_vault_operator_delegation.rs @@ -4,7 +4,7 @@ mod tests { use crate::fixtures::{test_builder::TestBuilder, TestResult}; #[tokio::test] - async fn test_initialize_operator_snapshot() -> TestResult<()> { + async fn test_snapshot_vault_operator_delegation() -> TestResult<()> { let mut fixture = TestBuilder::new().await; let mut vault_client = fixture.vault_program_client(); let mut tip_router_client = fixture.tip_router_client(); @@ -13,10 +13,10 @@ mod tests { fixture.warp_slot_incremental(1000).await?; - let slot = fixture.clock().await.slot; + let epoch = fixture.clock().await.epoch; tip_router_client - .do_initialize_weight_table(test_ncn.ncn_root.ncn_pubkey, slot) + .do_full_initialize_weight_table(test_ncn.ncn_root.ncn_pubkey, epoch) .await?; let ncn = test_ncn.ncn_root.ncn_pubkey; @@ -29,21 +29,21 @@ mod tests { let weight = 100; tip_router_client - .do_admin_update_weight_table(ncn, slot, mint, weight) + .do_admin_update_weight_table(ncn, epoch, mint, weight) .await?; tip_router_client - .do_initialize_epoch_snapshot(ncn, slot) + .do_initialize_epoch_snapshot(ncn, epoch) .await?; let operator = test_ncn.operators[0].operator_pubkey; tip_router_client - .do_initialize_operator_snapshot(operator, ncn, slot) + .do_full_initialize_operator_snapshot(operator, ncn, epoch) .await?; tip_router_client - .do_snapshot_vault_operator_delegation(vault_address, operator, ncn, slot) + .do_snapshot_vault_operator_delegation(vault_address, operator, ncn, epoch) .await?; Ok(()) diff --git a/program/src/cast_vote.rs b/program/src/cast_vote.rs index d292d02..8a186d8 100644 --- a/program/src/cast_vote.rs +++ b/program/src/cast_vote.rs @@ -41,7 +41,6 @@ pub fn process_cast_vote( operator_snapshot, false, )?; - let operator_data = operator.data.borrow(); let operator_account = Operator::try_from_slice_unchecked(&operator_data)?; diff --git a/program/src/distribute_base_ncn_reward_route.rs b/program/src/distribute_base_ncn_reward_route.rs index b5b7e75..e606cb2 100644 --- a/program/src/distribute_base_ncn_reward_route.rs +++ b/program/src/distribute_base_ncn_reward_route.rs @@ -1,12 +1,12 @@ use jito_bytemuck::AccountDeserialize; use jito_restaking_core::{config::Config, ncn::Ncn, operator::Operator}; use jito_tip_router_core::{ - base_reward_router::BaseRewardRouter, error::TipRouterError, loaders::load_ncn_epoch, - ncn_config::NcnConfig, ncn_fee_group::NcnFeeGroup, ncn_reward_router::NcnRewardRouter, + base_reward_router::BaseRewardRouter, error::TipRouterError, ncn_config::NcnConfig, + ncn_fee_group::NcnFeeGroup, ncn_reward_router::NcnRewardRouter, }; use solana_program::{ - account_info::AccountInfo, clock::Clock, entrypoint::ProgramResult, msg, - program_error::ProgramError, pubkey::Pubkey, sysvar::Sysvar, + account_info::AccountInfo, entrypoint::ProgramResult, msg, program_error::ProgramError, + pubkey::Pubkey, }; /// Can be backfilled for previous epochs @@ -14,7 +14,7 @@ pub fn process_distribute_base_ncn_reward_route( program_id: &Pubkey, accounts: &[AccountInfo], ncn_fee_group: u8, - first_slot_of_ncn_epoch: Option, + epoch: u64, ) -> ProgramResult { let [restaking_config, ncn_config, ncn, operator, base_reward_router, ncn_reward_router, restaking_program] = accounts @@ -31,18 +31,16 @@ pub fn process_distribute_base_ncn_reward_route( Ncn::load(restaking_program.key, ncn, false)?; Operator::load(restaking_program.key, operator, false)?; - let current_slot = Clock::get()?.slot; - let (ncn_epoch, _) = load_ncn_epoch(restaking_config, current_slot, first_slot_of_ncn_epoch)?; let ncn_fee_group = NcnFeeGroup::try_from(ncn_fee_group)?; NcnConfig::load(program_id, ncn.key, ncn_config, false)?; - BaseRewardRouter::load(program_id, ncn.key, ncn_epoch, base_reward_router, true)?; + BaseRewardRouter::load(program_id, ncn.key, epoch, base_reward_router, true)?; NcnRewardRouter::load( program_id, ncn_fee_group, operator.key, ncn.key, - ncn_epoch, + epoch, ncn_reward_router, true, )?; diff --git a/program/src/distribute_base_rewards.rs b/program/src/distribute_base_rewards.rs index d0c7633..c1a6209 100644 --- a/program/src/distribute_base_rewards.rs +++ b/program/src/distribute_base_rewards.rs @@ -2,11 +2,11 @@ use jito_bytemuck::AccountDeserialize; use jito_restaking_core::{config::Config, ncn::Ncn}; use jito_tip_router_core::{ base_fee_group::BaseFeeGroup, base_reward_router::BaseRewardRouter, error::TipRouterError, - loaders::load_ncn_epoch, ncn_config::NcnConfig, + ncn_config::NcnConfig, }; use solana_program::{ - account_info::AccountInfo, clock::Clock, entrypoint::ProgramResult, msg, - program_error::ProgramError, pubkey::Pubkey, sysvar::Sysvar, + account_info::AccountInfo, entrypoint::ProgramResult, msg, program_error::ProgramError, + pubkey::Pubkey, }; /// Can be backfilled for previous epochs @@ -14,7 +14,7 @@ pub fn process_distribute_base_rewards( program_id: &Pubkey, accounts: &[AccountInfo], base_fee_group: u8, - first_slot_of_ncn_epoch: Option, + epoch: u64, ) -> ProgramResult { let [restaking_config, ncn_config, ncn, base_reward_router, base_fee_wallet, restaking_program] = accounts @@ -35,12 +35,9 @@ pub fn process_distribute_base_rewards( Config::load(restaking_program.key, restaking_config, false)?; Ncn::load(restaking_program.key, ncn, false)?; - let current_slot = Clock::get()?.slot; - let (ncn_epoch, _) = load_ncn_epoch(restaking_config, current_slot, first_slot_of_ncn_epoch)?; - NcnConfig::load(program_id, ncn.key, ncn_config, false)?; - BaseRewardRouter::load(program_id, ncn.key, ncn_epoch, base_reward_router, true)?; + BaseRewardRouter::load(program_id, ncn.key, epoch, base_reward_router, true)?; let group = BaseFeeGroup::try_from(base_fee_group)?; diff --git a/program/src/distribute_ncn_operator_rewards.rs b/program/src/distribute_ncn_operator_rewards.rs index 3a6f854..2507653 100644 --- a/program/src/distribute_ncn_operator_rewards.rs +++ b/program/src/distribute_ncn_operator_rewards.rs @@ -1,12 +1,12 @@ use jito_bytemuck::AccountDeserialize; use jito_restaking_core::{config::Config, ncn::Ncn, operator::Operator}; use jito_tip_router_core::{ - error::TipRouterError, loaders::load_ncn_epoch, ncn_config::NcnConfig, - ncn_fee_group::NcnFeeGroup, ncn_reward_router::NcnRewardRouter, + error::TipRouterError, ncn_config::NcnConfig, ncn_fee_group::NcnFeeGroup, + ncn_reward_router::NcnRewardRouter, }; use solana_program::{ - account_info::AccountInfo, clock::Clock, entrypoint::ProgramResult, msg, - program_error::ProgramError, pubkey::Pubkey, sysvar::Sysvar, + account_info::AccountInfo, entrypoint::ProgramResult, msg, program_error::ProgramError, + pubkey::Pubkey, }; /// Can be backfilled for previous epochs @@ -14,7 +14,7 @@ pub fn process_distribute_ncn_operator_rewards( program_id: &Pubkey, accounts: &[AccountInfo], ncn_fee_group: u8, - first_slot_of_ncn_epoch: Option, + epoch: u64, ) -> ProgramResult { let [restaking_config, ncn_config, ncn, operator, ncn_reward_router, restaking_program] = accounts @@ -31,8 +31,6 @@ pub fn process_distribute_ncn_operator_rewards( Ncn::load(restaking_program.key, ncn, false)?; Operator::load(restaking_program.key, operator, true)?; - let current_slot = Clock::get()?.slot; - let (ncn_epoch, _) = load_ncn_epoch(restaking_config, current_slot, first_slot_of_ncn_epoch)?; let ncn_fee_group = NcnFeeGroup::try_from(ncn_fee_group)?; NcnConfig::load(program_id, ncn.key, ncn_config, false)?; @@ -41,7 +39,7 @@ pub fn process_distribute_ncn_operator_rewards( ncn_fee_group, operator.key, ncn.key, - ncn_epoch, + epoch, ncn_reward_router, true, )?; diff --git a/program/src/distribute_ncn_vault_rewards.rs b/program/src/distribute_ncn_vault_rewards.rs index 8ea4cc3..5e399dd 100644 --- a/program/src/distribute_ncn_vault_rewards.rs +++ b/program/src/distribute_ncn_vault_rewards.rs @@ -1,13 +1,13 @@ use jito_bytemuck::AccountDeserialize; use jito_restaking_core::{config::Config, ncn::Ncn, operator::Operator}; use jito_tip_router_core::{ - error::TipRouterError, loaders::load_ncn_epoch, ncn_config::NcnConfig, - ncn_fee_group::NcnFeeGroup, ncn_reward_router::NcnRewardRouter, + error::TipRouterError, ncn_config::NcnConfig, ncn_fee_group::NcnFeeGroup, + ncn_reward_router::NcnRewardRouter, }; use jito_vault_core::vault::Vault; use solana_program::{ - account_info::AccountInfo, clock::Clock, entrypoint::ProgramResult, - program_error::ProgramError, pubkey::Pubkey, sysvar::Sysvar, + account_info::AccountInfo, entrypoint::ProgramResult, program_error::ProgramError, + pubkey::Pubkey, }; /// Can be backfilled for previous epochs @@ -15,7 +15,7 @@ pub fn process_distribute_ncn_vault_rewards( program_id: &Pubkey, accounts: &[AccountInfo], ncn_fee_group: u8, - first_slot_of_ncn_epoch: Option, + epoch: u64, ) -> ProgramResult { let [restaking_config, ncn_config, ncn, operator, vault, ncn_reward_router] = accounts else { return Err(ProgramError::NotEnoughAccountKeys); @@ -29,8 +29,6 @@ pub fn process_distribute_ncn_vault_rewards( Operator::load(&restaking_program, operator, false)?; Vault::load(&vault_program, vault, true)?; - let current_slot = Clock::get()?.slot; - let (ncn_epoch, _) = load_ncn_epoch(restaking_config, current_slot, first_slot_of_ncn_epoch)?; let ncn_fee_group = NcnFeeGroup::try_from(ncn_fee_group)?; NcnConfig::load(program_id, ncn.key, ncn_config, false)?; @@ -39,7 +37,7 @@ pub fn process_distribute_ncn_vault_rewards( ncn_fee_group, operator.key, ncn.key, - ncn_epoch, + epoch, ncn_reward_router, true, )?; diff --git a/program/src/initialize_ballot_box.rs b/program/src/initialize_ballot_box.rs index 550fe19..fdf28e5 100644 --- a/program/src/initialize_ballot_box.rs +++ b/program/src/initialize_ballot_box.rs @@ -1,12 +1,13 @@ -use jito_bytemuck::{AccountDeserialize, Discriminator}; use jito_jsm_core::{ create_account, loader::{load_signer, load_system_account, load_system_program}, }; -use jito_tip_router_core::{ballot_box::BallotBox, ncn_config::NcnConfig}; +use jito_tip_router_core::{ + ballot_box::BallotBox, constants::MAX_REALLOC_BYTES, ncn_config::NcnConfig, +}; use solana_program::{ - account_info::AccountInfo, clock::Clock, entrypoint::ProgramResult, - program_error::ProgramError, pubkey::Pubkey, rent::Rent, sysvar::Sysvar, + account_info::AccountInfo, entrypoint::ProgramResult, program_error::ProgramError, + pubkey::Pubkey, rent::Rent, sysvar::Sysvar, }; pub fn process_initialize_ballot_box( @@ -40,17 +41,9 @@ pub fn process_initialize_ballot_box( system_program, program_id, &Rent::get()?, - 8_u64 - .checked_add(std::mem::size_of::() as u64) - .unwrap(), + MAX_REALLOC_BYTES, &ballot_box_seeds, )?; - let mut ballot_box_data = ballot_box.try_borrow_mut_data()?; - ballot_box_data[0] = BallotBox::DISCRIMINATOR; - let ballot_box_account = BallotBox::try_from_slice_unchecked_mut(&mut ballot_box_data)?; - - ballot_box_account.initialize(*ncn_account.key, epoch, ballot_box_bump, Clock::get()?.slot); - Ok(()) } diff --git a/program/src/initialize_base_reward_router.rs b/program/src/initialize_base_reward_router.rs index e7eeaa5..ec17348 100644 --- a/program/src/initialize_base_reward_router.rs +++ b/program/src/initialize_base_reward_router.rs @@ -1,22 +1,19 @@ -use std::mem::size_of; - -use jito_bytemuck::{AccountDeserialize, Discriminator}; use jito_jsm_core::{ create_account, loader::{load_signer, load_system_account, load_system_program}, }; use jito_restaking_core::{config::Config, ncn::Ncn}; -use jito_tip_router_core::{base_reward_router::BaseRewardRouter, loaders::load_ncn_epoch}; +use jito_tip_router_core::{base_reward_router::BaseRewardRouter, constants::MAX_REALLOC_BYTES}; use solana_program::{ - account_info::AccountInfo, clock::Clock, entrypoint::ProgramResult, msg, - program_error::ProgramError, pubkey::Pubkey, rent::Rent, sysvar::Sysvar, + account_info::AccountInfo, entrypoint::ProgramResult, msg, program_error::ProgramError, + pubkey::Pubkey, rent::Rent, sysvar::Sysvar, }; /// Can be backfilled for previous epochs pub fn process_initialize_base_reward_router( program_id: &Pubkey, accounts: &[AccountInfo], - first_slot_of_ncn_epoch: Option, + epoch: u64, ) -> ProgramResult { let [restaking_config, ncn, base_reward_router, payer, restaking_program, system_program] = accounts @@ -36,15 +33,12 @@ pub fn process_initialize_base_reward_router( load_system_program(system_program)?; load_signer(payer, true)?; - let current_slot = Clock::get()?.slot; - let (ncn_epoch, _) = load_ncn_epoch(restaking_config, current_slot, first_slot_of_ncn_epoch)?; - let (base_reward_router_pubkey, base_reward_router_bump, mut base_reward_router_seeds) = - BaseRewardRouter::find_program_address(program_id, ncn.key, ncn_epoch); + BaseRewardRouter::find_program_address(program_id, ncn.key, epoch); base_reward_router_seeds.push(vec![base_reward_router_bump]); if base_reward_router_pubkey.ne(base_reward_router.key) { - msg!("Incorrect epoch reward router PDA"); + msg!("Incorrect base reward router PDA"); return Err(ProgramError::InvalidAccountData); } @@ -52,7 +46,7 @@ pub fn process_initialize_base_reward_router( "Initializing Base Reward Router {} for NCN: {} at epoch: {}", base_reward_router.key, ncn.key, - ncn_epoch + epoch ); create_account( payer, @@ -60,19 +54,9 @@ pub fn process_initialize_base_reward_router( system_program, program_id, &Rent::get()?, - 8_u64 - .checked_add(size_of::() as u64) - .unwrap(), + MAX_REALLOC_BYTES, &base_reward_router_seeds, )?; - let mut base_reward_router_data = base_reward_router.try_borrow_mut_data()?; - base_reward_router_data[0] = BaseRewardRouter::DISCRIMINATOR; - let base_reward_router_account = - BaseRewardRouter::try_from_slice_unchecked_mut(&mut base_reward_router_data)?; - - *base_reward_router_account = - BaseRewardRouter::new(*ncn.key, ncn_epoch, base_reward_router_bump, current_slot); - Ok(()) } diff --git a/program/src/initialize_epoch_snapshot.rs b/program/src/initialize_epoch_snapshot.rs index 3c3ca6a..c94392b 100644 --- a/program/src/initialize_epoch_snapshot.rs +++ b/program/src/initialize_epoch_snapshot.rs @@ -5,8 +5,8 @@ use jito_jsm_core::{ }; use jito_restaking_core::{config::Config, ncn::Ncn}; use jito_tip_router_core::{ - epoch_snapshot::EpochSnapshot, error::TipRouterError, fees, loaders::load_ncn_epoch, - ncn_config::NcnConfig, tracked_mints::TrackedMints, weight_table::WeightTable, + epoch_snapshot::EpochSnapshot, error::TipRouterError, fees, ncn_config::NcnConfig, + tracked_mints::TrackedMints, weight_table::WeightTable, }; use solana_program::{ account_info::AccountInfo, clock::Clock, entrypoint::ProgramResult, msg, @@ -17,7 +17,7 @@ use solana_program::{ pub fn process_initialize_epoch_snapshot( program_id: &Pubkey, accounts: &[AccountInfo], - first_slot_of_ncn_epoch: Option, + epoch: u64, ) -> ProgramResult { let [ncn_config, restaking_config, ncn, tracked_mints, weight_table, epoch_snapshot, payer, restaking_program, system_program] = accounts @@ -41,7 +41,7 @@ pub fn process_initialize_epoch_snapshot( load_signer(payer, false)?; let current_slot = Clock::get()?.slot; - let (ncn_epoch, _) = load_ncn_epoch(restaking_config, current_slot, first_slot_of_ncn_epoch)?; + let ncn_epoch = epoch; WeightTable::load(program_id, weight_table, ncn, ncn_epoch, false)?; diff --git a/program/src/initialize_ncn_reward_router.rs b/program/src/initialize_ncn_reward_router.rs index 1387617..58e398b 100644 --- a/program/src/initialize_ncn_reward_router.rs +++ b/program/src/initialize_ncn_reward_router.rs @@ -6,9 +6,7 @@ use jito_jsm_core::{ loader::{load_signer, load_system_account, load_system_program}, }; use jito_restaking_core::{config::Config, ncn::Ncn, operator::Operator}; -use jito_tip_router_core::{ - loaders::load_ncn_epoch, ncn_fee_group::NcnFeeGroup, ncn_reward_router::NcnRewardRouter, -}; +use jito_tip_router_core::{ncn_fee_group::NcnFeeGroup, ncn_reward_router::NcnRewardRouter}; use solana_program::{ account_info::AccountInfo, clock::Clock, entrypoint::ProgramResult, msg, program_error::ProgramError, pubkey::Pubkey, rent::Rent, sysvar::Sysvar, @@ -19,7 +17,7 @@ pub fn process_initialize_ncn_reward_router( program_id: &Pubkey, accounts: &[AccountInfo], ncn_fee_group: u8, - first_slot_of_ncn_epoch: Option, + epoch: u64, ) -> ProgramResult { let [restaking_config, ncn, operator, ncn_reward_router, payer, restaking_program, system_program] = accounts @@ -43,7 +41,6 @@ pub fn process_initialize_ncn_reward_router( let ncn_fee_group = NcnFeeGroup::try_from(ncn_fee_group)?; let current_slot = Clock::get()?.slot; - let (ncn_epoch, _) = load_ncn_epoch(restaking_config, current_slot, first_slot_of_ncn_epoch)?; let (ncn_reward_router_pubkey, ncn_reward_router_bump, mut ncn_reward_router_seeds) = NcnRewardRouter::find_program_address( @@ -51,7 +48,7 @@ pub fn process_initialize_ncn_reward_router( ncn_fee_group, operator.key, ncn.key, - ncn_epoch, + epoch, ); ncn_reward_router_seeds.push(vec![ncn_reward_router_bump]); @@ -64,7 +61,7 @@ pub fn process_initialize_ncn_reward_router( "Initializing Epoch Reward Router {} for NCN: {} at epoch: {}", ncn_reward_router.key, ncn.key, - ncn_epoch + epoch ); create_account( payer, @@ -87,7 +84,7 @@ pub fn process_initialize_ncn_reward_router( ncn_fee_group, *operator.key, *ncn.key, - ncn_epoch, + epoch, ncn_reward_router_bump, current_slot, ); diff --git a/program/src/initialize_operator_snapshot.rs b/program/src/initialize_operator_snapshot.rs index 998f383..88ea647 100644 --- a/program/src/initialize_operator_snapshot.rs +++ b/program/src/initialize_operator_snapshot.rs @@ -1,4 +1,3 @@ -use jito_bytemuck::{AccountDeserialize, Discriminator}; use jito_jsm_core::{ create_account, loader::{load_signer, load_system_account, load_system_program}, @@ -7,21 +6,20 @@ use jito_restaking_core::{ config::Config, ncn::Ncn, ncn_operator_state::NcnOperatorState, operator::Operator, }; use jito_tip_router_core::{ + constants::MAX_REALLOC_BYTES, epoch_snapshot::{EpochSnapshot, OperatorSnapshot}, - loaders::load_ncn_epoch, ncn_config::NcnConfig, - stake_weight::StakeWeights, }; use solana_program::{ - account_info::AccountInfo, clock::Clock, entrypoint::ProgramResult, msg, - program_error::ProgramError, pubkey::Pubkey, rent::Rent, sysvar::Sysvar, + account_info::AccountInfo, entrypoint::ProgramResult, msg, program_error::ProgramError, + pubkey::Pubkey, rent::Rent, sysvar::Sysvar, }; /// Initializes an Operator Snapshot pub fn process_initialize_operator_snapshot( program_id: &Pubkey, accounts: &[AccountInfo], - first_slot_of_ncn_epoch: Option, + epoch: u64, ) -> ProgramResult { let [ncn_config, restaking_config, ncn, operator, ncn_operator_state, epoch_snapshot, operator_snapshot, payer, restaking_program, system_program] = accounts @@ -45,24 +43,19 @@ pub fn process_initialize_operator_snapshot( operator, false, )?; + EpochSnapshot::load(program_id, ncn.key, epoch, epoch_snapshot, true)?; load_system_account(operator_snapshot, true)?; load_system_program(system_program)?; //TODO check that it is not writable load_signer(payer, false)?; - let current_slot = Clock::get()?.slot; - let (ncn_epoch, ncn_epoch_length) = - load_ncn_epoch(restaking_config, current_slot, first_slot_of_ncn_epoch)?; - - EpochSnapshot::load(program_id, ncn.key, ncn_epoch, epoch_snapshot, true)?; - let (operator_snapshot_pubkey, operator_snapshot_bump, mut operator_snapshot_seeds) = - OperatorSnapshot::find_program_address(program_id, operator.key, ncn.key, ncn_epoch); + OperatorSnapshot::find_program_address(program_id, operator.key, ncn.key, epoch); operator_snapshot_seeds.push(vec![operator_snapshot_bump]); if operator_snapshot_pubkey.ne(operator_snapshot.key) { - msg!("Incorrect epoch snapshot PDA"); + msg!("Operator snapshot account is not at the correct PDA"); return Err(ProgramError::InvalidAccountData); } @@ -70,7 +63,7 @@ pub fn process_initialize_operator_snapshot( "Initializing Operator snapshot {} for NCN: {} at epoch: {}", epoch_snapshot.key, ncn.key, - ncn_epoch + epoch ); create_account( @@ -79,88 +72,9 @@ pub fn process_initialize_operator_snapshot( system_program, program_id, &Rent::get()?, - 8_u64 - .checked_add(std::mem::size_of::() as u64) - .unwrap(), + MAX_REALLOC_BYTES, &operator_snapshot_seeds, )?; - //TODO move to helper function - let (is_active, ncn_operator_index): (bool, u64) = { - let ncn_operator_state_data = ncn_operator_state.data.borrow(); - let ncn_operator_state_account = - NcnOperatorState::try_from_slice_unchecked(&ncn_operator_state_data)?; - - let ncn_operator_okay = ncn_operator_state_account - .ncn_opt_in_state - .is_active(current_slot, ncn_epoch_length); - - let operator_ncn_okay = ncn_operator_state_account - .operator_opt_in_state - .is_active(current_slot, ncn_epoch_length); - - let ncn_operator_index = ncn_operator_state_account.index(); - - (ncn_operator_okay && operator_ncn_okay, ncn_operator_index) - }; - - let vault_count = { - let epoch_snapshot_data = epoch_snapshot.data.borrow(); - let epoch_snapshot_account = EpochSnapshot::try_from_slice_unchecked(&epoch_snapshot_data)?; - epoch_snapshot_account.vault_count() - }; - - let (operator_fee_bps, operator_index): (u16, u64) = { - let operator_data = operator.data.borrow(); - let operator_account = Operator::try_from_slice_unchecked(&operator_data)?; - ( - operator_account.operator_fee_bps.into(), - operator_account.index(), - ) - }; - - let mut operator_snapshot_data: std::cell::RefMut<'_, &mut [u8]> = - operator_snapshot.try_borrow_mut_data()?; - operator_snapshot_data[0] = OperatorSnapshot::DISCRIMINATOR; - let operator_snapshot_account = - OperatorSnapshot::try_from_slice_unchecked_mut(&mut operator_snapshot_data)?; - - *operator_snapshot_account = if is_active { - OperatorSnapshot::new_active( - *operator.key, - *ncn.key, - ncn_epoch, - operator_snapshot_bump, - current_slot, - ncn_operator_index, - operator_index, - operator_fee_bps, - vault_count, - )? - } else { - OperatorSnapshot::new_inactive( - *operator.key, - *ncn.key, - ncn_epoch, - operator_snapshot_bump, - current_slot, - ncn_operator_index, - operator_index, - )? - }; - - // Increment operator registration for an inactive operator - if !is_active { - let mut epoch_snapshot_data = epoch_snapshot.try_borrow_mut_data()?; - let epoch_snapshot_account = - EpochSnapshot::try_from_slice_unchecked_mut(&mut epoch_snapshot_data)?; - - epoch_snapshot_account.increment_operator_registration( - current_slot, - 0, - &StakeWeights::default(), - )?; - } - Ok(()) } diff --git a/program/src/initialize_tracked_mints.rs b/program/src/initialize_tracked_mints.rs index 84bcd3b..bf30127 100644 --- a/program/src/initialize_tracked_mints.rs +++ b/program/src/initialize_tracked_mints.rs @@ -47,7 +47,7 @@ pub fn process_initialize_tracked_mints( tracked_mints_data[0] = TrackedMints::DISCRIMINATOR; let tracked_mints_account = TrackedMints::try_from_slice_unchecked_mut(&mut tracked_mints_data)?; - *tracked_mints_account = TrackedMints::new(*ncn_account.key, tracked_mints_bump); + tracked_mints_account.initialize(*ncn_account.key, tracked_mints_bump); Ok(()) } diff --git a/program/src/initialize_weight_table.rs b/program/src/initialize_weight_table.rs index 4f98643..90f2738 100644 --- a/program/src/initialize_weight_table.rs +++ b/program/src/initialize_weight_table.rs @@ -1,17 +1,15 @@ -use std::mem::size_of; - -use jito_bytemuck::{AccountDeserialize, Discriminator}; +use jito_bytemuck::AccountDeserialize; use jito_jsm_core::{ create_account, loader::{load_signer, load_system_account, load_system_program}, }; use jito_restaking_core::{config::Config, ncn::Ncn}; use jito_tip_router_core::{ - loaders::load_ncn_epoch, tracked_mints::TrackedMints, weight_table::WeightTable, + constants::MAX_REALLOC_BYTES, tracked_mints::TrackedMints, weight_table::WeightTable, }; use solana_program::{ - account_info::AccountInfo, clock::Clock, entrypoint::ProgramResult, msg, - program_error::ProgramError, pubkey::Pubkey, rent::Rent, sysvar::Sysvar, + account_info::AccountInfo, entrypoint::ProgramResult, msg, program_error::ProgramError, + pubkey::Pubkey, rent::Rent, sysvar::Sysvar, }; /// Initializes a Weight Table @@ -19,7 +17,7 @@ use solana_program::{ pub fn process_initialize_weight_table( program_id: &Pubkey, accounts: &[AccountInfo], - first_slot_of_ncn_epoch: Option, + epoch: u64, ) -> ProgramResult { let [restaking_config, tracked_mints, ncn, weight_table, payer, restaking_program, system_program] = accounts @@ -40,19 +38,16 @@ pub fn process_initialize_weight_table( load_system_program(system_program)?; load_signer(payer, true)?; - let current_slot = Clock::get()?.slot; - let (ncn_epoch, _) = load_ncn_epoch(restaking_config, current_slot, first_slot_of_ncn_epoch)?; - let vault_count = { let ncn_data = ncn.data.borrow(); let ncn = Ncn::try_from_slice_unchecked(&ncn_data)?; ncn.vault_count() }; - let (tracked_mint_count, unique_mints) = { + let tracked_mint_count = { let tracked_mints_data = tracked_mints.data.borrow(); let tracked_mints = TrackedMints::try_from_slice_unchecked(&tracked_mints_data)?; - (tracked_mints.mint_count(), tracked_mints.get_unique_mints()) + tracked_mints.mint_count() }; if vault_count != tracked_mint_count { @@ -61,7 +56,7 @@ pub fn process_initialize_weight_table( } let (weight_table_pubkey, weight_table_bump, mut weight_table_seeds) = - WeightTable::find_program_address(program_id, ncn.key, ncn_epoch); + WeightTable::find_program_address(program_id, ncn.key, epoch); weight_table_seeds.push(vec![weight_table_bump]); if weight_table_pubkey.ne(weight_table.key) { @@ -73,7 +68,7 @@ pub fn process_initialize_weight_table( "Initializing Weight Table {} for NCN: {} at epoch: {}", weight_table.key, ncn.key, - ncn_epoch + epoch ); create_account( payer, @@ -81,17 +76,9 @@ pub fn process_initialize_weight_table( system_program, program_id, &Rent::get()?, - 8_u64.checked_add(size_of::() as u64).unwrap(), + MAX_REALLOC_BYTES, &weight_table_seeds, )?; - let mut weight_table_data = weight_table.try_borrow_mut_data()?; - weight_table_data[0] = WeightTable::DISCRIMINATOR; - let weight_table_account = WeightTable::try_from_slice_unchecked_mut(&mut weight_table_data)?; - - *weight_table_account = WeightTable::new(*ncn.key, ncn_epoch, current_slot, weight_table_bump); - - weight_table_account.initalize_weight_table(&unique_mints)?; - Ok(()) } diff --git a/program/src/lib.rs b/program/src/lib.rs index 4e680be..2a746f1 100644 --- a/program/src/lib.rs +++ b/program/src/lib.rs @@ -12,6 +12,10 @@ mod initialize_ncn_reward_router; mod initialize_operator_snapshot; mod initialize_tracked_mints; mod initialize_weight_table; +mod realloc_ballot_box; +mod realloc_base_reward_router; +mod realloc_operator_snapshot; +mod realloc_weight_table; mod register_mint; mod route_base_rewards; mod route_ncn_rewards; @@ -46,7 +50,11 @@ use crate::{ initialize_ncn_reward_router::process_initialize_ncn_reward_router, initialize_operator_snapshot::process_initialize_operator_snapshot, initialize_tracked_mints::process_initialize_tracked_mints, - initialize_weight_table::process_initialize_weight_table, register_mint::process_register_mint, + initialize_weight_table::process_initialize_weight_table, + realloc_ballot_box::process_realloc_ballot_box, + realloc_base_reward_router::process_realloc_base_reward_router, + realloc_operator_snapshot::process_realloc_operator_snapshot, + realloc_weight_table::process_realloc_weight_table, register_mint::process_register_mint, route_base_rewards::process_route_base_rewards, route_ncn_rewards::process_route_ncn_rewards, set_config_fees::process_set_config_fees, set_merkle_root::process_set_merkle_root, set_tie_breaker::process_set_tie_breaker, @@ -104,116 +112,75 @@ pub fn process_instruction( msg!("Instruction: InitializeTrackedMints"); process_initialize_tracked_mints(program_id, accounts) } - TipRouterInstruction::InitializeWeightTable { - first_slot_of_ncn_epoch, - } => { + TipRouterInstruction::InitializeWeightTable { epoch } => { msg!("Instruction: InitializeWeightTable"); - process_initialize_weight_table(program_id, accounts, first_slot_of_ncn_epoch) + process_initialize_weight_table(program_id, accounts, epoch) } - TipRouterInstruction::InitializeEpochSnapshot { - first_slot_of_ncn_epoch, - } => { + TipRouterInstruction::InitializeEpochSnapshot { epoch } => { msg!("Instruction: InitializeEpochSnapshot"); - process_initialize_epoch_snapshot(program_id, accounts, first_slot_of_ncn_epoch) + process_initialize_epoch_snapshot(program_id, accounts, epoch) } - TipRouterInstruction::InitializeOperatorSnapshot { - first_slot_of_ncn_epoch, - } => { + TipRouterInstruction::InitializeOperatorSnapshot { epoch } => { msg!("Instruction: InitializeOperatorSnapshot"); - process_initialize_operator_snapshot(program_id, accounts, first_slot_of_ncn_epoch) + process_initialize_operator_snapshot(program_id, accounts, epoch) } - TipRouterInstruction::InitializeBaseRewardRouter { - first_slot_of_ncn_epoch, - } => { + TipRouterInstruction::InitializeBaseRewardRouter { epoch } => { msg!("Instruction: InitializeBaseRewardRouter"); - process_initialize_base_reward_router(program_id, accounts, first_slot_of_ncn_epoch) + process_initialize_base_reward_router(program_id, accounts, epoch) } TipRouterInstruction::InitializeNcnRewardRouter { ncn_fee_group, - first_slot_of_ncn_epoch, + epoch, } => { msg!("Instruction: InitializeNcnRewardRouter"); - process_initialize_ncn_reward_router( - program_id, - accounts, - ncn_fee_group, - first_slot_of_ncn_epoch, - ) + process_initialize_ncn_reward_router(program_id, accounts, ncn_fee_group, epoch) } // ------------------------------------------ // Cranks // ------------------------------------------ - TipRouterInstruction::SnapshotVaultOperatorDelegation { - first_slot_of_ncn_epoch, - } => { + TipRouterInstruction::SnapshotVaultOperatorDelegation { epoch } => { msg!("Instruction: SnapshotVaultOperatorDelegation"); - process_snapshot_vault_operator_delegation( - program_id, - accounts, - first_slot_of_ncn_epoch, - ) + process_snapshot_vault_operator_delegation(program_id, accounts, epoch) } - TipRouterInstruction::RouteBaseRewards { - first_slot_of_ncn_epoch, - } => { + TipRouterInstruction::RouteBaseRewards { epoch } => { msg!("Instruction: RouteBaseRewards"); - process_route_base_rewards(program_id, accounts, first_slot_of_ncn_epoch) + process_route_base_rewards(program_id, accounts, epoch) } TipRouterInstruction::RouteNcnRewards { ncn_fee_group, - first_slot_of_ncn_epoch, + epoch, } => { msg!("Instruction: RouteNcnRewards"); - process_route_ncn_rewards(program_id, accounts, ncn_fee_group, first_slot_of_ncn_epoch) + process_route_ncn_rewards(program_id, accounts, ncn_fee_group, epoch) } TipRouterInstruction::DistributeBaseRewards { base_fee_group, - first_slot_of_ncn_epoch, + epoch, } => { msg!("Instruction: DistributeBaseRewards"); - process_distribute_base_rewards( - program_id, - accounts, - base_fee_group, - first_slot_of_ncn_epoch, - ) + process_distribute_base_rewards(program_id, accounts, base_fee_group, epoch) } TipRouterInstruction::DistributeBaseNcnRewardRoute { ncn_fee_group, - first_slot_of_ncn_epoch, + epoch, } => { msg!("Instruction: DistributeBaseNcnRewardRoute"); - process_distribute_base_ncn_reward_route( - program_id, - accounts, - ncn_fee_group, - first_slot_of_ncn_epoch, - ) + process_distribute_base_ncn_reward_route(program_id, accounts, ncn_fee_group, epoch) } TipRouterInstruction::DistributeNcnOperatorRewards { ncn_fee_group, - first_slot_of_ncn_epoch, + epoch, } => { msg!("Instruction: DistributeNcnOperatorRewards"); - process_distribute_ncn_operator_rewards( - program_id, - accounts, - ncn_fee_group, - first_slot_of_ncn_epoch, - ) + process_distribute_ncn_operator_rewards(program_id, accounts, ncn_fee_group, epoch) } TipRouterInstruction::DistributeNcnVaultRewards { ncn_fee_group, - first_slot_of_ncn_epoch, + epoch, } => { msg!("Instruction: DistributeNcnVaultRewards"); - process_distribute_ncn_vault_rewards( - program_id, - accounts, - ncn_fee_group, - first_slot_of_ncn_epoch, - ) + process_distribute_ncn_vault_rewards(program_id, accounts, ncn_fee_group, epoch) } // ------------------------------------------ // Update @@ -293,5 +260,21 @@ pub fn process_instruction( msg!("Instruction: SetTieBreaker"); process_set_tie_breaker(program_id, accounts, meta_merkle_root, epoch) } + TipRouterInstruction::ReallocBallotBox { epoch } => { + msg!("Instruction: ReallocBallotBox"); + process_realloc_ballot_box(program_id, accounts, epoch) + } + TipRouterInstruction::ReallocOperatorSnapshot { epoch } => { + msg!("Instruction: ReallocOperatorSnapshot"); + process_realloc_operator_snapshot(program_id, accounts, epoch) + } + TipRouterInstruction::ReallocBaseRewardRouter { epoch } => { + msg!("Instruction: ReallocBaseRewardRouter"); + process_realloc_base_reward_router(program_id, accounts, epoch) + } + TipRouterInstruction::ReallocWeightTable { epoch } => { + msg!("Instruction: ReallocWeightTable"); + process_realloc_weight_table(program_id, accounts, epoch) + } } } diff --git a/program/src/realloc_ballot_box.rs b/program/src/realloc_ballot_box.rs new file mode 100644 index 0000000..919eaf1 --- /dev/null +++ b/program/src/realloc_ballot_box.rs @@ -0,0 +1,56 @@ +use jito_bytemuck::{AccountDeserialize, Discriminator}; +use jito_jsm_core::{ + loader::{load_signer, load_system_program}, + realloc, +}; +use jito_tip_router_core::{ballot_box::BallotBox, ncn_config::NcnConfig, utils::get_new_size}; +use solana_program::{ + account_info::AccountInfo, clock::Clock, entrypoint::ProgramResult, msg, + program_error::ProgramError, pubkey::Pubkey, rent::Rent, sysvar::Sysvar, +}; + +/// Reallocates the ballot box account to its full size. +/// This is needed due to Solana's account size limits during initialization. +pub fn process_realloc_ballot_box( + program_id: &Pubkey, + accounts: &[AccountInfo], + epoch: u64, +) -> ProgramResult { + let [ncn_config, ballot_box, ncn, payer, system_program] = accounts else { + return Err(ProgramError::NotEnoughAccountKeys); + }; + + load_system_program(system_program)?; + load_signer(payer, false)?; + NcnConfig::load(program_id, ncn.key, ncn_config, false)?; + + let (ballot_box_pda, ballot_box_bump, _) = + BallotBox::find_program_address(program_id, ncn.key, epoch); + + if ballot_box_pda != *ballot_box.key { + msg!("Ballot box account is not at the correct PDA"); + return Err(ProgramError::InvalidAccountData); + } + + if ballot_box.data_len() < BallotBox::SIZE { + let new_size = get_new_size(ballot_box.data_len(), BallotBox::SIZE)?; + msg!( + "Reallocating ballot box from {} bytes to {} bytes", + ballot_box.data_len(), + new_size + ); + realloc(ballot_box, new_size, payer, &Rent::get()?)?; + } + + let should_initialize = ballot_box.data_len() >= BallotBox::SIZE + && ballot_box.try_borrow_data()?[0] != BallotBox::DISCRIMINATOR; + + if should_initialize { + let mut ballot_box_data = ballot_box.try_borrow_mut_data()?; + ballot_box_data[0] = BallotBox::DISCRIMINATOR; + let ballot_box_account = BallotBox::try_from_slice_unchecked_mut(&mut ballot_box_data)?; + ballot_box_account.initialize(*ncn.key, epoch, ballot_box_bump, Clock::get()?.slot); + } + + Ok(()) +} diff --git a/program/src/realloc_base_reward_router.rs b/program/src/realloc_base_reward_router.rs new file mode 100644 index 0000000..04adbf7 --- /dev/null +++ b/program/src/realloc_base_reward_router.rs @@ -0,0 +1,63 @@ +use jito_bytemuck::{AccountDeserialize, Discriminator}; +use jito_jsm_core::{ + loader::{load_signer, load_system_program}, + realloc, +}; +use jito_tip_router_core::{ + base_reward_router::BaseRewardRouter, ncn_config::NcnConfig, utils::get_new_size, +}; +use solana_program::{ + account_info::AccountInfo, clock::Clock, entrypoint::ProgramResult, msg, + program_error::ProgramError, pubkey::Pubkey, rent::Rent, sysvar::Sysvar, +}; + +pub fn process_realloc_base_reward_router( + program_id: &Pubkey, + accounts: &[AccountInfo], + epoch: u64, +) -> ProgramResult { + let [ncn_config, base_reward_router, ncn, payer, system_program] = accounts else { + return Err(ProgramError::NotEnoughAccountKeys); + }; + + load_system_program(system_program)?; + load_signer(payer, false)?; + NcnConfig::load(program_id, ncn.key, ncn_config, false)?; + + let (base_reward_router_pda, base_reward_router_bump, _) = + BaseRewardRouter::find_program_address(program_id, ncn.key, epoch); + + if base_reward_router_pda != *base_reward_router.key { + msg!("Base reward router account is not at the correct PDA"); + return Err(ProgramError::InvalidAccountData); + } + + if base_reward_router.data_len() < BaseRewardRouter::SIZE { + let new_size = get_new_size(base_reward_router.data_len(), BaseRewardRouter::SIZE)?; + msg!( + "Reallocating base reward router from {} bytes to {} bytes", + base_reward_router.data_len(), + new_size + ); + realloc(base_reward_router, new_size, payer, &Rent::get()?)?; + } + + let should_initialize = base_reward_router.data_len() >= BaseRewardRouter::SIZE + && base_reward_router.try_borrow_data()?[0] != BaseRewardRouter::DISCRIMINATOR; + + if should_initialize { + let mut base_reward_router_data = base_reward_router.try_borrow_mut_data()?; + base_reward_router_data[0] = BaseRewardRouter::DISCRIMINATOR; + let base_reward_router_account = + BaseRewardRouter::try_from_slice_unchecked_mut(&mut base_reward_router_data)?; + + base_reward_router_account.initialize( + *ncn.key, + epoch, + base_reward_router_bump, + Clock::get()?.slot, + ); + } + + Ok(()) +} diff --git a/program/src/realloc_operator_snapshot.rs b/program/src/realloc_operator_snapshot.rs new file mode 100644 index 0000000..63077e6 --- /dev/null +++ b/program/src/realloc_operator_snapshot.rs @@ -0,0 +1,146 @@ +use jito_bytemuck::{AccountDeserialize, Discriminator}; +use jito_jsm_core::{ + loader::{load_signer, load_system_program}, + realloc, +}; +use jito_restaking_core::{ + config::Config, ncn::Ncn, ncn_operator_state::NcnOperatorState, operator::Operator, +}; +use jito_tip_router_core::{ + epoch_snapshot::{EpochSnapshot, OperatorSnapshot}, + loaders::load_ncn_epoch, + ncn_config::NcnConfig, + stake_weight::StakeWeights, + utils::get_new_size, +}; +use solana_program::{ + account_info::AccountInfo, clock::Clock, entrypoint::ProgramResult, msg, + program_error::ProgramError, pubkey::Pubkey, rent::Rent, sysvar::Sysvar, +}; + +pub fn process_realloc_operator_snapshot( + program_id: &Pubkey, + accounts: &[AccountInfo], + epoch: u64, +) -> ProgramResult { + let [ncn_config, restaking_config, ncn, operator, ncn_operator_state, epoch_snapshot, operator_snapshot, payer, restaking_program, system_program] = + accounts + else { + return Err(ProgramError::NotEnoughAccountKeys); + }; + + if restaking_program.key.ne(&jito_restaking_program::id()) { + msg!("Incorrect restaking program ID"); + return Err(ProgramError::InvalidAccountData); + } + + NcnConfig::load(program_id, ncn.key, ncn_config, false)?; + Config::load(restaking_program.key, restaking_config, false)?; + Ncn::load(restaking_program.key, ncn, false)?; + Operator::load(restaking_program.key, operator, false)?; + NcnOperatorState::load( + restaking_program.key, + ncn_operator_state, + ncn, + operator, + false, + )?; + EpochSnapshot::load(program_id, ncn.key, epoch, epoch_snapshot, true)?; + + load_system_program(system_program)?; + load_signer(payer, false)?; + + let (operator_snapshot_pda, operator_snapshot_bump, _) = + OperatorSnapshot::find_program_address(program_id, operator.key, ncn.key, epoch); + + if operator_snapshot_pda != *operator_snapshot.key { + msg!("Operator snapshot account is not at the correct PDA"); + return Err(ProgramError::InvalidAccountData); + } + + if operator_snapshot.data_len() < OperatorSnapshot::SIZE { + let new_size = get_new_size(operator_snapshot.data_len(), OperatorSnapshot::SIZE)?; + msg!( + "Reallocating operator snapshot from {} bytes to {} bytes", + operator_snapshot.data_len(), + new_size + ); + realloc(operator_snapshot, new_size, payer, &Rent::get()?)?; + } + + let should_initialize = operator_snapshot.data_len() >= OperatorSnapshot::SIZE + && operator_snapshot.try_borrow_data()?[0] != OperatorSnapshot::DISCRIMINATOR; + + if should_initialize { + let current_slot = Clock::get()?.slot; + let (_, ncn_epoch_length) = load_ncn_epoch(restaking_config, current_slot, None)?; + + //TODO move to helper function + let (is_active, ncn_operator_index): (bool, u64) = { + let ncn_operator_state_data = ncn_operator_state.data.borrow(); + let ncn_operator_state_account = + NcnOperatorState::try_from_slice_unchecked(&ncn_operator_state_data)?; + + let ncn_operator_okay = ncn_operator_state_account + .ncn_opt_in_state + .is_active(current_slot, ncn_epoch_length); + + let operator_ncn_okay = ncn_operator_state_account + .operator_opt_in_state + .is_active(current_slot, ncn_epoch_length); + + let ncn_operator_index = ncn_operator_state_account.index(); + + (ncn_operator_okay && operator_ncn_okay, ncn_operator_index) + }; + + let vault_count = { + let epoch_snapshot_data = epoch_snapshot.data.borrow(); + let epoch_snapshot_account = + EpochSnapshot::try_from_slice_unchecked(&epoch_snapshot_data)?; + epoch_snapshot_account.vault_count() + }; + + let (operator_fee_bps, operator_index): (u16, u64) = { + let operator_data = operator.data.borrow(); + let operator_account = Operator::try_from_slice_unchecked(&operator_data)?; + ( + operator_account.operator_fee_bps.into(), + operator_account.index(), + ) + }; + + let mut operator_snapshot_data = operator_snapshot.try_borrow_mut_data()?; + operator_snapshot_data[0] = OperatorSnapshot::DISCRIMINATOR; + let operator_snapshot_account = + OperatorSnapshot::try_from_slice_unchecked_mut(&mut operator_snapshot_data)?; + + operator_snapshot_account.initialize( + *operator.key, + *ncn.key, + epoch, + operator_snapshot_bump, + current_slot, + is_active, + ncn_operator_index, + operator_index, + operator_fee_bps, + vault_count, + )?; + + // Increment operator registration for an inactive operator + if !is_active { + let mut epoch_snapshot_data = epoch_snapshot.try_borrow_mut_data()?; + let epoch_snapshot_account = + EpochSnapshot::try_from_slice_unchecked_mut(&mut epoch_snapshot_data)?; + + epoch_snapshot_account.increment_operator_registration( + current_slot, + 0, + &StakeWeights::default(), + )?; + } + } + + Ok(()) +} diff --git a/program/src/realloc_weight_table.rs b/program/src/realloc_weight_table.rs new file mode 100644 index 0000000..8c59aca --- /dev/null +++ b/program/src/realloc_weight_table.rs @@ -0,0 +1,72 @@ +use jito_bytemuck::{AccountDeserialize, Discriminator}; +use jito_jsm_core::{ + loader::{load_signer, load_system_program}, + realloc, +}; +use jito_tip_router_core::{ + ncn_config::NcnConfig, tracked_mints::TrackedMints, utils::get_new_size, + weight_table::WeightTable, +}; +use solana_program::{ + account_info::AccountInfo, clock::Clock, entrypoint::ProgramResult, msg, + program_error::ProgramError, pubkey::Pubkey, rent::Rent, sysvar::Sysvar, +}; + +pub fn process_realloc_weight_table( + program_id: &Pubkey, + accounts: &[AccountInfo], + epoch: u64, +) -> ProgramResult { + let [ncn_config, weight_table, ncn, tracked_mints, payer, system_program] = accounts else { + return Err(ProgramError::NotEnoughAccountKeys); + }; + + load_system_program(system_program)?; + load_signer(payer, false)?; + NcnConfig::load(program_id, ncn.key, ncn_config, false)?; + TrackedMints::load(program_id, ncn.key, tracked_mints, false)?; + + let (weight_table_pda, weight_table_bump, _) = + WeightTable::find_program_address(program_id, ncn.key, epoch); + + if weight_table_pda != *weight_table.key { + msg!("Weight table account is not at the correct PDA"); + return Err(ProgramError::InvalidAccountData); + } + + if weight_table.data_len() < WeightTable::SIZE { + let new_size = get_new_size(weight_table.data_len(), WeightTable::SIZE)?; + msg!( + "Reallocating weight table from {} bytes to {} bytes", + weight_table.data_len(), + new_size + ); + realloc(weight_table, new_size, payer, &Rent::get()?)?; + } + + let should_initialize = weight_table.data_len() >= WeightTable::SIZE + && weight_table.try_borrow_data()?[0] != WeightTable::DISCRIMINATOR; + + if should_initialize { + let unique_mints = { + let tracked_mints_data = tracked_mints.data.borrow(); + let tracked_mints = TrackedMints::try_from_slice_unchecked(&tracked_mints_data)?; + tracked_mints.get_unique_mints() + }; + + let mut weight_table_data = weight_table.try_borrow_mut_data()?; + weight_table_data[0] = WeightTable::DISCRIMINATOR; + let weight_table_account = + WeightTable::try_from_slice_unchecked_mut(&mut weight_table_data)?; + + weight_table_account.initialize( + *ncn.key, + epoch, + Clock::get()?.slot, + weight_table_bump, + &unique_mints, + )?; + } + + Ok(()) +} diff --git a/program/src/register_mint.rs b/program/src/register_mint.rs index 9e0c7e3..28af9ff 100644 --- a/program/src/register_mint.rs +++ b/program/src/register_mint.rs @@ -39,16 +39,14 @@ pub fn process_register_mint(program_id: &Pubkey, accounts: &[AccountInfo]) -> P Config::try_from_slice_unchecked(&restaking_config_data)?.epoch_length() }; - let slot = Clock::get()?.slot; - - let ncn_epoch = slot - .checked_div(epoch_length) - .ok_or(TipRouterError::DenominatorIsZero)?; + let clock = Clock::get()?; + let slot = clock.slot; + let epoch = clock.epoch; // Once tracked_mints.mint_count() == ncn.vault_count, the weight table can be initialized // Once the weight table is initialized, you can't add any more mints if weight_table.owner.eq(&system_program::ID) { - let expected_pubkey = WeightTable::find_program_address(program_id, ncn.key, ncn_epoch).0; + let expected_pubkey = WeightTable::find_program_address(program_id, ncn.key, epoch).0; if weight_table.key.ne(&expected_pubkey) { msg!("Weight table incorrect PDA"); return Err(ProgramError::InvalidAccountData); @@ -57,7 +55,7 @@ pub fn process_register_mint(program_id: &Pubkey, accounts: &[AccountInfo]) -> P } if weight_table.owner.eq(program_id) { - WeightTable::load(program_id, weight_table, ncn, ncn_epoch, false)?; + WeightTable::load(program_id, weight_table, ncn, epoch, false)?; return Err(TipRouterError::TrackedMintsLocked.into()); } diff --git a/program/src/route_base_rewards.rs b/program/src/route_base_rewards.rs index 1be3b1a..ac29ece 100644 --- a/program/src/route_base_rewards.rs +++ b/program/src/route_base_rewards.rs @@ -2,18 +2,17 @@ use jito_bytemuck::AccountDeserialize; use jito_restaking_core::{config::Config, ncn::Ncn}; use jito_tip_router_core::{ ballot_box::BallotBox, base_reward_router::BaseRewardRouter, epoch_snapshot::EpochSnapshot, - loaders::load_ncn_epoch, }; use solana_program::{ - account_info::AccountInfo, clock::Clock, entrypoint::ProgramResult, msg, - program_error::ProgramError, pubkey::Pubkey, rent::Rent, sysvar::Sysvar, + account_info::AccountInfo, entrypoint::ProgramResult, msg, program_error::ProgramError, + pubkey::Pubkey, rent::Rent, sysvar::Sysvar, }; /// Can be backfilled for previous epochs pub fn process_route_base_rewards( program_id: &Pubkey, accounts: &[AccountInfo], - first_slot_of_ncn_epoch: Option, + epoch: u64, ) -> ProgramResult { let [restaking_config, ncn, epoch_snapshot, ballot_box, base_reward_router, restaking_program] = accounts @@ -29,12 +28,9 @@ pub fn process_route_base_rewards( Config::load(restaking_program.key, restaking_config, false)?; Ncn::load(restaking_program.key, ncn, false)?; - let current_slot = Clock::get()?.slot; - let (ncn_epoch, _) = load_ncn_epoch(restaking_config, current_slot, first_slot_of_ncn_epoch)?; - - EpochSnapshot::load(program_id, ncn.key, ncn_epoch, epoch_snapshot, false)?; - BaseRewardRouter::load(program_id, ncn.key, ncn_epoch, base_reward_router, true)?; - BallotBox::load(program_id, ncn.key, ncn_epoch, ballot_box, false)?; + EpochSnapshot::load(program_id, ncn.key, epoch, epoch_snapshot, false)?; + BaseRewardRouter::load(program_id, ncn.key, epoch, base_reward_router, true)?; + BallotBox::load(program_id, ncn.key, epoch, ballot_box, false)?; let epoch_snapshot_data = epoch_snapshot.try_borrow_data()?; let epoch_snapshot_account = EpochSnapshot::try_from_slice_unchecked(&epoch_snapshot_data)?; diff --git a/program/src/route_ncn_rewards.rs b/program/src/route_ncn_rewards.rs index 2852585..3b6278f 100644 --- a/program/src/route_ncn_rewards.rs +++ b/program/src/route_ncn_rewards.rs @@ -1,11 +1,11 @@ use jito_bytemuck::AccountDeserialize; use jito_restaking_core::{config::Config, ncn::Ncn, operator::Operator}; use jito_tip_router_core::{ - epoch_snapshot::OperatorSnapshot, loaders::load_ncn_epoch, ncn_fee_group::NcnFeeGroup, + epoch_snapshot::OperatorSnapshot, ncn_fee_group::NcnFeeGroup, ncn_reward_router::NcnRewardRouter, }; use solana_program::{ - account_info::AccountInfo, clock::Clock, entrypoint::ProgramResult, msg, + account_info::AccountInfo, entrypoint::ProgramResult, log::sol_log_compute_units, msg, program_error::ProgramError, pubkey::Pubkey, rent::Rent, sysvar::Sysvar, }; @@ -14,7 +14,7 @@ pub fn process_route_ncn_rewards( program_id: &Pubkey, accounts: &[AccountInfo], ncn_fee_group: u8, - first_slot_of_ncn_epoch: Option, + epoch: u64, ) -> ProgramResult { let [restaking_config, ncn, operator, operator_snapshot, ncn_reward_router, restaking_program] = accounts @@ -31,15 +31,13 @@ pub fn process_route_ncn_rewards( Ncn::load(restaking_program.key, ncn, false)?; Operator::load(restaking_program.key, operator, false)?; - let current_slot = Clock::get()?.slot; - let (ncn_epoch, _) = load_ncn_epoch(restaking_config, current_slot, first_slot_of_ncn_epoch)?; let ncn_fee_group = NcnFeeGroup::try_from(ncn_fee_group)?; OperatorSnapshot::load( program_id, operator.key, ncn.key, - ncn_epoch, + epoch, operator_snapshot, false, )?; @@ -48,7 +46,7 @@ pub fn process_route_ncn_rewards( ncn_fee_group, operator.key, ncn.key, - ncn_epoch, + epoch, ncn_reward_router, true, )?; diff --git a/program/src/set_tracked_mint_ncn_fee_group.rs b/program/src/set_tracked_mint_ncn_fee_group.rs index 0fdf3f2..b40fc14 100644 --- a/program/src/set_tracked_mint_ncn_fee_group.rs +++ b/program/src/set_tracked_mint_ncn_fee_group.rs @@ -44,21 +44,12 @@ pub fn process_set_tracked_mint_ncn_fee_group( } } - let epoch_length = { - let restaking_config_data = restaking_config.data.borrow(); - Config::try_from_slice_unchecked(&restaking_config_data)?.epoch_length() - }; - - let slot = Clock::get()?.slot; - - let ncn_epoch = slot - .checked_div(epoch_length) - .ok_or(TipRouterError::DenominatorIsZero)?; + let epoch = Clock::get()?.epoch; // Once tracked_mints.mint_count() == ncn.vault_count, the weight table can be initialized // Once the weight table is initialized, you can't add any more mints if weight_table.owner.eq(&system_program::ID) { - let expected_pubkey = WeightTable::find_program_address(program_id, ncn.key, ncn_epoch).0; + let expected_pubkey = WeightTable::find_program_address(program_id, ncn.key, epoch).0; if weight_table.key.ne(&expected_pubkey) { msg!("Weight table incorrect PDA"); return Err(ProgramError::InvalidAccountData); @@ -67,7 +58,7 @@ pub fn process_set_tracked_mint_ncn_fee_group( } if weight_table.owner.eq(program_id) { - WeightTable::load(program_id, weight_table, ncn, ncn_epoch, false)?; + WeightTable::load(program_id, weight_table, ncn, epoch, false)?; return Err(TipRouterError::TrackedMintsLocked.into()); } diff --git a/program/src/snapshot_vault_operator_delegation.rs b/program/src/snapshot_vault_operator_delegation.rs index dda4afa..7cb3055 100644 --- a/program/src/snapshot_vault_operator_delegation.rs +++ b/program/src/snapshot_vault_operator_delegation.rs @@ -22,7 +22,7 @@ use solana_program::{ pub fn process_snapshot_vault_operator_delegation( program_id: &Pubkey, accounts: &[AccountInfo], - first_slot_of_ncn_epoch: Option, + epoch: u64, ) -> ProgramResult { let [ncn_config, restaking_config, tracked_mints, ncn, operator, vault, vault_ncn_ticket, ncn_vault_ticket, vault_operator_delegation, weight_table, epoch_snapshot, operator_snapshot, vault_program, restaking_program] = accounts @@ -67,17 +67,16 @@ pub fn process_snapshot_vault_operator_delegation( } let current_slot = Clock::get()?.slot; - let (ncn_epoch, ncn_epoch_length) = - load_ncn_epoch(restaking_config, current_slot, first_slot_of_ncn_epoch)?; + let (_, ncn_epoch_length) = load_ncn_epoch(restaking_config, current_slot, None)?; TrackedMints::load(program_id, ncn.key, tracked_mints, false)?; - WeightTable::load(program_id, weight_table, ncn, ncn_epoch, false)?; - EpochSnapshot::load(program_id, ncn.key, ncn_epoch, epoch_snapshot, true)?; + WeightTable::load(program_id, weight_table, ncn, epoch, false)?; + EpochSnapshot::load(program_id, ncn.key, epoch, epoch_snapshot, true)?; OperatorSnapshot::load( program_id, operator.key, ncn.key, - ncn_epoch, + epoch, operator_snapshot, true, )?;